project-loop-harness 0.3.0__tar.gz → 0.3.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 (303) hide show
  1. {project_loop_harness-0.3.0/src/project_loop_harness.egg-info → project_loop_harness-0.3.1}/PKG-INFO +28 -1
  2. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/README.md +27 -0
  3. project_loop_harness-0.3.1/agent-tasks/0116-receipt-link-agreement-validation.md +163 -0
  4. project_loop_harness-0.3.1/agent-tasks/0117-markdown-target-refresh-command.md +76 -0
  5. project_loop_harness-0.3.1/agent-tasks/0118-canonical-target-bound-handoff-docs.md +64 -0
  6. project_loop_harness-0.3.1/agent-tasks/0119-context-check-preflight.md +145 -0
  7. project_loop_harness-0.3.1/agent-tasks/0120-pcl-finish-terminal-closeout.md +140 -0
  8. project_loop_harness-0.3.1/agent-tasks/0121-human-gate-japanese-guidance.md +61 -0
  9. project_loop_harness-0.3.1/agent-tasks/0122-feature-coverage-noop.md +80 -0
  10. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/README.md +18 -5
  11. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/adoption-guide.md +19 -0
  12. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/code-context.md +10 -0
  13. project_loop_harness-0.3.1/docs/context-check.md +74 -0
  14. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/context-pack.md +6 -0
  15. project_loop_harness-0.3.1/docs/finish.md +75 -0
  16. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/release-notes/v0.3.0.md +17 -4
  17. project_loop_harness-0.3.1/docs/release-notes/v0.3.1.md +89 -0
  18. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/pyproject.toml +1 -1
  19. project_loop_harness-0.3.1/src/pcl/__init__.py +1 -0
  20. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/cli.py +129 -1
  21. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/commands.py +308 -78
  22. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/context.py +287 -4
  23. project_loop_harness-0.3.1/src/pcl/context_binding.py +20 -0
  24. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/locales.py +56 -0
  25. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/validators.py +52 -1
  26. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/workflows.py +37 -0
  27. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1/src/project_loop_harness.egg-info}/PKG-INFO +28 -1
  28. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/SOURCES.txt +13 -0
  29. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/fixtures/context_pack_code_context_contract_v0.json +107 -0
  30. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_context.py +126 -3
  31. project_loop_harness-0.3.1/tests/test_context_check.py +517 -0
  32. project_loop_harness-0.3.1/tests/test_finish.py +222 -0
  33. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_next_actions.py +62 -0
  34. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_validation.py +117 -0
  35. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_workflows.py +96 -0
  36. project_loop_harness-0.3.0/src/pcl/__init__.py +0 -1
  37. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/LICENSE +0 -0
  38. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/MANIFEST.in +0 -0
  39. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/Makefile +0 -0
  40. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0001-hardening-cli.md +0 -0
  41. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0002-db-migrations.md +0 -0
  42. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0003-workflow-runner.md +0 -0
  43. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0004-dashboard-renderer.md +0 -0
  44. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0005-agent-integration.md +0 -0
  45. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0006-codex-plugin.md +0 -0
  46. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0007-mcp-server.md +0 -0
  47. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0008-loop-lifecycle.md +0 -0
  48. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0009-defect-lifecycle.md +0 -0
  49. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0010-reporting-evidence.md +0 -0
  50. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0011-validation-invariants.md +0 -0
  51. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0012-audit-log-integrity.md +0 -0
  52. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0013-validation-diagnostics.md +0 -0
  53. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0014-escalation-lifecycle.md +0 -0
  54. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0015-decision-lifecycle.md +0 -0
  55. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0016-escalation-decision-linkage.md +0 -0
  56. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0017-next-action-guided-loop.md +0 -0
  57. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0018-readme-golden-path.md +0 -0
  58. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0019-recovery-playbook.md +0 -0
  59. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0020-example-project-refresh.md +0 -0
  60. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0021-agent-adapter-contract.md +0 -0
  61. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0022-agent-output-validation.md +0 -0
  62. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0023-codex-exec-adapter-hardening.md +0 -0
  63. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0024-claude-manual-adapter-hardening.md +0 -0
  64. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0025-generic-shell-adapter.md +0 -0
  65. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0026-agent-job-evidence-ingestion.md +0 -0
  66. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0027-dashboard-data-contract.md +0 -0
  67. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0028-dashboard-evidence-navigation.md +0 -0
  68. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0029-dashboard-risk-and-blockers.md +0 -0
  69. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0030-distribution-readiness.md +0 -0
  70. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0031-workflow-proposal-mode.md +0 -0
  71. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0032-workflow-proposal-review.md +0 -0
  72. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0033-workflow-verifier.md +0 -0
  73. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0034-limited-execution-sandbox.md +0 -0
  74. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0035-automatic-workflow-executor.md +0 -0
  75. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0036-executor-dogfood-workflow.md +0 -0
  76. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0037-executor-retry-resume.md +0 -0
  77. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0038-story-test-lifecycle.md +0 -0
  78. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0039-workflow-yaml-rule-expressions.md +0 -0
  79. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0040-test-case-evidence-validation.md +0 -0
  80. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0041-feature-inspection-commands.md +0 -0
  81. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0042-report-coverage-context.md +0 -0
  82. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0043-feature-report.md +0 -0
  83. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0044-complete-csv-export.md +0 -0
  84. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0045-filtered-job-inspection.md +0 -0
  85. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0046-feature-status-lifecycle.md +0 -0
  86. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0047-feature-coverage-next-action.md +0 -0
  87. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0048-migration-status-command.md +0 -0
  88. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0049-render-json-artifact-paths.md +0 -0
  89. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0050-codex-plugin-package-inventory.md +0 -0
  90. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0051-mcp-render-artifact-paths.md +0 -0
  91. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0052-lifecycle-failure-job-cleanup.md +0 -0
  92. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0053-prompt-job-json-handoff.md +0 -0
  93. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0054-human-queue-linkage-cli.md +0 -0
  94. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0055-workflow-proposal-list-filter.md +0 -0
  95. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0056-sandbox-noop-execution-guard.md +0 -0
  96. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0057-executor-no-executable-step-guard.md +0 -0
  97. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0058-dogfood-usability-hardening.md +0 -0
  98. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0059-checkpoint-review-guidance.md +0 -0
  99. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0060-pypi-trusted-publishing.md +0 -0
  100. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0061-context-pack-v1.md +0 -0
  101. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0062-task-backlog-entity.md +0 -0
  102. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0063-structured-verification-rubric.md +0 -0
  103. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0064-task-loop-integration.md +0 -0
  104. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0065-dashboard-human-decisions.md +0 -0
  105. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0066-agent-registry-lease.md +0 -0
  106. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0067-context-pack-improvements.md +0 -0
  107. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0068-trust-hardening.md +0 -0
  108. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0069-explainable-code-context-v0.md +0 -0
  109. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0070-human-decision-cockpit.md +0 -0
  110. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0071-dogfood-impact-precision.md +0 -0
  111. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0072-sensitive-omission.md +0 -0
  112. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0073-code-context-module-split.md +0 -0
  113. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0074-search-snapshot-consistency.md +0 -0
  114. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0075-diff-source-modes.md +0 -0
  115. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0076-schema-version-integrity.md +0 -0
  116. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0077-index-output-budget-and-impact-noise.md +0 -0
  117. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0078-context-pack-code-context-bridge.md +0 -0
  118. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0079-receipt-human-summary.md +0 -0
  119. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0080-retrieval-eval-gate.md +0 -0
  120. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0081-diff-modes-completion.md +0 -0
  121. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0082-receipt-relevance-and-age.md +0 -0
  122. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0083-required-section-invariant.md +0 -0
  123. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0084-source-commands-honesty.md +0 -0
  124. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0085-distribution-source-completeness.md +0 -0
  125. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0086-command-surface-alignment.md +0 -0
  126. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0087-verification-suggestion-ids.md +0 -0
  127. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0088-verification-feedback.md +0 -0
  128. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0089-dogfood-fixture-propose.md +0 -0
  129. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0090-eval-baseline-record-compare.md +0 -0
  130. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0091-refresh-command-scope-fidelity.md +0 -0
  131. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0092-idempotent-status-transitions.md +0 -0
  132. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0093-evidence-add-command.md +0 -0
  133. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0094-job-completion-evidence.md +0 -0
  134. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0095-supporting-evidence-health.md +0 -0
  135. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0096-evidence-add-path-guards.md +0 -0
  136. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0097-evidence-durability-design.md +0 -0
  137. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0098-field-feedback-next-weight-and-run-report-scope.md +0 -0
  138. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0099-evidence-copy-mode.md +0 -0
  139. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0100-evidence-task-linking.md +0 -0
  140. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0101-evidence-id-allocation-race.md +0 -0
  141. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0102-source-drift-health-warning.md +0 -0
  142. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0103-security-policy-v02x.md +0 -0
  143. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0104-python-ci-matrix.md +0 -0
  144. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0105-evidence-copy-observability.md +0 -0
  145. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0106-release-checklist.md +0 -0
  146. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0107-agent-tasks-backlog-index.md +0 -0
  147. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0108-target-bound-code-context-receipts.md +0 -0
  148. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0113-evidence-links-table.md +0 -0
  149. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0114-source-hash-drift.md +0 -0
  150. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/agent-tasks/0115-context-pack-contract-fixtures.md +0 -0
  151. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/adr/0001-hybrid-state.md +0 -0
  152. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/adr/0002-cli-is-the-runtime.md +0 -0
  153. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/adr/0003-static-workflows-before-dynamic-workflows.md +0 -0
  154. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/agent-adapter-contract.md +0 -0
  155. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/agent-output-template.md +0 -0
  156. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/agent-roles.md +0 -0
  157. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/architecture.md +0 -0
  158. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/dashboard-data-contract.md +0 -0
  159. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/dashboard-design.md +0 -0
  160. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/data-model.md +0 -0
  161. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/distribution.md +0 -0
  162. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/evidence-durability-design.md +0 -0
  163. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/evidence-entry-paths-design.md +0 -0
  164. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/feedback/2026-07-06-ax1-moc1-agent-feedback.md +0 -0
  165. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/golden-path.md +0 -0
  166. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/growth-plan-v0.2.4-v0.5.md +0 -0
  167. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/implementation-plan.md +0 -0
  168. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/master-trace-handoff.md +0 -0
  169. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/plh_v0_1_11_review_agenda.md +0 -0
  170. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/plh_v0_1_12_review_agenda.md +0 -0
  171. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/pypi-publishing.md +0 -0
  172. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/recovery-playbook.md +0 -0
  173. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/release-checklist.md +0 -0
  174. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/release-notes/v0.2.4.md +0 -0
  175. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/safety-permissions.md +0 -0
  176. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/v0.2.0-plan.md +0 -0
  177. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/verification-feedback-design.md +0 -0
  178. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/verification-feedback.md +0 -0
  179. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/verification-rubric.md +0 -0
  180. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/docs/workflow-contract.md +0 -0
  181. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/scripts/run_advisory_retrieval_eval.py +0 -0
  182. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/scripts/verify_sdist_contracts.py +0 -0
  183. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/setup.cfg +0 -0
  184. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/__main__.py +0 -0
  185. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/agents.py +0 -0
  186. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/checkpoints.py +0 -0
  187. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/__init__.py +0 -0
  188. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/diff.py +0 -0
  189. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/eval.py +0 -0
  190. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/impact.py +0 -0
  191. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/receipts.py +0 -0
  192. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/scan.py +0 -0
  193. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/search.py +0 -0
  194. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/store.py +0 -0
  195. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/summary.py +0 -0
  196. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/symbols.py +0 -0
  197. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_context/test_hints.py +0 -0
  198. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/code_index.py +0 -0
  199. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/db/migrations/001_initial.sql +0 -0
  200. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/db/migrations/002_tasks.sql +0 -0
  201. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/db/migrations/003_agent_registry.sql +0 -0
  202. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/db/migrations/004_code_index.sql +0 -0
  203. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/db/migrations/005_verification_feedback.sql +0 -0
  204. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/db/migrations/006_evidence_task_link.sql +0 -0
  205. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/db/migrations/007_evidence_links.sql +0 -0
  206. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/db/schema.sql +0 -0
  207. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/db.py +0 -0
  208. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/decisions.py +0 -0
  209. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/dispatch.py +0 -0
  210. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/errors.py +0 -0
  211. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/escalations.py +0 -0
  212. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/events.py +0 -0
  213. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/evidence.py +0 -0
  214. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/exporters.py +0 -0
  215. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/guards.py +0 -0
  216. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/ids.py +0 -0
  217. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/init_project.py +0 -0
  218. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/lifecycle.py +0 -0
  219. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/links.py +0 -0
  220. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/mcp_server.py +0 -0
  221. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/migrations.py +0 -0
  222. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/paths.py +0 -0
  223. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/receipt_show.py +0 -0
  224. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/registry.py +0 -0
  225. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/renderer.py +0 -0
  226. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/reports.py +0 -0
  227. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/resources.py +0 -0
  228. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/rubric.py +0 -0
  229. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/stories.py +0 -0
  230. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/tasks.py +0 -0
  231. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/dashboard/dashboard.html +0 -0
  232. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/project/AGENTS.block.md +0 -0
  233. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/project/CLAUDE.block.md +0 -0
  234. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/project/gitignore.fragment +0 -0
  235. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/project/pcl.yaml +0 -0
  236. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/skills/project-control-loop/SKILL.md +0 -0
  237. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/workflows/defect_repair.yaml +0 -0
  238. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/workflows/executor_smoke.yaml +0 -0
  239. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/workflows/feature_coverage.yaml +0 -0
  240. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/templates/workflows/regression_loop.yaml +0 -0
  241. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/timeutil.py +0 -0
  242. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/token_estimation.py +0 -0
  243. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/update_check.py +0 -0
  244. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/verification_feedback.py +0 -0
  245. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/verifications.py +0 -0
  246. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/workflow_executor.py +0 -0
  247. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/workflow_proposal_validation.py +0 -0
  248. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/workflow_proposals.py +0 -0
  249. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/workflow_sandbox.py +0 -0
  250. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/workflow_verifier.py +0 -0
  251. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/pcl/workflow_yaml.py +0 -0
  252. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/dependency_links.txt +0 -0
  253. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/entry_points.txt +0 -0
  254. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/requires.txt +0 -0
  255. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/top_level.txt +0 -0
  256. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/fixtures/code_context_summary_v0.json +0 -0
  257. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/fixtures/context_receipt_v0.json +0 -0
  258. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/fixtures/context_receipt_v0_legacy_string_suggestions.json +0 -0
  259. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/fixtures/retrieval_adversarial_v0.json +0 -0
  260. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/fixtures/retrieval_real_history_v0.json +0 -0
  261. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/fixtures/retrieval_v0.json +0 -0
  262. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_advisory_retrieval_eval_script.py +0 -0
  263. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_agent_adapter_contract.py +0 -0
  264. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_agent_output_validation.py +0 -0
  265. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_agents.py +0 -0
  266. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_audit_log_integrity.py +0 -0
  267. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_checkpoints.py +0 -0
  268. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_claude_manual_adapter.py +0 -0
  269. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_cli_init.py +0 -0
  270. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_code_context_summary.py +0 -0
  271. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_code_index.py +0 -0
  272. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_codex_exec_adapter.py +0 -0
  273. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_codex_plugin.py +0 -0
  274. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_dashboard.py +0 -0
  275. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_dashboard_data_contract.py +0 -0
  276. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_decisions.py +0 -0
  277. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_defects.py +0 -0
  278. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_dispatch.py +0 -0
  279. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_distribution.py +0 -0
  280. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_escalations.py +0 -0
  281. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_evidence_add.py +0 -0
  282. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_examples.py +0 -0
  283. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_features.py +0 -0
  284. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_generic_shell_adapter.py +0 -0
  285. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_golden_path.py +0 -0
  286. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_lifecycle.py +0 -0
  287. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_mcp_server.py +0 -0
  288. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_migrations.py +0 -0
  289. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_pypi_publishing.py +0 -0
  290. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_receipt_show.py +0 -0
  291. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_recovery_playbook.py +0 -0
  292. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_registry.py +0 -0
  293. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_reports.py +0 -0
  294. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_rubric.py +0 -0
  295. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_stories.py +0 -0
  296. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_tasks.py +0 -0
  297. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_update_check.py +0 -0
  298. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_validation_diagnostics.py +0 -0
  299. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_verification_feedback.py +0 -0
  300. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_workflow_executor.py +0 -0
  301. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_workflow_proposals.py +0 -0
  302. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_workflow_sandbox.py +0 -0
  303. {project_loop_harness-0.3.0 → project_loop_harness-0.3.1}/tests/test_workflow_verifier.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: project-loop-harness
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Local control plane for agentic project development loops
5
5
  Author: Project Loop Harness Contributors
6
6
  License: MIT
@@ -269,6 +269,33 @@ evidence. Receipts use the fields `included_candidate_context`, `omitted`, and
269
269
  See [docs/code-context.md](docs/code-context.md) for the index, impact,
270
270
  receipt, and retrieval-eval contracts.
271
271
 
272
+ ### Target-bound agent handoff (v0.3)
273
+
274
+ To hand another agent auditable, target-scoped code context, bind a receipt to
275
+ the task or job, then require that binding when you build the pack:
276
+
277
+ ```bash
278
+ pcl index build --json
279
+ pcl impact --diff --for-task T-0001 --json
280
+ pcl context pack --task T-0001 --include-code-context --require-bound-receipt --json
281
+ ```
282
+
283
+ Use the `--for-job` / `--job` forms for an agent-job handoff:
284
+
285
+ ```bash
286
+ pcl impact --diff --for-job J-0001 --json
287
+ pcl context pack --job J-0001 --include-code-context --require-bound-receipt --json
288
+ ```
289
+
290
+ `pcl impact --diff --for-task` (or `--for-job`) records a caller-asserted binding
291
+ between the diff-based receipt and the target. With `--require-bound-receipt` the
292
+ pack fails with `context_pack_bound_receipt_required` instead of silently using an
293
+ unrelated latest receipt, so a worker never receives another task's context under
294
+ a target-bound label. The binding records that a receipt was created for the
295
+ target (`binding_strength: caller_asserted`) — not that the receipt is sufficient
296
+ or that any agent read it. Because the receipt comes from a diff, this is a
297
+ review/continuation handoff and presumes a change already exists for the target.
298
+
272
299
  ## Guided Next Actions
273
300
 
274
301
  `pcl next` is the loop router. The JSON output keeps the original fields and adds stable guidance fields:
@@ -237,6 +237,33 @@ evidence. Receipts use the fields `included_candidate_context`, `omitted`, and
237
237
  See [docs/code-context.md](docs/code-context.md) for the index, impact,
238
238
  receipt, and retrieval-eval contracts.
239
239
 
240
+ ### Target-bound agent handoff (v0.3)
241
+
242
+ To hand another agent auditable, target-scoped code context, bind a receipt to
243
+ the task or job, then require that binding when you build the pack:
244
+
245
+ ```bash
246
+ pcl index build --json
247
+ pcl impact --diff --for-task T-0001 --json
248
+ pcl context pack --task T-0001 --include-code-context --require-bound-receipt --json
249
+ ```
250
+
251
+ Use the `--for-job` / `--job` forms for an agent-job handoff:
252
+
253
+ ```bash
254
+ pcl impact --diff --for-job J-0001 --json
255
+ pcl context pack --job J-0001 --include-code-context --require-bound-receipt --json
256
+ ```
257
+
258
+ `pcl impact --diff --for-task` (or `--for-job`) records a caller-asserted binding
259
+ between the diff-based receipt and the target. With `--require-bound-receipt` the
260
+ pack fails with `context_pack_bound_receipt_required` instead of silently using an
261
+ unrelated latest receipt, so a worker never receives another task's context under
262
+ a target-bound label. The binding records that a receipt was created for the
263
+ target (`binding_strength: caller_asserted`) — not that the receipt is sufficient
264
+ or that any agent read it. Because the receipt comes from a diff, this is a
265
+ review/continuation handoff and presumes a change already exists for the target.
266
+
240
267
  ## Guided Next Actions
241
268
 
242
269
  `pcl next` is the loop router. The JSON output keeps the original fields and adds stable guidance fields:
@@ -0,0 +1,163 @@
1
+ # 0116: Target-bound receipt / link agreement validation
2
+
3
+ Milestone: v0.3.1 Handoff Integrity + Operator Experience
4
+ Priority: P1
5
+ Area: context/validation
6
+ Origin: third-party v0.3.0 post-release review (P1①). Sakamoto approved the
7
+ recommended plan 2026-07-09 (integrity pair 0116+0117 first).
8
+
9
+ ## Problem
10
+
11
+ v0.3.0 selects a target-bound code-context receipt purely from the
12
+ `evidence_links` routing row plus the evidence type. `_select_code_context_receipt_ref`
13
+ (`context.py:780-791`) reads `newest_linked_evidence_id(... link_role="code_context")`,
14
+ loads the evidence row, checks only `evidence_type == context_receipt`, and returns
15
+ `"target_bound"`. Downstream, `_latest_code_context_summary` (`context.py:725-751`)
16
+ loads the receipt artifact but **never compares the artifact's `target_binding`
17
+ to the requested pack target**, and `_code_context_relevance` (`context.py:857`)
18
+ stamps `scope: target_bound` from `selection_scope` alone. Strict validation
19
+ (`_validate_evidence_links`, `validators.py:621-659`) only checks dangling links
20
+ (evidence row exists; `target_id` exists in `tasks`/`agent_jobs`); it does not
21
+ read the artifact binding either.
22
+
23
+ On the normal write path this cannot break: 0108 writes the `evidence_links`
24
+ row and the artifact `target_binding` in one transaction with the same target,
25
+ and inserts the `code_context` link **only when `target_binding is not None`**
26
+ (`code_context/receipts.py:123-129`). But a hand-edited DB, a future writer bug,
27
+ a migration accident, or raw SQL can leave the link routing a receipt whose
28
+ artifact binding names a *different* target. Today that receipt would surface as
29
+ `scope: target_bound` for the wrong target — the exact "target-bound label that
30
+ lies" failure this milestone must foreclose.
31
+
32
+ This is defense-in-depth / corruption resilience, not a normal-path bug. The
33
+ guarantee to establish: **nothing is ever reported as `target_bound` unless the
34
+ selected receipt artifact's own `target_binding` agrees with the requested
35
+ target.**
36
+
37
+ ## Scope
38
+
39
+ ### 1. Agreement predicate (single reusable helper)
40
+
41
+ Add one pure helper (in `context.py`, or a small shared location `pcl context
42
+ check` (0119) can also import — do not duplicate this logic later):
43
+
44
+ ```python
45
+ def _receipt_target_binding_agrees(
46
+ receipt_payload: dict[str, Any], *, target_type: str, target_id: str
47
+ ) -> bool:
48
+ binding = receipt_payload.get("target_binding")
49
+ if not isinstance(binding, dict):
50
+ return False # a code_context-linked artifact with no binding is anomalous
51
+ return (
52
+ str(binding.get("target_type")) == target_type
53
+ and str(binding.get("target_id")) == target_id
54
+ )
55
+ ```
56
+
57
+ Missing / non-dict `target_binding` on a receipt reached through a `code_context`
58
+ link counts as **disagreement** (per the 0108 invariant such a link always has a
59
+ binding, so its absence is corruption).
60
+
61
+ ### 2. Read-side guard in selection
62
+
63
+ In `_select_code_context_receipt_ref`, after obtaining the candidate
64
+ `receipt_ref` from the link and confirming `evidence_type == context_receipt`,
65
+ load the receipt artifact (reuse `resolve_context_receipt_path` +
66
+ `json.loads`, both already used at `context.py:725-727`):
67
+
68
+ - **Artifact load fails** (OSError / JSONDecodeError / not a dict): NOT a
69
+ mismatch. Preserve current behavior — return `(_public_receipt_ref(...),
70
+ "target_bound")` and let `_latest_code_context_summary` render
71
+ `receipt_unavailable`. (Unreadable ≠ disagreement; do not turn transient FS
72
+ errors into mismatches.)
73
+ - **Artifact loads and binding agrees**: return `(ref, "target_bound")` (today's
74
+ happy path, unchanged).
75
+ - **Artifact loads and binding disagrees** (including missing/blank binding):
76
+ MISMATCH.
77
+ - `require_bound_receipt=True` → raise a new distinct
78
+ `ContextPackBoundReceiptMismatchError` (see §3). Do **not** raise the
79
+ existing `...RequiredError` — the operator must be able to tell "corrupt
80
+ binding" from "no receipt".
81
+ - `require_bound_receipt=False` → skip this receipt and fall through to the
82
+ existing `latest_context_receipt_ref` path, returning `"unscoped_latest"`
83
+ (or `"missing_receipt"` if none). It MUST NOT return `"target_bound"`.
84
+ SHOULD: surface that a mismatched bound link was skipped in the
85
+ `unscoped_latest` relevance `warning` (distinct wording from plain "no
86
+ target-bound receipt found"); if threading a flag is awkward, the MUST
87
+ (never `target_bound`) is sufficient for this task.
88
+
89
+ ### 3. New typed error
90
+
91
+ Add `ContextPackBoundReceiptMismatchError(PclError)` modeled on
92
+ `ContextPackBoundReceiptRequiredError` (`context.py:47-58`):
93
+
94
+ - `code = "context_pack_bound_receipt_mismatch"`, `exit_code = EXIT_USAGE`.
95
+ - `message`: names the target and that a linked receipt's binding disagrees.
96
+ - `details`: `target_type`, `target_id`, the offending `evidence_id`, the
97
+ artifact's claimed `target_binding` (as read), and
98
+ `suggested_refresh_commands = [_target_refresh_command(target_type, target_id)]`.
99
+
100
+ ### 4. Strict-validation agreement check
101
+
102
+ Thread `ProjectPaths` into the evidence-links validation (`validate_project`
103
+ already has `paths` at `validators.py:110`; update the call site
104
+ `_validate_evidence_links(conn, result)` at `validators.py:266`). For each
105
+ `evidence_links` row with `link_role == "code_context"` and a **known**
106
+ `target_type`:
107
+
108
+ - Resolve the receipt artifact via `evidence_ref_by_id(paths, evidence_id)` +
109
+ `resolve_context_receipt_path`.
110
+ - If the artifact is **readable** and its `target_binding` disagrees with the
111
+ row's `(target_type, target_id)` (using the §1 predicate), `result.add_error`
112
+ with a message naming the link, the row target, and the artifact's claimed
113
+ binding.
114
+ - If the artifact is **missing/unreadable**, add no new error here (existing
115
+ evidence-health / dangling checks own that surface; avoid double-reporting).
116
+
117
+ Only `code_context` links are checked (supporting links have no artifact
118
+ binding). Unknown `target_type` stays tolerated (no error), as in 0113.
119
+
120
+ ## Invariants (what to protect, on the normal paths)
121
+
122
+ - Normal-path target-bound selection and output are byte-for-byte unchanged: a
123
+ receipt whose artifact binding matches keeps `scope: target_bound` /
124
+ `binding_strength: caller_asserted` and the same `receipt_ref`.
125
+ - No new claim vocabulary. Binding stays `caller_asserted`; no
126
+ `verified_relevant` / `safe_to_continue` / `agent_read` / semantic wording.
127
+ A mismatch error states a *fact* ("the routing row and the artifact binding
128
+ disagree"), never a judgment about relevance.
129
+ - `pcl` remains the only mutation path; this task adds read-side checks only and
130
+ writes nothing.
131
+ - Additive: no schema change (schema stays 7), no migration, no new table or
132
+ column. `require_human_approval: database_migration` does NOT apply.
133
+
134
+ ## Non-scope
135
+
136
+ - `pcl context check` (0119) — it will import the §1 predicate; do not build the
137
+ command here.
138
+ - Auto-repair / re-linking of a mismatched link. Detection and safe refusal
139
+ only; never mutate `evidence_links` to "fix" a mismatch.
140
+ - Any change to the 0108 write path (it is already correct and atomic).
141
+ - Markdown refresh-command wording (that is 0117).
142
+
143
+ ## Acceptance
144
+
145
+ - New helper is unit-tested: agrees on matching binding; disagrees on
146
+ mismatched target, on missing `target_binding`, and on non-dict payload.
147
+ - Contract fixture added (extend the 0115 code-context contract set): an
148
+ `evidence_links` `code_context` row pointing at target A while the artifact
149
+ `target_binding` names target B —
150
+ - `--require-bound-receipt` → error
151
+ `context_pack_bound_receipt_mismatch` (not `..._required`);
152
+ - default (no require) → `code_context.relevance.scope` is `unscoped_latest`
153
+ or `missing_receipt`, **never** `target_bound`.
154
+ - `validate --strict --json` reports the hand-built mismatch row as an error;
155
+ an agreeing `code_context` row and any `supporting` row produce no new error;
156
+ an unknown `target_type` row is still tolerated.
157
+ - All existing target-bound / require / unscoped tests stay green (normal path
158
+ unaffected).
159
+ - Full `pytest` green; live smoke in a scratch project proving: a normal
160
+ `impact --for-task` + `context pack --require-bound-receipt` still selects
161
+ `target_bound`, and a deliberately corrupted link (built through `pcl`-created
162
+ state, then the `.db` row's `target_id` diverged for the test only) yields the
163
+ mismatch error under `--require-bound-receipt` and `unscoped_latest` without.
@@ -0,0 +1,76 @@
1
+ # 0117: Target-specific refresh command in code-context Markdown
2
+
3
+ Milestone: v0.3.1 Handoff Integrity + Operator Experience
4
+ Priority: P1
5
+ Area: context/markdown
6
+ Origin: third-party v0.3.0 post-release review (P1②). Sakamoto approved the
7
+ recommended plan 2026-07-09 (integrity pair 0116+0117 first).
8
+
9
+ ## Problem
10
+
11
+ The JSON context pack exposes a target-specific refresh command
12
+ (`suggested_refresh_commands` ends with `pcl impact --diff --for-task T-XXXX
13
+ --json` / `--for-job J-XXXX --json`; see `context.py:313,431` and the JSON tests
14
+ at `tests/test_context.py:1626,1660,1694`). But the **Markdown** safety section
15
+ `_render_code_context_safety_section` (`context.py:1001-1027`) hardcodes a
16
+ generic line in both the `missing_receipt` and `receipt_unavailable` branches:
17
+
18
+ ```
19
+ Next action: `pcl index build --json`, then `pcl impact --diff --json`.
20
+ ```
21
+
22
+ An agent reading the Markdown pack (many workers read Markdown, not JSON) is told
23
+ to run the **unbound** `pcl impact --diff --json`, which produces an unbound
24
+ receipt — the exact anti-pattern v0.3.0's target binding exists to prevent. The
25
+ stamped `summary` already carries the target: `relevance.target_id`,
26
+ target-specific `next_actions` (set for `missing_receipt` in
27
+ `_stamp_code_context_pack_facts`, `context.py:827-831`), and a target-rewritten
28
+ `refresh_replay` (`_target_refresh_replay`). The Markdown renderer simply ignores
29
+ them.
30
+
31
+ ## Scope
32
+
33
+ 1. In `_render_code_context_safety_section`, replace the hardcoded generic
34
+ "Next action" line in **both** the `missing_receipt` and `receipt_unavailable`
35
+ branches with commands derived from the **same** target-specific source the
36
+ JSON uses: `recommended_refresh_commands(summary)` (already imported into
37
+ `context.py:12`). Render them as the "Next action" line so Markdown and JSON
38
+ cannot diverge.
39
+ 2. Establish the invariant explicitly: **the Markdown safety "Next action"
40
+ commands equal the JSON `suggested_refresh_commands`** for the same pack.
41
+ Whatever list drives `pack["suggested_refresh_commands"]` must be what the
42
+ Markdown line renders — one source, two renderings.
43
+ 3. If `recommended_refresh_commands(summary)` is empty for some state, fall back
44
+ to the prior generic text (do not crash / emit an empty line); target-bound
45
+ states are the ones that matter here.
46
+
47
+ ## Invariants (what to protect)
48
+
49
+ - No behavioral change to the JSON pack; only the Markdown string changes.
50
+ - For a task pack the rendered command contains `--for-task <task_id>`; for a job
51
+ pack, `--for-job <job_id>`. The `pcl index build --json` prelude is preserved
52
+ if it is part of `recommended_refresh_commands`.
53
+ - `## Code Context Safety` heading and the surrounding "Receipt selection and
54
+ freshness facts" lines are unchanged.
55
+ - No new claim vocabulary; this is a command-string fix only.
56
+
57
+ ## Non-scope
58
+
59
+ - Read-side agreement / mismatch handling (0116).
60
+ - JSON `suggested_refresh_commands` (already target-specific).
61
+ - Any change to `recommended_refresh_commands` / `refresh_replay` themselves.
62
+
63
+ ## Acceptance
64
+
65
+ - New/updated test on the **Markdown**: for a `missing_receipt` task pack the
66
+ safety section contains `pcl impact --diff --for-task T-XXXX --json` and does
67
+ **not** contain a bare `pcl impact --diff --json` line; the job pack variant
68
+ contains `--for-job J-XXXX`. Add the equivalent assertion for the
69
+ `receipt_unavailable` branch.
70
+ - A test asserts the equivalence invariant: the Markdown safety "Next action"
71
+ commands match `pack["suggested_refresh_commands"]` for the same pack.
72
+ - Existing `"## Code Context Safety" in pack["markdown"]` assertions
73
+ (`tests/test_context.py:1076,1528,1896` etc.) stay green.
74
+ - Full `pytest` green; live smoke: a `context pack --task T-XXXX
75
+ --include-code-context` with no receipt shows the target-specific command in
76
+ the rendered Markdown.
@@ -0,0 +1,64 @@
1
+ # 0118: Canonical target-bound handoff docs (README + adoption)
2
+
3
+ Milestone: v0.3.1 Handoff Integrity + Operator Experience
4
+ Priority: P1
5
+ Area: docs
6
+ Origin: third-party v0.3.0 post-release review (P1③ — README does not surface
7
+ v0.3's canonical `--require-bound-receipt` flow). Sakamoto approved 2026-07-09.
8
+ Implemented by the orchestrator (opus) directly, not delegated — README/adoption
9
+ copy is user-facing, where taste matters more than throughput.
10
+
11
+ ## Problem
12
+
13
+ v0.3.0's headline value is the target-bound context pack, gated by
14
+ `pcl context pack --include-code-context --require-bound-receipt`. But the README
15
+ front door (`## Context Packs`, `## Explainable Code Context`) shows only the
16
+ basic `pcl context pack --task ...` and `pcl impact --diff --json` forms, so a
17
+ first-time reader never sees the canonical strict handoff. `grep` on README for
18
+ `--require-bound-receipt` / `--for-task` / `--include-code-context` returns zero.
19
+
20
+ ## Scope (orchestrator-owned files only)
21
+
22
+ Disjoint from 0119 (which owns `src/`, `tests/`, and the new
23
+ `docs/context-check.md`). This task edits only:
24
+
25
+ - `README.md`: add a short "Target-bound agent handoff (v0.3)" subsection near
26
+ `## Context Packs` / `## Explainable Code Context` showing the canonical
27
+ command for a task and a job:
28
+ ```
29
+ pcl index build --json
30
+ pcl impact --diff --for-task T-0001 --json
31
+ pcl context pack --task T-0001 --include-code-context --require-bound-receipt --json
32
+ ```
33
+ State plainly: with `--require-bound-receipt` the pack fails
34
+ (`context_pack_bound_receipt_required`) instead of silently using an unrelated
35
+ latest receipt; binding is a caller assertion (`caller_asserted`), not a
36
+ relevance proof.
37
+ - `docs/context-pack.md`: mark `--require-bound-receipt` as the canonical strict
38
+ handoff path for worker handoffs.
39
+ - `docs/code-context.md`: add a short "review/continuation vs pre-work" boundary
40
+ note — receipts are built from `pcl impact --diff`, so a target-bound receipt
41
+ presumes a diff exists; pre-implementation handoff is a separate future path.
42
+ - `docs/adoption-guide.md`: add the worker-handoff command as the recommended
43
+ default.
44
+
45
+ ## Invariants (what to protect)
46
+
47
+ - Docs only. No `src/`, no `tests/`, no schema, no behavior change.
48
+ - Every command shown must be one that actually exists and works in v0.3.0
49
+ (verify by running each in a scratch repo before claiming it).
50
+ - Do not document `pcl context check` here — it does not exist until 0119 merges
51
+ (a follow-up may cross-link once both are in).
52
+ - Keep the epistemic framing: no "safe"/"verified"/"understood" language; the
53
+ pack records that a receipt was created for a target, not that it is
54
+ sufficient.
55
+
56
+ ## Acceptance
57
+
58
+ - README contains the canonical task and job handoff commands and the
59
+ `--require-bound-receipt` semantics; `grep` for `--require-bound-receipt` in
60
+ README is non-empty.
61
+ - The three docs carry the canonical-path / boundary notes.
62
+ - Each shown command verified against a live scratch repo (paste evidence in the
63
+ commit or handoff).
64
+ - No code or test files changed.
@@ -0,0 +1,145 @@
1
+ # 0119: `pcl context check` — read-only target-bound handoff preflight
2
+
3
+ Milestone: v0.3.1 Handoff Integrity + Operator Experience
4
+ Priority: P1
5
+ Area: cli/context
6
+ Origin: third-party v0.2.4 + v0.3.0 reviews (context-check deferred to v0.3.1);
7
+ Sakamoto approved starting 0118+0119 together 2026-07-09. Builds on 0116.
8
+
9
+ ## Problem
10
+
11
+ Today an operator or agent only learns whether a target has a usable
12
+ target-bound code-context receipt by *running* `pcl context pack
13
+ --include-code-context --require-bound-receipt` and reading the error, or by
14
+ inspecting `relevance.scope` in a full pack. There is no cheap, read-only
15
+ preflight that answers, for a task or job: is there a target-bound code-context
16
+ receipt, is it the corrupt (mismatched) kind, how much supporting evidence is
17
+ linked, and what is the exact canonical command to produce a bound handoff.
18
+
19
+ Add `pcl context check`: a **read-only** diagnostic that reports these facts and
20
+ the next command, without mutating anything and without running `index build` or
21
+ `impact`.
22
+
23
+ ## Scope
24
+
25
+ ### CLI
26
+ Add a sibling of `context pack` under the existing `context` subparser
27
+ (`cli.py:587-589`):
28
+
29
+ ```
30
+ pcl context check (--task T-XXXX | --job J-XXXX) [--json] [--require-bound-receipt]
31
+ ```
32
+
33
+ - `--task` / `--job` are a required mutually-exclusive group (mirror
34
+ `context pack`, `cli.py:590-592`).
35
+ - `--require-bound-receipt`: optional; changes exit behavior (see Exit codes).
36
+ - Dispatch under `if args.command == "context" and args.context_command ==
37
+ "check":` next to the `pack` handler (`cli.py:1923`). Emit
38
+ `_print_json({"ok": True, "context_check": payload})` for `--json`, else a
39
+ short factual text summary.
40
+
41
+ ### Behavior (read-only)
42
+ Implement a `context_check_for_task` / `context_check_for_job` (or one
43
+ `check_context(paths, *, target_type, target_id, ...)`) in `context.py` that:
44
+
45
+ 1. Validates the target id shape and existence by reusing the impact validators
46
+ `_validate_target_id_shape` + `_require_existing_target`
47
+ (`code_context/impact.py`) so a bad/absent target raises the same typed
48
+ `ImpactTargetError` (`impact_target_invalid` / not-found) as `impact
49
+ --for-task`. Do not invent a new not-found error.
50
+ 2. Determines the target-bound code-context status by reusing 0116 machinery,
51
+ read-only:
52
+ - `newest_linked_evidence_id(conn, target_type, target_id,
53
+ link_role="code_context")`;
54
+ - if found and the evidence row is a `context_receipt`, load the artifact and
55
+ apply `_receipt_target_binding_agrees` (from `context_binding.py`):
56
+ agree -> `status: "present"`; disagree/missing-binding -> `status:
57
+ "mismatched"`; artifact unreadable -> `status: "present"` is NOT claimed —
58
+ report `status: "unavailable"` (cannot confirm agreement) rather than
59
+ asserting a bound receipt;
60
+ - if no `code_context` link -> `status: "missing"`.
61
+ 3. Counts supporting evidence: number of `evidence_links` rows for
62
+ `(target_type, target_id, link_role="supporting")` (a `SELECT COUNT` read;
63
+ the existing supporting-link query is at `context.py:1419`). SELECT-only reads
64
+ are allowed; this task writes nothing.
65
+
66
+ ### Output payload (`context_check`)
67
+ Factual fields only:
68
+ - `target`: `{ "type": "task"|"agent_job", "id": "T-XXXX" }`
69
+ - `supporting_evidence_count`: int
70
+ - `target_bound_code_context`: `{ "status": "present"|"missing"|"mismatched"|
71
+ "unavailable", "receipt_ref"?: {"evidence_id","created_at"},
72
+ "claimed_target_binding"?: <on mismatched> }`
73
+ - `canonical_context_pack_command`: the exact command a caller should run for a
74
+ strict bound handoff, e.g.
75
+ `pcl context pack --task T-XXXX --include-code-context --require-bound-receipt
76
+ --json` (job variant with `--job`).
77
+ - `recommended_refresh_command`: `_target_refresh_command(target_type,
78
+ target_id)` — present when status is `missing`/`mismatched`/`unavailable`.
79
+ - `warnings`: list of factual strings (e.g. `"No target-bound code context
80
+ receipt exists for this task."`, `"A code_context link disagrees with its
81
+ artifact binding."`).
82
+
83
+ ### Exit codes
84
+ - Default (no `--require-bound-receipt`): the diagnostic itself succeeded ->
85
+ exit 0, status in payload, even when `status != present`.
86
+ - Bad/absent target: typed `ImpactTargetError` -> exit 2 (existing behavior).
87
+ - With `--require-bound-receipt`: exit 2 when `status != present`, raising the
88
+ SAME typed errors as `context pack` for scriptable parity —
89
+ `context_pack_bound_receipt_required` for `missing`/`unavailable`,
90
+ `context_pack_bound_receipt_mismatch` for `mismatched`. (Reuse the existing
91
+ error classes from `context.py`.)
92
+
93
+ ## Invariants (what to protect)
94
+
95
+ - **Read-only.** `context check` MUST NOT run `index build`, MUST NOT run
96
+ `impact`, and MUST NOT write any evidence row, event, `evidence_links` row, or
97
+ artifact. It only does SELECT reads and reads a receipt artifact file. A test
98
+ MUST assert row/event/adhoc-file counts are identical before and after.
99
+ - **Epistemic discipline (hard).** Report facts about *what exists*, never a
100
+ sufficiency/safety/relevance judgment. Do NOT add `ready_for_handoff`,
101
+ `safe_to_continue`, `safe_to_run`, `verified_relevant`, `agent_read`,
102
+ `semantic_match`, or any go/no-go or cognition field — **even though the
103
+ originating third-party review sketched `ready_for_handoff`, we deliberately do
104
+ not adopt it.** `binding_strength` stays `caller_asserted` where surfaced. A
105
+ test MUST assert these forbidden keys are absent from the JSON.
106
+ - Additive: no schema change, no migration, no new table/column. No change to
107
+ `context pack` behavior or output.
108
+ - `pcl` stays the only mutation interface; this command mutates nothing.
109
+
110
+ ## Non-scope
111
+
112
+ - README / adoption-guide / `docs/context-pack.md` / `docs/code-context.md`
113
+ edits — those belong to **0118** (disjoint ownership; do not touch them). If a
114
+ command-surface contract test or doc must be updated to register the new
115
+ subcommand and it is one of those four files, STOP and report the conflict
116
+ instead of editing it.
117
+ - `pcl context prepare` / pre-work context synthesis (v0.4).
118
+ - Any staleness scoring beyond echoing the receipt `created_at` (no new age
119
+ policy; you may include an age in seconds computed from an injected `now`, but
120
+ it is optional).
121
+ - Auto-running refresh or repairing a mismatch.
122
+
123
+ ## Acceptance
124
+
125
+ - `pcl context check --task T-XXXX --json` on a task with a matching bound
126
+ receipt -> `status: present`, `receipt_ref` populated, `supporting_evidence_count`
127
+ correct, `canonical_context_pack_command` present, exit 0.
128
+ - Missing bound receipt -> `status: missing`, `recommended_refresh_command`
129
+ target-specific, exit 0; with `--require-bound-receipt` -> exit 2 and
130
+ `context_pack_bound_receipt_required`.
131
+ - Mismatched link (as built by the 0116 contract fixture pattern) -> `status:
132
+ mismatched`, exit 0; with `--require-bound-receipt` -> exit 2 and
133
+ `context_pack_bound_receipt_mismatch`.
134
+ - Job variant works symmetrically.
135
+ - Bad/absent target id -> typed error, exit 2.
136
+ - Read-only proof test: evidence/event/adhoc-file counts unchanged across a
137
+ `context check` invocation.
138
+ - Forbidden-key test: `ready_for_handoff` / `safe_*` / `verified_relevant` /
139
+ `agent_read` / `semantic_match` absent from the payload.
140
+ - New `docs/context-check.md` documents the command (read-only, the four status
141
+ values, the canonical command, exit-code behavior).
142
+ - `ruff` clean; full `pytest` green (v0.3.1 baseline 488; expect > 488).
143
+ - Live smoke (`python -m pcl` in a fresh scratch repo): build a bound receipt,
144
+ `context check` -> present; a second task with none -> missing (+ exit 2 under
145
+ `--require-bound-receipt`); paste the JSON for both.
@@ -0,0 +1,140 @@
1
+ # 0120: `pcl finish` — terminal close-out planner (safe first slice)
2
+
3
+ Milestone: v0.3.1 Handoff Integrity + Operator Experience
4
+ Priority: P1
5
+ Area: cli/loop
6
+ Origin: ax1-moc1 agent feedback F7 ("終端処理の認知負荷が実装より重い");
7
+ growth-plan v0.3.1 Operator Experience. Sakamoto approved proceeding 2026-07-09.
8
+
9
+ ## Problem
10
+
11
+ Closing out a loop is a long, easy-to-misorder sequence (Golden Path):
12
+ `pcl jobs complete` (per job) -> `pcl verification record` -> `pcl loop
13
+ complete` -> `pcl goal close` -> `pcl validate --strict` -> `pcl report` ->
14
+ `pcl render`. The cognitive load of knowing *what to run, in what order, and
15
+ what still blocks closure* is heavier than the work itself. There is no single
16
+ command that answers "what is left to finish this, and what needs my decision."
17
+
18
+ Add `pcl finish`: a terminal close-out **planner** that computes the ordered
19
+ remaining steps for the active run and its goal, classifies each, and — only
20
+ when asked — runs the safe generation tail. It never fabricates a completion,
21
+ verification, or closure.
22
+
23
+ ## Design boundary (non-negotiable)
24
+
25
+ `pcl finish` MUST NOT assert state on the human's behalf. It never records a
26
+ verification, completes a job, completes/fails a run, or closes a goal or
27
+ defect. Those are all `safe_to_run=False` / `requires_human` steps in the
28
+ existing `next_action` model; `finish` plans them and hands them back as
29
+ explicit commands. `finish --execute` runs ONLY `safe_to_run=True` generation
30
+ (`pcl validate --strict`, `pcl render`), and only once no state-transition step
31
+ remains. This keeps `finish` inside PLH's epistemic discipline: it organizes and
32
+ reports, it does not claim work is done.
33
+
34
+ ## Scope
35
+
36
+ ### CLI
37
+ Add a top-level `pcl finish [--json] [--execute]` (sibling of `pcl next`).
38
+ Optional `--run WR-XXXX` / `--goal G-XXXX` to target explicitly; default is
39
+ auto-detect (below). Dispatch in `cli.py` next to the `next` handler; emit
40
+ `_print_json({"ok": True, "finish": payload})` for `--json`, else a short
41
+ ordered text summary.
42
+
43
+ ### Target detection (reuse existing state model, read-only)
44
+ - Auto-detect the active run exactly as `_active_workflow_next_action`
45
+ (`commands.py:1302`) does: newest `workflow_runs` row with status in
46
+ `ACTIVE_RUN_STATUSES`. Its `goal_id` is the goal in scope.
47
+ - If no active run: fall back to the newest open goal from `loop_status`
48
+ (`commands.py:309`). If neither exists, return a `finished`/nothing-to-do
49
+ payload (idempotent), not an error.
50
+
51
+ ### Plan (the core, read-only)
52
+ Compute the ordered remaining close-out steps and classify each. Reuse the
53
+ existing ladder in `_active_workflow_next_action` for the run portion — do not
54
+ reinvent it — extracting the same step dicts (`type`, `command`, `reason`,
55
+ `requires_human`, `safe_to_run`, produced by `build_next_action`,
56
+ `commands.py:340`). Steps, in order:
57
+ 1. Run close-out ladder (reuse `_active_workflow_next_action` semantics /
58
+ `_job_status_counts`): `continue_workflow` (active jobs remain) ->
59
+ `resolve_workflow_failure` (failed/cancelled jobs) -> `record_verification`
60
+ (all jobs terminal, no approved verification; `requires_human=True`) ->
61
+ `complete_workflow` (approved verification exists).
62
+ 2. `close_goal`: if the run's goal is not yet `closed`/`cancelled` and the run
63
+ is (or becomes) passed, the remaining step is
64
+ `pcl goal close {goal_id} --summary '...' --verification {verification_id}`
65
+ (`requires_human=True`, `safe_to_run=False`). Include the approved
66
+ `verification_id` when known.
67
+ 3. Generation tail (only listed as remaining when steps 1-2 are all done):
68
+ `pcl validate --strict` and `pcl render` (`safe_to_run=True`,
69
+ `requires_human=False`). These are read-only / idempotent regeneration.
70
+
71
+ Payload:
72
+ ```
73
+ {
74
+ "target": {"run": "WR-XXXX"|null, "goal": "G-XXXX"|null},
75
+ "finished": bool, # true when no state-transition step remains
76
+ "remaining_steps": [ {type, command, reason, requires_human, safe_to_run} ],
77
+ "next_command": "<first remaining step command>"|null,
78
+ "executed": [ {command, ok} ], # only with --execute
79
+ "changed": bool # only with --execute
80
+ }
81
+ ```
82
+
83
+ ### `--execute` (safe tail only)
84
+ - If any `safe_to_run=False` step remains (jobs/verification/run/goal
85
+ assertions): run NOTHING, return the plan, `changed: false`, `next_command`
86
+ set. (You cannot safely generate from non-final state, and you must never run
87
+ the assertion.)
88
+ - If no `safe_to_run=False` step remains: run the generation tail
89
+ (`validate --strict`, then `render`) in order, capture each in `executed`,
90
+ set `changed: true` if anything ran. `finished: true`.
91
+ - Idempotent: a fully-closed, already-generated loop re-run with `--execute`
92
+ reports `finished: true`, `remaining_steps: []`. Regenerating render is
93
+ acceptable; do not error and do not assert anything.
94
+
95
+ ## Invariants (what to protect)
96
+
97
+ - `finish` writes NO loop state itself: no verification, job completion, run
98
+ complete/fail, goal/defect close. It only ever *invokes* the existing safe
99
+ read-only generators (`validate`, `render`) under `--execute`, and otherwise
100
+ reads. A test MUST assert that a plan (no `--execute`) changes no rows/events,
101
+ and that `--execute` with a pending assertion changes no rows/events.
102
+ - Reuse the existing `requires_human` / `safe_to_run` classification from the
103
+ `next_action` machinery; do not invent a parallel policy. `finish`'s per-step
104
+ flags must match what `pcl next` reports for the same step.
105
+ - No new claim vocabulary. `finish` states facts ("all jobs terminal; no
106
+ approved verification exists; next: record verification") — never that work is
107
+ correct, sufficient, or safe.
108
+ - Additive: no schema change, no migration.
109
+
110
+ ## Non-scope
111
+
112
+ - Auto-completing evidenced jobs, auto-recording verifications, or auto-closing
113
+ goals (a possible future opt-in slice; NOT this task).
114
+ - `report` generation in the tail (keep the tail to `validate` + `render`;
115
+ reports can be a later addition).
116
+ - Feature-coverage / escalation / decision handling — `finish` is scoped to the
117
+ active run + its goal close-out, not the whole `next_action` priority ladder.
118
+ - Localization (0121) and any human-gate wording changes.
119
+
120
+ ## Acceptance
121
+
122
+ - Mid-run (`continue_workflow`): `pcl finish --json` lists the remaining ladder
123
+ with correct `requires_human`/`safe_to_run` per step, `next_command` = jobs
124
+ read/continue; `--execute` runs nothing (`changed:false`) because an assertion
125
+ is pending.
126
+ - All jobs terminal, no verification: `next_command` = `verification record`,
127
+ step `requires_human:true`; `--execute` still runs nothing.
128
+ - Run passed + verification approved, goal open: `next_command` = `goal close`
129
+ with the `--verification` id; `--execute` runs nothing.
130
+ - Everything closed: `finished:true`, `remaining_steps:[]`; `--execute` runs
131
+ `validate --strict` then `render`, reports them in `executed`, `changed:true`;
132
+ a second `--execute` is idempotent.
133
+ - Read-only proof test: a plan and a `--execute` with a pending assertion each
134
+ leave evidence/event/row counts unchanged.
135
+ - No active run and no open goal: `finished:true`/nothing-to-do, exit 0, no
136
+ error.
137
+ - `ruff` clean; full `pytest` green (v0.3.1 baseline 497; expect > 497).
138
+ - New `docs/finish.md` (or a `## Finish` section in an existing loop doc, but do
139
+ not touch README / the 0118-owned docs). Live smoke (`python -m pcl`) pasting
140
+ the plan JSON at two ladder stages plus the closed-loop `--execute`.