project-loop-harness 0.2.4__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 (304) hide show
  1. {project_loop_harness-0.2.4/src/project_loop_harness.egg-info → project_loop_harness-0.3.1}/PKG-INFO +28 -1
  2. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/README.md +27 -0
  3. project_loop_harness-0.3.1/agent-tasks/0108-target-bound-code-context-receipts.md +152 -0
  4. project_loop_harness-0.3.1/agent-tasks/0113-evidence-links-table.md +118 -0
  5. project_loop_harness-0.3.1/agent-tasks/0114-source-hash-drift.md +78 -0
  6. project_loop_harness-0.3.1/agent-tasks/0115-context-pack-contract-fixtures.md +72 -0
  7. project_loop_harness-0.3.1/agent-tasks/0116-receipt-link-agreement-validation.md +163 -0
  8. project_loop_harness-0.3.1/agent-tasks/0117-markdown-target-refresh-command.md +76 -0
  9. project_loop_harness-0.3.1/agent-tasks/0118-canonical-target-bound-handoff-docs.md +64 -0
  10. project_loop_harness-0.3.1/agent-tasks/0119-context-check-preflight.md +145 -0
  11. project_loop_harness-0.3.1/agent-tasks/0120-pcl-finish-terminal-closeout.md +140 -0
  12. project_loop_harness-0.3.1/agent-tasks/0121-human-gate-japanese-guidance.md +61 -0
  13. project_loop_harness-0.3.1/agent-tasks/0122-feature-coverage-noop.md +80 -0
  14. project_loop_harness-0.3.1/agent-tasks/README.md +55 -0
  15. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/adoption-guide.md +19 -0
  16. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/code-context.md +54 -6
  17. project_loop_harness-0.3.1/docs/context-check.md +74 -0
  18. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/context-pack.md +46 -18
  19. project_loop_harness-0.3.1/docs/finish.md +75 -0
  20. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/growth-plan-v0.2.4-v0.5.md +43 -1
  21. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/release-notes/v0.2.4.md +12 -2
  22. project_loop_harness-0.3.1/docs/release-notes/v0.3.0.md +90 -0
  23. project_loop_harness-0.3.1/docs/release-notes/v0.3.1.md +89 -0
  24. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/pyproject.toml +1 -1
  25. project_loop_harness-0.3.1/src/pcl/__init__.py +1 -0
  26. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/cli.py +150 -1
  27. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/impact.py +94 -1
  28. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/receipts.py +40 -2
  29. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/commands.py +308 -78
  30. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/context.py +473 -18
  31. project_loop_harness-0.3.1/src/pcl/context_binding.py +20 -0
  32. project_loop_harness-0.3.1/src/pcl/db/migrations/007_evidence_links.sql +19 -0
  33. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/db.py +1 -1
  34. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/evidence.py +86 -1
  35. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/locales.py +56 -0
  36. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/validators.py +97 -1
  37. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/workflows.py +37 -0
  38. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1/src/project_loop_harness.egg-info}/PKG-INFO +28 -1
  39. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/SOURCES.txt +20 -0
  40. project_loop_harness-0.3.1/tests/fixtures/context_pack_code_context_contract_v0.json +441 -0
  41. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_cli_init.py +7 -4
  42. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_code_index.py +187 -1
  43. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_context.py +585 -15
  44. project_loop_harness-0.3.1/tests/test_context_check.py +517 -0
  45. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_evidence_add.py +120 -0
  46. project_loop_harness-0.3.1/tests/test_finish.py +222 -0
  47. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_migrations.py +179 -50
  48. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_next_actions.py +62 -0
  49. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_validation.py +193 -0
  50. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_workflows.py +96 -0
  51. project_loop_harness-0.2.4/agent-tasks/README.md +0 -35
  52. project_loop_harness-0.2.4/src/pcl/__init__.py +0 -1
  53. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/LICENSE +0 -0
  54. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/MANIFEST.in +0 -0
  55. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/Makefile +0 -0
  56. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0001-hardening-cli.md +0 -0
  57. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0002-db-migrations.md +0 -0
  58. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0003-workflow-runner.md +0 -0
  59. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0004-dashboard-renderer.md +0 -0
  60. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0005-agent-integration.md +0 -0
  61. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0006-codex-plugin.md +0 -0
  62. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0007-mcp-server.md +0 -0
  63. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0008-loop-lifecycle.md +0 -0
  64. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0009-defect-lifecycle.md +0 -0
  65. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0010-reporting-evidence.md +0 -0
  66. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0011-validation-invariants.md +0 -0
  67. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0012-audit-log-integrity.md +0 -0
  68. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0013-validation-diagnostics.md +0 -0
  69. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0014-escalation-lifecycle.md +0 -0
  70. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0015-decision-lifecycle.md +0 -0
  71. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0016-escalation-decision-linkage.md +0 -0
  72. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0017-next-action-guided-loop.md +0 -0
  73. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0018-readme-golden-path.md +0 -0
  74. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0019-recovery-playbook.md +0 -0
  75. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0020-example-project-refresh.md +0 -0
  76. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0021-agent-adapter-contract.md +0 -0
  77. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0022-agent-output-validation.md +0 -0
  78. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0023-codex-exec-adapter-hardening.md +0 -0
  79. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0024-claude-manual-adapter-hardening.md +0 -0
  80. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0025-generic-shell-adapter.md +0 -0
  81. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0026-agent-job-evidence-ingestion.md +0 -0
  82. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0027-dashboard-data-contract.md +0 -0
  83. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0028-dashboard-evidence-navigation.md +0 -0
  84. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0029-dashboard-risk-and-blockers.md +0 -0
  85. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0030-distribution-readiness.md +0 -0
  86. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0031-workflow-proposal-mode.md +0 -0
  87. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0032-workflow-proposal-review.md +0 -0
  88. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0033-workflow-verifier.md +0 -0
  89. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0034-limited-execution-sandbox.md +0 -0
  90. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0035-automatic-workflow-executor.md +0 -0
  91. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0036-executor-dogfood-workflow.md +0 -0
  92. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0037-executor-retry-resume.md +0 -0
  93. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0038-story-test-lifecycle.md +0 -0
  94. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0039-workflow-yaml-rule-expressions.md +0 -0
  95. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0040-test-case-evidence-validation.md +0 -0
  96. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0041-feature-inspection-commands.md +0 -0
  97. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0042-report-coverage-context.md +0 -0
  98. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0043-feature-report.md +0 -0
  99. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0044-complete-csv-export.md +0 -0
  100. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0045-filtered-job-inspection.md +0 -0
  101. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0046-feature-status-lifecycle.md +0 -0
  102. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0047-feature-coverage-next-action.md +0 -0
  103. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0048-migration-status-command.md +0 -0
  104. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0049-render-json-artifact-paths.md +0 -0
  105. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0050-codex-plugin-package-inventory.md +0 -0
  106. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0051-mcp-render-artifact-paths.md +0 -0
  107. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0052-lifecycle-failure-job-cleanup.md +0 -0
  108. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0053-prompt-job-json-handoff.md +0 -0
  109. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0054-human-queue-linkage-cli.md +0 -0
  110. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0055-workflow-proposal-list-filter.md +0 -0
  111. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0056-sandbox-noop-execution-guard.md +0 -0
  112. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0057-executor-no-executable-step-guard.md +0 -0
  113. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0058-dogfood-usability-hardening.md +0 -0
  114. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0059-checkpoint-review-guidance.md +0 -0
  115. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0060-pypi-trusted-publishing.md +0 -0
  116. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0061-context-pack-v1.md +0 -0
  117. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0062-task-backlog-entity.md +0 -0
  118. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0063-structured-verification-rubric.md +0 -0
  119. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0064-task-loop-integration.md +0 -0
  120. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0065-dashboard-human-decisions.md +0 -0
  121. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0066-agent-registry-lease.md +0 -0
  122. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0067-context-pack-improvements.md +0 -0
  123. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0068-trust-hardening.md +0 -0
  124. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0069-explainable-code-context-v0.md +0 -0
  125. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0070-human-decision-cockpit.md +0 -0
  126. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0071-dogfood-impact-precision.md +0 -0
  127. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0072-sensitive-omission.md +0 -0
  128. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0073-code-context-module-split.md +0 -0
  129. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0074-search-snapshot-consistency.md +0 -0
  130. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0075-diff-source-modes.md +0 -0
  131. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0076-schema-version-integrity.md +0 -0
  132. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0077-index-output-budget-and-impact-noise.md +0 -0
  133. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0078-context-pack-code-context-bridge.md +0 -0
  134. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0079-receipt-human-summary.md +0 -0
  135. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0080-retrieval-eval-gate.md +0 -0
  136. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0081-diff-modes-completion.md +0 -0
  137. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0082-receipt-relevance-and-age.md +0 -0
  138. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0083-required-section-invariant.md +0 -0
  139. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0084-source-commands-honesty.md +0 -0
  140. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0085-distribution-source-completeness.md +0 -0
  141. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0086-command-surface-alignment.md +0 -0
  142. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0087-verification-suggestion-ids.md +0 -0
  143. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0088-verification-feedback.md +0 -0
  144. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0089-dogfood-fixture-propose.md +0 -0
  145. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0090-eval-baseline-record-compare.md +0 -0
  146. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0091-refresh-command-scope-fidelity.md +0 -0
  147. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0092-idempotent-status-transitions.md +0 -0
  148. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0093-evidence-add-command.md +0 -0
  149. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0094-job-completion-evidence.md +0 -0
  150. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0095-supporting-evidence-health.md +0 -0
  151. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0096-evidence-add-path-guards.md +0 -0
  152. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0097-evidence-durability-design.md +0 -0
  153. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0098-field-feedback-next-weight-and-run-report-scope.md +0 -0
  154. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0099-evidence-copy-mode.md +0 -0
  155. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0100-evidence-task-linking.md +0 -0
  156. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0101-evidence-id-allocation-race.md +0 -0
  157. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0102-source-drift-health-warning.md +0 -0
  158. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0103-security-policy-v02x.md +0 -0
  159. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0104-python-ci-matrix.md +0 -0
  160. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0105-evidence-copy-observability.md +0 -0
  161. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0106-release-checklist.md +0 -0
  162. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/agent-tasks/0107-agent-tasks-backlog-index.md +0 -0
  163. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/adr/0001-hybrid-state.md +0 -0
  164. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/adr/0002-cli-is-the-runtime.md +0 -0
  165. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/adr/0003-static-workflows-before-dynamic-workflows.md +0 -0
  166. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/agent-adapter-contract.md +0 -0
  167. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/agent-output-template.md +0 -0
  168. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/agent-roles.md +0 -0
  169. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/architecture.md +0 -0
  170. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/dashboard-data-contract.md +0 -0
  171. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/dashboard-design.md +0 -0
  172. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/data-model.md +0 -0
  173. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/distribution.md +0 -0
  174. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/evidence-durability-design.md +0 -0
  175. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/evidence-entry-paths-design.md +0 -0
  176. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/feedback/2026-07-06-ax1-moc1-agent-feedback.md +0 -0
  177. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/golden-path.md +0 -0
  178. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/implementation-plan.md +0 -0
  179. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/master-trace-handoff.md +0 -0
  180. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/plh_v0_1_11_review_agenda.md +0 -0
  181. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/plh_v0_1_12_review_agenda.md +0 -0
  182. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/pypi-publishing.md +0 -0
  183. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/recovery-playbook.md +0 -0
  184. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/release-checklist.md +0 -0
  185. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/safety-permissions.md +0 -0
  186. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/v0.2.0-plan.md +0 -0
  187. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/verification-feedback-design.md +0 -0
  188. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/verification-feedback.md +0 -0
  189. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/verification-rubric.md +0 -0
  190. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/docs/workflow-contract.md +0 -0
  191. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/scripts/run_advisory_retrieval_eval.py +0 -0
  192. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/scripts/verify_sdist_contracts.py +0 -0
  193. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/setup.cfg +0 -0
  194. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/__main__.py +0 -0
  195. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/agents.py +0 -0
  196. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/checkpoints.py +0 -0
  197. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/__init__.py +0 -0
  198. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/diff.py +0 -0
  199. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/eval.py +0 -0
  200. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/scan.py +0 -0
  201. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/search.py +0 -0
  202. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/store.py +0 -0
  203. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/summary.py +0 -0
  204. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/symbols.py +0 -0
  205. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_context/test_hints.py +0 -0
  206. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/code_index.py +0 -0
  207. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/db/migrations/001_initial.sql +0 -0
  208. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/db/migrations/002_tasks.sql +0 -0
  209. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/db/migrations/003_agent_registry.sql +0 -0
  210. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/db/migrations/004_code_index.sql +0 -0
  211. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/db/migrations/005_verification_feedback.sql +0 -0
  212. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/db/migrations/006_evidence_task_link.sql +0 -0
  213. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/db/schema.sql +0 -0
  214. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/decisions.py +0 -0
  215. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/dispatch.py +0 -0
  216. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/errors.py +0 -0
  217. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/escalations.py +0 -0
  218. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/events.py +0 -0
  219. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/exporters.py +0 -0
  220. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/guards.py +0 -0
  221. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/ids.py +0 -0
  222. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/init_project.py +0 -0
  223. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/lifecycle.py +0 -0
  224. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/links.py +0 -0
  225. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/mcp_server.py +0 -0
  226. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/migrations.py +0 -0
  227. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/paths.py +0 -0
  228. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/receipt_show.py +0 -0
  229. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/registry.py +0 -0
  230. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/renderer.py +0 -0
  231. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/reports.py +0 -0
  232. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/resources.py +0 -0
  233. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/rubric.py +0 -0
  234. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/stories.py +0 -0
  235. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/tasks.py +0 -0
  236. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/dashboard/dashboard.html +0 -0
  237. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/project/AGENTS.block.md +0 -0
  238. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/project/CLAUDE.block.md +0 -0
  239. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/project/gitignore.fragment +0 -0
  240. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/project/pcl.yaml +0 -0
  241. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/skills/project-control-loop/SKILL.md +0 -0
  242. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/workflows/defect_repair.yaml +0 -0
  243. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/workflows/executor_smoke.yaml +0 -0
  244. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/workflows/feature_coverage.yaml +0 -0
  245. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/templates/workflows/regression_loop.yaml +0 -0
  246. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/timeutil.py +0 -0
  247. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/token_estimation.py +0 -0
  248. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/update_check.py +0 -0
  249. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/verification_feedback.py +0 -0
  250. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/verifications.py +0 -0
  251. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/workflow_executor.py +0 -0
  252. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/workflow_proposal_validation.py +0 -0
  253. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/workflow_proposals.py +0 -0
  254. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/workflow_sandbox.py +0 -0
  255. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/workflow_verifier.py +0 -0
  256. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/pcl/workflow_yaml.py +0 -0
  257. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/dependency_links.txt +0 -0
  258. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/entry_points.txt +0 -0
  259. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/requires.txt +0 -0
  260. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/src/project_loop_harness.egg-info/top_level.txt +0 -0
  261. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/fixtures/code_context_summary_v0.json +0 -0
  262. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/fixtures/context_receipt_v0.json +0 -0
  263. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/fixtures/context_receipt_v0_legacy_string_suggestions.json +0 -0
  264. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/fixtures/retrieval_adversarial_v0.json +0 -0
  265. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/fixtures/retrieval_real_history_v0.json +0 -0
  266. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/fixtures/retrieval_v0.json +0 -0
  267. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_advisory_retrieval_eval_script.py +0 -0
  268. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_agent_adapter_contract.py +0 -0
  269. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_agent_output_validation.py +0 -0
  270. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_agents.py +0 -0
  271. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_audit_log_integrity.py +0 -0
  272. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_checkpoints.py +0 -0
  273. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_claude_manual_adapter.py +0 -0
  274. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_code_context_summary.py +0 -0
  275. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_codex_exec_adapter.py +0 -0
  276. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_codex_plugin.py +0 -0
  277. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_dashboard.py +0 -0
  278. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_dashboard_data_contract.py +0 -0
  279. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_decisions.py +0 -0
  280. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_defects.py +0 -0
  281. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_dispatch.py +0 -0
  282. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_distribution.py +0 -0
  283. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_escalations.py +0 -0
  284. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_examples.py +0 -0
  285. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_features.py +0 -0
  286. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_generic_shell_adapter.py +0 -0
  287. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_golden_path.py +0 -0
  288. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_lifecycle.py +0 -0
  289. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_mcp_server.py +0 -0
  290. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_pypi_publishing.py +0 -0
  291. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_receipt_show.py +0 -0
  292. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_recovery_playbook.py +0 -0
  293. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_registry.py +0 -0
  294. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_reports.py +0 -0
  295. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_rubric.py +0 -0
  296. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_stories.py +0 -0
  297. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_tasks.py +0 -0
  298. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_update_check.py +0 -0
  299. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_validation_diagnostics.py +0 -0
  300. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_verification_feedback.py +0 -0
  301. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_workflow_executor.py +0 -0
  302. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_workflow_proposals.py +0 -0
  303. {project_loop_harness-0.2.4 → project_loop_harness-0.3.1}/tests/test_workflow_sandbox.py +0 -0
  304. {project_loop_harness-0.2.4 → 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.2.4
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,152 @@
1
+ # 0108: Target-bound code context receipts
2
+
3
+ Milestone: v0.3.0 Target-Bound Context
4
+ Priority: P1
5
+ Area: code-context/context-pack
6
+ Origin: docs/growth-plan-v0.2.4-v0.5.md v0.3.0; docs/project-loop-harness-v0.2.3-third-party-review.md P2-3
7
+ Depends on: 0113 (evidence_links table, migration 007) — merge first.
8
+
9
+ > **Revision 2026-07-08 (坂本承認):** the original no-migration invariant is
10
+ > **retracted**. Target binding is now persisted as a queryable `evidence_links`
11
+ > row (`link_role="code_context"`, from 0113) **and** embedded in the receipt
12
+ > artifact; receipt selection is a SQL query, not an artifact scan. This unblocks
13
+ > `pcl context check` (v0.3.1) and v0.4 `bound_receipt_coverage` without a second
14
+ > migration later.
15
+
16
+ ## Problem
17
+
18
+ `pcl context pack --include-code-context` currently reads the latest
19
+ `context_receipt` evidence row. The pack tells the reader that this is
20
+ `scope: "unscoped_latest"` with `binding_strength: "none"`, which is honest,
21
+ but it still risks handing a worker a receipt from an unrelated task or job.
22
+
23
+ The existing docs reserve `scope: "target_bound"` and
24
+ `binding_strength: "caller_asserted"`, but there is no command path that
25
+ creates or requires such a receipt. v0.3.0 turns that reserved contract into a
26
+ narrow, explicit handoff workflow, backed by queryable link state.
27
+
28
+ ## Scope
29
+
30
+ 1. Extend `pcl impact --diff` with explicit target flags:
31
+ - `--for-task T-XXXX`
32
+ - `--for-job J-XXXX`
33
+ Exactly zero or one target flag is allowed. Existing diff mode flags
34
+ (`--base`, `--staged`, `--unstaged`, `--include-untracked`,
35
+ `--all-changes`, and provided diff input) keep their current semantics.
36
+ 2. Validate the named target before writing a receipt. Missing or malformed
37
+ target IDs must fail with a typed error and must not create evidence or an
38
+ `evidence_links` row.
39
+ 3. When a target flag is present, record the binding in **two** places, in the
40
+ same transaction that writes the receipt evidence:
41
+ - An `evidence_links` row (0113 helper): `(evidence_id=<receipt>,
42
+ target_type, target_id, link_role="code_context", created_at)`, where
43
+ `target_type` is `task` or `agent_job`.
44
+ - Target binding metadata inside the `impact/v0` response and the
45
+ `context-receipt/v0` artifact so the receipt is self-describing:
46
+ ```json
47
+ {
48
+ "target_binding": {
49
+ "target_type": "task",
50
+ "target_id": "T-0001",
51
+ "binding_strength": "caller_asserted",
52
+ "source": "impact_flag"
53
+ }
54
+ }
55
+ ```
56
+ For job targets, use `target_type: "agent_job"`. The link row and the
57
+ artifact `target_binding` must agree.
58
+ 4. Update context-pack receipt selection when `--include-code-context` is used.
59
+ Selection is a **query on `evidence_links`** (0113 helper), not an artifact
60
+ scan:
61
+ - For a task pack, prefer the newest receipt evidence with a matching
62
+ `evidence_links` row `(target_type="task", target_id=<task>,
63
+ link_role="code_context")`.
64
+ - For a job pack, prefer the newest matching
65
+ `(target_type="agent_job", target_id=<job>, link_role="code_context")`.
66
+ - If no matching bound receipt exists, preserve the current unscoped latest
67
+ fallback unless the caller requires a bound receipt.
68
+ 5. Add `pcl context pack --require-bound-receipt`, valid only with
69
+ `--include-code-context`. When no matching bound receipt exists, fail with a
70
+ typed error `context_pack_bound_receipt_required` and include a
71
+ target-specific refresh suggestion:
72
+ - `pcl impact --diff --for-task T-XXXX --json`
73
+ - `pcl impact --diff --for-job J-XXXX --json`
74
+ 6. Update `code_context.relevance` in the embedded summary:
75
+ - Matching bound receipt: `scope: "target_bound"`,
76
+ `binding_strength: "caller_asserted"`, plus `target_type` and
77
+ `target_id`.
78
+ - Unbound fallback: keep `scope: "unscoped_latest"` and
79
+ `binding_strength: "none"` with an explicit warning.
80
+ - Missing receipt: keep `scope: "missing_receipt"` and
81
+ `binding_strength: "none"`.
82
+ 7. Update docs and CLI help for `docs/code-context.md`,
83
+ `docs/context-pack.md`, and relevant tests.
84
+
85
+ ## Invariants (what to protect, on the normal paths)
86
+
87
+ - Binding is recorded in lockstep: when a target flag is given, the receipt
88
+ evidence row, its `evidence_links` `code_context` row, and the artifact
89
+ `target_binding` are written in one transaction and must agree. Never write
90
+ the link row without the receipt, or an artifact `target_binding` without the
91
+ link row.
92
+ - Binding is a **caller assertion**, not PLH proof that the receipt is
93
+ semantically relevant. Use claims-not-facts vocabulary; do not add fields such
94
+ as `safe_to_continue`, `verified_relevant`, or `agent_read`.
95
+ - Extend `impact/v0`, `context-receipt/v0`, and `context-pack/v1` **additively**
96
+ via the `code-context-summary/v0` insulation layer (0078). The pack embeds the
97
+ summary and `receipt_ref` (evidence_id / receipt_path) only — never the full
98
+ receipt body or copied evidence contents.
99
+ - `pcl context pack` remains read-only: it must not run `pcl index build`,
100
+ `pcl impact`, Git commands, tests, or any artifact-generating command. It
101
+ reads `evidence_links` and evidence rows only.
102
+ - `source_commands` remain read-only re-fetch commands. Artifact-generating
103
+ commands (`pcl impact …`) appear only under `suggested_refresh_commands`.
104
+ - Existing unscoped latest behavior remains available when
105
+ `--require-bound-receipt` is absent.
106
+ - Deterministic generated artifacts stay deterministic; timestamped facts remain
107
+ in receipt/evidence payloads where timestamps already exist.
108
+
109
+ ## Non-scope
110
+
111
+ - Semantic or embedding-based relevance proof.
112
+ - Automatic target inference from changed files, branches, or task text.
113
+ - `pcl context pack --receipt ...` manual receipt selection.
114
+ - `pcl receipt list` / `pcl evidence link` CLI verbs.
115
+ - Dashboard redesign or MCP surface changes.
116
+ - Hosted code analysis, cloud sync, telemetry, or external LLM calls.
117
+ - `pcl context check` preflight (deferred to v0.3.1).
118
+
119
+ ## Acceptance
120
+
121
+ - `pcl impact --diff --for-task T-0001 --json` writes a receipt with
122
+ `target_binding.target_type == "task"` and `target_id == "T-0001"`, and an
123
+ `evidence_links` row `(target_type="task", target_id="T-0001",
124
+ link_role="code_context")`.
125
+ - `pcl impact --diff --for-job J-0001 --json` writes a receipt with
126
+ `target_binding.target_type == "agent_job"` and `target_id == "J-0001"`, and
127
+ the matching `code_context` link row.
128
+ - Invalid target IDs and mutually exclusive target flags fail with typed errors
129
+ before any evidence or link row is created.
130
+ - `pcl context pack --task T-0001 --include-code-context --json` chooses the
131
+ newest matching task-bound receipt over a newer unbound receipt, via the
132
+ `evidence_links` query.
133
+ - `pcl context pack --job J-0001 --include-code-context --json` chooses the
134
+ newest matching job-bound receipt over a newer unbound receipt.
135
+ - Without a matching bound receipt and without `--require-bound-receipt`,
136
+ context pack still succeeds with the existing unscoped latest warning and a
137
+ target-specific suggested refresh command.
138
+ - With `--require-bound-receipt` and no matching bound receipt, context pack
139
+ fails with `context_pack_bound_receipt_required` and does not silently fall
140
+ back to unscoped latest.
141
+ - `source_commands` for code-context packs still contain only read-only
142
+ commands; `pcl impact` appears only under `suggested_refresh_commands`.
143
+ - Full `pytest` green.
144
+ - Live smoke in a scratch project:
145
+ 1. `pcl init`
146
+ 2. create a goal and task
147
+ 3. `pcl index build --json`
148
+ 4. make a small tracked change
149
+ 5. `pcl impact --diff --for-task T-0001 --json`
150
+ 6. `pcl context pack --task T-0001 --include-code-context --require-bound-receipt --json`
151
+ 7. `pcl validate --strict --json`
152
+ 8. `pcl render --json`
@@ -0,0 +1,118 @@
1
+ # 0113: Generic evidence links table (migration 007)
2
+
3
+ Milestone: v0.3.0 Target-Bound Context
4
+ Priority: P1
5
+ Area: schema/evidence
6
+ Origin: docs/growth-plan-v0.2.4-v0.5.md v0.3.0; third-party review 議題1 — migration
7
+ approved and 0108 no-migration invariant retracted (Sakamoto approved 2026-07-08).
8
+
9
+ ## Problem
10
+
11
+ Evidence-to-target linkage is currently a single `evidence.linked_task_id`
12
+ column (migration 006), which can only express "supporting evidence for a
13
+ task". v0.3.0 introduces a second link role — a code-context receipt bound
14
+ to a task or job (0108) — and v0.3.2 will add master-trace / intent-index
15
+ roles. A single typed column cannot express a role, and adding one column per
16
+ target type (`linked_job_id`, `linked_goal_id`, and so on) sprawls.
17
+
18
+ Introduce a generic, queryable `evidence_links` table so target-bound receipt
19
+ selection (0108), `pcl context check` (v0.3.1), and v0.4 coverage KPIs become
20
+ SQL queries rather than artifact scans. This is a control-plane primitive, not
21
+ a per-feature column.
22
+
23
+ ## Scope
24
+
25
+ 1. Add migration `007_evidence_links.sql`:
26
+ ```sql
27
+ PRAGMA foreign_keys = ON;
28
+
29
+ CREATE TABLE IF NOT EXISTS evidence_links (
30
+ evidence_id TEXT NOT NULL REFERENCES evidence(id),
31
+ target_type TEXT NOT NULL,
32
+ target_id TEXT NOT NULL,
33
+ link_role TEXT NOT NULL,
34
+ created_at TEXT NOT NULL,
35
+ PRIMARY KEY (evidence_id, target_type, target_id, link_role)
36
+ );
37
+
38
+ CREATE INDEX IF NOT EXISTS idx_evidence_links_target
39
+ ON evidence_links(target_type, target_id, link_role, created_at);
40
+
41
+ -- Backfill existing task-linked evidence as role 'supporting'.
42
+ INSERT OR IGNORE INTO evidence_links(evidence_id, target_type, target_id, link_role, created_at)
43
+ SELECT id, 'task', linked_task_id, 'supporting', created_at
44
+ FROM evidence
45
+ WHERE linked_task_id IS NOT NULL;
46
+ ```
47
+ Vocabulary in use now: `target_type` is `task` or `agent_job`;
48
+ `link_role` is `supporting` or `code_context`. Reserve (do not emit yet)
49
+ `goal` / `workflow_run` / `decision` / `escalation` and
50
+ `master_trace` / `intent_index` / `worker_output`.
51
+ 2. Write path: `pcl evidence add --task T-XXXX` (evidence.py) keeps setting the
52
+ `evidence.linked_task_id` column (0.x compat) and also inserts an
53
+ `evidence_links` row `(evidence_id, 'task', task_id, 'supporting', now)` in
54
+ the same transaction, before the existing `append_event`.
55
+ 3. Read path: `context.py._linked_task_evidence` selects from `evidence_links`
56
+ where `target_type='task' AND link_role='supporting'`, joined to `evidence`
57
+ for the display columns, ordered `created_at, evidence_id`. When the
58
+ `evidence_links` table is absent (pre-migration DB opened by a newer binary
59
+ mid-upgrade), fall back to the current `linked_task_id` column query. Output
60
+ shape, ordering, and member/stored-path resolution are unchanged.
61
+ 4. Strict validation (`validators.py`): add a dangling-link check modeled on the
62
+ verification `receipt_evidence_id` check (validators.py:596) — every
63
+ `evidence_links.evidence_id` must resolve to an existing evidence row (the
64
+ existing `PRAGMA foreign_key_check` already covers this; keep an explicit,
65
+ message-consistent check too), and for known target types the `target_id`
66
+ must exist (`task` maps to `tasks`, `agent_job` maps to `agent_jobs`).
67
+ Unknown `target_type` values are tolerated with no error (forward
68
+ compatibility).
69
+ 5. Provide two small internal helpers for 0108 to reuse (no new CLI surface):
70
+ insert a link row, and select the newest `evidence_id` for a given
71
+ `(target_type, target_id, link_role)`.
72
+
73
+ ## Invariants (what to protect, on the normal paths)
74
+
75
+ - The canonical write path for a task-linked ad-hoc evidence is, in one
76
+ transaction: the `evidence` row plus the `linked_task_id` column plus the
77
+ `evidence_links` row plus the `adhoc_evidence_recorded` event. Do not drop the
78
+ `linked_task_id` column write (compat). Do not write an `evidence_links` row
79
+ without its mirroring `evidence` row.
80
+ - The migration backfill is idempotent (`INSERT OR IGNORE`) and additive: it
81
+ must not update or delete any `evidence` row, and re-running `pcl migrate`
82
+ must be a no-op.
83
+ - `evidence_links` is written only through `pcl` (evidence add today, 0108
84
+ tomorrow). No command deletes links in this task; no raw-SQL mutation path.
85
+ - The existing task context-pack `linked_evidence` output — shape, ordering,
86
+ member/stored paths — is unchanged for existing DBs after backfill.
87
+ - Additive only: no existing table or column is dropped or repurposed. Schema
88
+ version advances 6 to 7; `never-downgrade` and DB-ahead typed rejection (0076)
89
+ continue to hold.
90
+
91
+ ## Non-scope
92
+
93
+ - `pcl evidence link` / `unlink` CLI verbs (links are written implicitly by
94
+ `evidence add` and, in 0108, by `impact --for-task/--for-job`).
95
+ - Job / goal / decision linking commands beyond the helper 0108 needs.
96
+ - Dashboard changes. The existing `heading_evidence_links` locale string is an
97
+ unrelated UI heading, not this table.
98
+ - Removing or deprecating `linked_task_id` (deferred past 0.x).
99
+ - Reading `evidence_links` from the code-context receipt selection path (that is
100
+ 0108).
101
+
102
+ ## Acceptance
103
+
104
+ - Fresh `pcl init` gives schema v7, `evidence_links` present,
105
+ `pcl validate --strict --json` green.
106
+ - A v6 to v7 live migration backfills every `linked_task_id` row into
107
+ `evidence_links` as role `supporting`; backfilled row count equals the number
108
+ of non-null `linked_task_id` rows; a second `pcl migrate` changes nothing.
109
+ - `pcl evidence add --task T-0001` writes both the column and the
110
+ `evidence_links` row; the task context pack lists the evidence identically to
111
+ before.
112
+ - A hand-broken dangling link (an `evidence_links` row whose `target_type='task'`
113
+ `target_id` has no matching task) is reported by `validate --strict`; a row
114
+ with an unknown `target_type` is tolerated (no error).
115
+ - An older (v6-aware) `pcl` binary typed-rejects a v7 DB with
116
+ `schema_version_ahead` (0076 behavior preserved).
117
+ - Full `pytest` green; live smoke in a scratch project (`init`, then `evidence
118
+ add --task`, then `validate --strict`, then context pack).
@@ -0,0 +1,78 @@
1
+ # 0114: Source hash drift detection for copied evidence
2
+
3
+ Milestone: v0.3.0 Target-Bound Context
4
+ Priority: P2
5
+ Area: evidence
6
+ Origin: docs/growth-plan-v0.2.4-v0.5.md 論点2; third-party review P1 / 議題2 —
7
+ default-on approved (坂本承認 2026-07-08). Extends 0102.
8
+
9
+ ## Problem
10
+
11
+ `_collect_copied_member_findings` in `src/pcl/evidence.py` (the source-freshness
12
+ block at evidence.py:589-605) detects source drift only via `detail: "missing"`
13
+ and `detail: "size_mismatch"`. A **same-size content change** to the source
14
+ file is undetected: `source_drifted` never fires, so a copied evidence member
15
+ whose origin was silently rewritten to a different-but-equal-length body reads
16
+ as fresh. The recorded member `sha256` (`expected_sha256`) is already a
17
+ parameter of this function (evidence.py:545) but is never compared against the
18
+ current source.
19
+
20
+ 0102 already classifies `source_drifted` as an evidence-health **warning**, so
21
+ closing this gap needs no health-model change — only the missing hash
22
+ comparison.
23
+
24
+ ## Scope
25
+
26
+ 1. In `_collect_copied_member_findings`, extend the `else` branch that currently
27
+ only handles the size check: when the source exists **and**
28
+ `source_stat.st_size == size_bytes`, compute the source file sha256 (reuse
29
+ `_sha256_file`, evidence.py:907) and compare to `expected_sha256`.
30
+ - Mismatch → append `{"code": "source_drifted", "path": member_path,
31
+ "detail": "hash_mismatch"}`.
32
+ - `OSError` while reading the source → treat as unreadable and reuse the
33
+ existing `detail: "missing"` finding (do not crash, do not add a new code).
34
+ 2. Default-on, no `--deep` flag. The hash is computed **only** in the same-size
35
+ branch, so `missing` and `size_mismatch` stay the cheap fast paths. The
36
+ `copy_max_member_bytes` cap (10MB, 0097) bounds per-member cost.
37
+ 3. Confirm the `validators.py` `source_drifted` rendering branch (the
38
+ `elif code == "source_drifted":` branch, ~line 977) renders the new
39
+ `hash_mismatch` detail consistently through the shared
40
+ `assess_adhoc_evidence` path (0095 pattern) — health stays `warning`.
41
+
42
+ ## Invariants (what to protect, on the normal paths)
43
+
44
+ - Read-only assessment: no finding rewrites or removes copied artifacts under
45
+ `.project-loop/evidence/adhoc-files/` or any source file.
46
+ - Findings shape is additive-only: `source_drifted` gains one new `detail`
47
+ value, `hash_mismatch`. Existing `missing` / `size_mismatch` details, their
48
+ `path` field, and ordering are unchanged.
49
+ - Copied-artifact health stays semantically **separate** from source freshness
50
+ in wording (0102 invariant): `copy_hash_mismatch` = the copied artifact broke;
51
+ `source_drifted/hash_mismatch` = the origin changed since the copy. Do not
52
+ merge or cross-reference the two codes.
53
+ - Health stays the three-level `ok | warning | error`; no `artifact_health` /
54
+ `source_health` split (still deferred until dogfood `source_drift_rate` data).
55
+
56
+ ## Non-scope
57
+
58
+ - A `--deep` / lightweight-vs-deep mode split (unnecessary: the size gate plus
59
+ the 10MB member cap already bound cost).
60
+ - Hashing sources of **reference** (non-copied) members — reference members are
61
+ already hash-checked against the source directly by `_assess_reference_member`.
62
+ - `artifact_health` / `source_health` field separation.
63
+
64
+ ## Acceptance
65
+
66
+ - Test: copied artifact intact + source rewritten to different content of the
67
+ **same byte length** → `health: "warning"` with a `source_drifted` finding,
68
+ `detail: "hash_mismatch"`.
69
+ - Test: copied artifact intact + source intact → `health: "ok"` (no regression).
70
+ - Test: `copy_hash_mismatch` (artifact corrupted) + `source_drifted/hash_mismatch`
71
+ co-occur → still `warning`, both findings present, no double-count crash.
72
+ - `pcl validate --strict --json` treats `source_drifted/hash_mismatch` as a
73
+ warning that remains a warning under strict (extend
74
+ `_strict_warning_remains_warning` coverage) and stays green overall.
75
+ - Live smoke: in a scratch project, `evidence add --copy` a file, edit the
76
+ source to same-length different content, `pcl validate --strict --json` →
77
+ evidence health `warning`, detail `hash_mismatch`, strict `ok: true`.
78
+ - Full `pytest` green; release note entry describing the tightened semantics.
@@ -0,0 +1,72 @@
1
+ # 0115: Context pack target-bound contract fixtures
2
+
3
+ Milestone: v0.3.0 Target-Bound Context
4
+ Priority: P2
5
+ Area: context-pack/tests
6
+ Origin: docs/growth-plan-v0.2.4-v0.5.md v0.3.0; third-party review 0111 —
7
+ required in v0.3.0 (坂本承認 2026-07-08). Depends on 0108 and 0113.
8
+
9
+ ## Problem
10
+
11
+ 0108 changes the `context-pack/v1` code-context contract: `code_context.relevance`
12
+ gains `scope: "target_bound"` / `binding_strength: "caller_asserted"` with
13
+ `target_type` / `target_id`, a `receipt_ref`, a `--require-bound-receipt` typed
14
+ error, and target-specific `suggested_refresh_commands`. PLH has shipped three
15
+ contract regressions caught only in review (0087 git-status key loss, 0089
16
+ audit-mirror break, 0090 receipt-content storage). Freeze the v0.3.0 handoff
17
+ contract with deterministic fixture-based tests so future changes are provably
18
+ additive and any silent shape change fails a test.
19
+
20
+ ## Scope
21
+
22
+ Add fixture-backed tests covering six code-context selection states. Each
23
+ fixture asserts `included_sections`, the required / non-droppable safety
24
+ sections, `source_paths`, `suggested_refresh_commands`, and
25
+ `code_context.relevance`:
26
+
27
+ 1. **no receipt** — `scope: "missing_receipt"`, `binding_strength: "none"`.
28
+ 2. **unscoped latest only** — a receipt with no `target_binding`;
29
+ `scope: "unscoped_latest"`, `binding_strength: "none"`, with the existing
30
+ unscoped warning and a target-specific suggested refresh command.
31
+ 3. **matching task-bound receipt** — `scope: "target_bound"`,
32
+ `binding_strength: "caller_asserted"`, `target_type: "task"`, `target_id`
33
+ set; chosen over a newer unbound receipt.
34
+ 4. **matching job-bound receipt** — same as (3) with `target_type: "agent_job"`.
35
+ 5. **stale bound receipt** — a matching bound receipt old enough that the 0082
36
+ `age_warning` fires; relevance stays `target_bound` and the age warning is
37
+ present (staleness is a surfaced fact, not a downgrade).
38
+ 6. **require-bound missing** — `--require-bound-receipt` with no matching bound
39
+ receipt → typed error `context_pack_bound_receipt_required` with the
40
+ target-specific refresh suggestion; assert there is **no** silent fallback to
41
+ unscoped latest.
42
+
43
+ ## Invariants (what to protect, on the normal paths)
44
+
45
+ - Fixtures are byte-deterministic: inject `now` at the CLI boundary the way
46
+ existing pack tests do; no wall-clock reads inside generated artifacts.
47
+ - Budget truncation never drops required safety sections: the
48
+ `code_context_safety` pin (priority 10000, 0078/0083) survives a deliberately
49
+ tight budget — at least one fixture asserts this.
50
+ - Contract assertions are additive-only in spirit: adding a new field is
51
+ allowed; changing or removing an asserted field, shape, or ordering must fail
52
+ a fixture. Do not weaken an assertion to make a change pass.
53
+ - Fixtures must not inline receipt bodies or copied evidence file contents
54
+ (0090 boundary): assert `receipt_ref` carries `evidence_id` / `receipt_path`
55
+ only.
56
+
57
+ ## Non-scope
58
+
59
+ - Any new runtime behavior — this is a pure test / fixture task. If a fixture
60
+ reveals a 0108 defect, fix it in 0108, not here.
61
+ - Dashboard, MCP, or CLI-surface changes.
62
+ - Golden-file snapshotting of the entire pack (assert the contract-bearing
63
+ fields, not incidental whitespace).
64
+
65
+ ## Acceptance
66
+
67
+ - Six fixtures committed and green.
68
+ - A deliberate contract break (e.g., dropping `binding_strength` from
69
+ `relevance`, or letting `--require-bound-receipt` fall back silently) makes at
70
+ least one fixture fail with a clear message.
71
+ - The tight-budget fixture proves the safety section is never truncated away.
72
+ - Full `pytest` green.
@@ -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.