project-loop-harness 0.2.1__tar.gz → 0.2.3__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 (274) hide show
  1. {project_loop_harness-0.2.1/src/project_loop_harness.egg-info → project_loop_harness-0.2.3}/PKG-INFO +1 -1
  2. project_loop_harness-0.2.3/agent-tasks/0092-idempotent-status-transitions.md +78 -0
  3. project_loop_harness-0.2.3/agent-tasks/0093-evidence-add-command.md +95 -0
  4. project_loop_harness-0.2.3/agent-tasks/0094-job-completion-evidence.md +71 -0
  5. project_loop_harness-0.2.3/agent-tasks/0095-supporting-evidence-health.md +156 -0
  6. project_loop_harness-0.2.3/agent-tasks/0096-evidence-add-path-guards.md +185 -0
  7. project_loop_harness-0.2.3/agent-tasks/0097-evidence-durability-design.md +54 -0
  8. project_loop_harness-0.2.3/agent-tasks/0098-field-feedback-next-weight-and-run-report-scope.md +69 -0
  9. project_loop_harness-0.2.3/agent-tasks/0099-evidence-copy-mode.md +76 -0
  10. project_loop_harness-0.2.3/agent-tasks/0100-evidence-task-linking.md +57 -0
  11. project_loop_harness-0.2.3/agent-tasks/0101-evidence-id-allocation-race.md +49 -0
  12. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/agent-adapter-contract.md +7 -1
  13. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/context-pack.md +28 -8
  14. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/data-model.md +82 -2
  15. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/distribution.md +1 -1
  16. project_loop_harness-0.2.3/docs/evidence-durability-design.md +189 -0
  17. project_loop_harness-0.2.3/docs/evidence-entry-paths-design.md +146 -0
  18. project_loop_harness-0.2.3/docs/feedback/2026-07-06-ax1-moc1-agent-feedback.md +55 -0
  19. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/golden-path.md +8 -0
  20. project_loop_harness-0.2.3/docs/master-trace-handoff.md +169 -0
  21. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/verification-feedback.md +28 -0
  22. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/pyproject.toml +1 -1
  23. project_loop_harness-0.2.3/src/pcl/__init__.py +1 -0
  24. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/cli.py +94 -0
  25. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/commands.py +16 -10
  26. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/context.py +113 -0
  27. project_loop_harness-0.2.3/src/pcl/db/migrations/006_evidence_task_link.sql +5 -0
  28. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/db.py +4 -2
  29. project_loop_harness-0.2.3/src/pcl/evidence.py +939 -0
  30. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/ids.py +2 -0
  31. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/init_project.py +1 -0
  32. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/lifecycle.py +76 -12
  33. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/stories.py +18 -10
  34. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/tasks.py +11 -5
  35. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/skills/project-control-loop/SKILL.md +39 -0
  36. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/validators.py +140 -3
  37. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/verification_feedback.py +97 -1
  38. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/workflow_executor.py +6 -1
  39. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/workflow_sandbox.py +68 -21
  40. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/workflows.py +1 -1
  41. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3/src/project_loop_harness.egg-info}/PKG-INFO +1 -1
  42. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/project_loop_harness.egg-info/SOURCES.txt +16 -0
  43. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_cli_init.py +5 -4
  44. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_context.py +147 -0
  45. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_distribution.py +17 -9
  46. project_loop_harness-0.2.3/tests/test_evidence_add.py +1455 -0
  47. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_features.py +89 -4
  48. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_lifecycle.py +268 -1
  49. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_migrations.py +97 -53
  50. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_stories.py +120 -1
  51. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_tasks.py +118 -0
  52. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_verification_feedback.py +392 -0
  53. project_loop_harness-0.2.1/src/pcl/__init__.py +0 -1
  54. project_loop_harness-0.2.1/src/pcl/evidence.py +0 -25
  55. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/LICENSE +0 -0
  56. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/MANIFEST.in +0 -0
  57. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/Makefile +0 -0
  58. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/README.md +0 -0
  59. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0001-hardening-cli.md +0 -0
  60. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0002-db-migrations.md +0 -0
  61. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0003-workflow-runner.md +0 -0
  62. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0004-dashboard-renderer.md +0 -0
  63. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0005-agent-integration.md +0 -0
  64. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0006-codex-plugin.md +0 -0
  65. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0007-mcp-server.md +0 -0
  66. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0008-loop-lifecycle.md +0 -0
  67. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0009-defect-lifecycle.md +0 -0
  68. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0010-reporting-evidence.md +0 -0
  69. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0011-validation-invariants.md +0 -0
  70. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0012-audit-log-integrity.md +0 -0
  71. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0013-validation-diagnostics.md +0 -0
  72. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0014-escalation-lifecycle.md +0 -0
  73. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0015-decision-lifecycle.md +0 -0
  74. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0016-escalation-decision-linkage.md +0 -0
  75. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0017-next-action-guided-loop.md +0 -0
  76. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0018-readme-golden-path.md +0 -0
  77. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0019-recovery-playbook.md +0 -0
  78. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0020-example-project-refresh.md +0 -0
  79. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0021-agent-adapter-contract.md +0 -0
  80. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0022-agent-output-validation.md +0 -0
  81. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0023-codex-exec-adapter-hardening.md +0 -0
  82. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0024-claude-manual-adapter-hardening.md +0 -0
  83. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0025-generic-shell-adapter.md +0 -0
  84. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0026-agent-job-evidence-ingestion.md +0 -0
  85. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0027-dashboard-data-contract.md +0 -0
  86. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0028-dashboard-evidence-navigation.md +0 -0
  87. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0029-dashboard-risk-and-blockers.md +0 -0
  88. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0030-distribution-readiness.md +0 -0
  89. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0031-workflow-proposal-mode.md +0 -0
  90. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0032-workflow-proposal-review.md +0 -0
  91. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0033-workflow-verifier.md +0 -0
  92. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0034-limited-execution-sandbox.md +0 -0
  93. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0035-automatic-workflow-executor.md +0 -0
  94. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0036-executor-dogfood-workflow.md +0 -0
  95. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0037-executor-retry-resume.md +0 -0
  96. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0038-story-test-lifecycle.md +0 -0
  97. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0039-workflow-yaml-rule-expressions.md +0 -0
  98. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0040-test-case-evidence-validation.md +0 -0
  99. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0041-feature-inspection-commands.md +0 -0
  100. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0042-report-coverage-context.md +0 -0
  101. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0043-feature-report.md +0 -0
  102. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0044-complete-csv-export.md +0 -0
  103. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0045-filtered-job-inspection.md +0 -0
  104. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0046-feature-status-lifecycle.md +0 -0
  105. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0047-feature-coverage-next-action.md +0 -0
  106. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0048-migration-status-command.md +0 -0
  107. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0049-render-json-artifact-paths.md +0 -0
  108. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0050-codex-plugin-package-inventory.md +0 -0
  109. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0051-mcp-render-artifact-paths.md +0 -0
  110. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0052-lifecycle-failure-job-cleanup.md +0 -0
  111. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0053-prompt-job-json-handoff.md +0 -0
  112. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0054-human-queue-linkage-cli.md +0 -0
  113. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0055-workflow-proposal-list-filter.md +0 -0
  114. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0056-sandbox-noop-execution-guard.md +0 -0
  115. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0057-executor-no-executable-step-guard.md +0 -0
  116. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0058-dogfood-usability-hardening.md +0 -0
  117. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0059-checkpoint-review-guidance.md +0 -0
  118. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0060-pypi-trusted-publishing.md +0 -0
  119. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0061-context-pack-v1.md +0 -0
  120. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0062-task-backlog-entity.md +0 -0
  121. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0063-structured-verification-rubric.md +0 -0
  122. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0064-task-loop-integration.md +0 -0
  123. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0065-dashboard-human-decisions.md +0 -0
  124. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0066-agent-registry-lease.md +0 -0
  125. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0067-context-pack-improvements.md +0 -0
  126. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0068-trust-hardening.md +0 -0
  127. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0069-explainable-code-context-v0.md +0 -0
  128. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0070-human-decision-cockpit.md +0 -0
  129. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0071-dogfood-impact-precision.md +0 -0
  130. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0072-sensitive-omission.md +0 -0
  131. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0073-code-context-module-split.md +0 -0
  132. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0074-search-snapshot-consistency.md +0 -0
  133. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0075-diff-source-modes.md +0 -0
  134. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0076-schema-version-integrity.md +0 -0
  135. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0077-index-output-budget-and-impact-noise.md +0 -0
  136. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0078-context-pack-code-context-bridge.md +0 -0
  137. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0079-receipt-human-summary.md +0 -0
  138. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0080-retrieval-eval-gate.md +0 -0
  139. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0081-diff-modes-completion.md +0 -0
  140. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0082-receipt-relevance-and-age.md +0 -0
  141. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0083-required-section-invariant.md +0 -0
  142. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0084-source-commands-honesty.md +0 -0
  143. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0085-distribution-source-completeness.md +0 -0
  144. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0086-command-surface-alignment.md +0 -0
  145. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0087-verification-suggestion-ids.md +0 -0
  146. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0088-verification-feedback.md +0 -0
  147. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0089-dogfood-fixture-propose.md +0 -0
  148. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0090-eval-baseline-record-compare.md +0 -0
  149. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/agent-tasks/0091-refresh-command-scope-fidelity.md +0 -0
  150. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/adoption-guide.md +0 -0
  151. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/adr/0001-hybrid-state.md +0 -0
  152. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/adr/0002-cli-is-the-runtime.md +0 -0
  153. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/adr/0003-static-workflows-before-dynamic-workflows.md +0 -0
  154. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/agent-output-template.md +0 -0
  155. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/agent-roles.md +0 -0
  156. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/architecture.md +0 -0
  157. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/code-context.md +0 -0
  158. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/dashboard-data-contract.md +0 -0
  159. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/dashboard-design.md +0 -0
  160. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/implementation-plan.md +0 -0
  161. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/plh_v0_1_11_review_agenda.md +0 -0
  162. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/plh_v0_1_12_review_agenda.md +0 -0
  163. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/pypi-publishing.md +0 -0
  164. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/recovery-playbook.md +0 -0
  165. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/safety-permissions.md +0 -0
  166. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/v0.2.0-plan.md +0 -0
  167. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/verification-feedback-design.md +0 -0
  168. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/verification-rubric.md +0 -0
  169. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/docs/workflow-contract.md +0 -0
  170. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/scripts/run_advisory_retrieval_eval.py +0 -0
  171. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/scripts/verify_sdist_contracts.py +0 -0
  172. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/setup.cfg +0 -0
  173. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/__main__.py +0 -0
  174. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/agents.py +0 -0
  175. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/checkpoints.py +0 -0
  176. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/__init__.py +0 -0
  177. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/diff.py +0 -0
  178. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/eval.py +0 -0
  179. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/impact.py +0 -0
  180. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/receipts.py +0 -0
  181. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/scan.py +0 -0
  182. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/search.py +0 -0
  183. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/store.py +0 -0
  184. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/summary.py +0 -0
  185. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/symbols.py +0 -0
  186. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_context/test_hints.py +0 -0
  187. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/code_index.py +0 -0
  188. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/db/migrations/001_initial.sql +0 -0
  189. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/db/migrations/002_tasks.sql +0 -0
  190. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/db/migrations/003_agent_registry.sql +0 -0
  191. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/db/migrations/004_code_index.sql +0 -0
  192. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/db/migrations/005_verification_feedback.sql +0 -0
  193. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/db/schema.sql +0 -0
  194. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/decisions.py +0 -0
  195. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/dispatch.py +0 -0
  196. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/errors.py +0 -0
  197. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/escalations.py +0 -0
  198. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/events.py +0 -0
  199. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/exporters.py +0 -0
  200. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/guards.py +0 -0
  201. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/links.py +0 -0
  202. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/locales.py +0 -0
  203. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/mcp_server.py +0 -0
  204. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/migrations.py +0 -0
  205. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/paths.py +0 -0
  206. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/receipt_show.py +0 -0
  207. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/registry.py +0 -0
  208. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/renderer.py +0 -0
  209. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/reports.py +0 -0
  210. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/resources.py +0 -0
  211. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/rubric.py +0 -0
  212. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/dashboard/dashboard.html +0 -0
  213. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/project/AGENTS.block.md +0 -0
  214. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/project/CLAUDE.block.md +0 -0
  215. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/project/gitignore.fragment +0 -0
  216. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/project/pcl.yaml +0 -0
  217. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/workflows/defect_repair.yaml +0 -0
  218. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/workflows/executor_smoke.yaml +0 -0
  219. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/workflows/feature_coverage.yaml +0 -0
  220. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/templates/workflows/regression_loop.yaml +0 -0
  221. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/timeutil.py +0 -0
  222. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/token_estimation.py +0 -0
  223. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/update_check.py +0 -0
  224. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/verifications.py +0 -0
  225. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/workflow_proposal_validation.py +0 -0
  226. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/workflow_proposals.py +0 -0
  227. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/workflow_verifier.py +0 -0
  228. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/pcl/workflow_yaml.py +0 -0
  229. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/project_loop_harness.egg-info/dependency_links.txt +0 -0
  230. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/project_loop_harness.egg-info/entry_points.txt +0 -0
  231. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/project_loop_harness.egg-info/requires.txt +0 -0
  232. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/src/project_loop_harness.egg-info/top_level.txt +0 -0
  233. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/fixtures/code_context_summary_v0.json +0 -0
  234. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/fixtures/context_receipt_v0.json +0 -0
  235. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/fixtures/context_receipt_v0_legacy_string_suggestions.json +0 -0
  236. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/fixtures/retrieval_adversarial_v0.json +0 -0
  237. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/fixtures/retrieval_real_history_v0.json +0 -0
  238. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/fixtures/retrieval_v0.json +0 -0
  239. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_advisory_retrieval_eval_script.py +0 -0
  240. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_agent_adapter_contract.py +0 -0
  241. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_agent_output_validation.py +0 -0
  242. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_agents.py +0 -0
  243. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_audit_log_integrity.py +0 -0
  244. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_checkpoints.py +0 -0
  245. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_claude_manual_adapter.py +0 -0
  246. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_code_context_summary.py +0 -0
  247. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_code_index.py +0 -0
  248. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_codex_exec_adapter.py +0 -0
  249. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_codex_plugin.py +0 -0
  250. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_dashboard.py +0 -0
  251. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_dashboard_data_contract.py +0 -0
  252. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_decisions.py +0 -0
  253. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_defects.py +0 -0
  254. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_dispatch.py +0 -0
  255. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_escalations.py +0 -0
  256. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_examples.py +0 -0
  257. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_generic_shell_adapter.py +0 -0
  258. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_golden_path.py +0 -0
  259. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_mcp_server.py +0 -0
  260. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_next_actions.py +0 -0
  261. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_pypi_publishing.py +0 -0
  262. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_receipt_show.py +0 -0
  263. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_recovery_playbook.py +0 -0
  264. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_registry.py +0 -0
  265. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_reports.py +0 -0
  266. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_rubric.py +0 -0
  267. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_update_check.py +0 -0
  268. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_validation.py +0 -0
  269. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_validation_diagnostics.py +0 -0
  270. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_workflow_executor.py +0 -0
  271. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_workflow_proposals.py +0 -0
  272. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_workflow_sandbox.py +0 -0
  273. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_workflow_verifier.py +0 -0
  274. {project_loop_harness-0.2.1 → project_loop_harness-0.2.3}/tests/test_workflows.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: project-loop-harness
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: Local control plane for agentic project development loops
5
5
  Author: Project Loop Harness Contributors
6
6
  License: MIT
@@ -0,0 +1,78 @@
1
+ # Task 0092: Idempotent Same-State Transitions (v0.2.2, F1)
2
+
3
+ Source: first external-project agent dogfood feedback
4
+ (`docs/feedback/2026-07-06-ax1-moc1-agent-feedback.md`, item F1).
5
+ `pcl feature status F-0001 --status passing` exits 2 when the feature
6
+ is already passing. For scripting agents a same-state request is a
7
+ satisfied postcondition, not an input error; exit 2 forces every
8
+ caller to pre-read state or wrap errors. No migration, no new
9
+ dependency.
10
+
11
+ ## Behavior change (all four sites)
12
+
13
+ Same-state transition requests become successful no-ops:
14
+
15
+ - `pcl feature status <id> --status <current>` (`commands.py`
16
+ `set_feature_status`)
17
+ - `pcl goal complete` / goal lifecycle same-state (`lifecycle.py`,
18
+ the "Goal ... is already ..." site)
19
+ - `pcl test <verb>` when the test case is already in the requested
20
+ terminal state (`stories.py`, the "Test case ... is already ..."
21
+ site)
22
+ - `pcl task status <id> <current>` (`tasks.py`, the "Task ... is
23
+ already ..." site)
24
+
25
+ No-op semantics (identical across all four):
26
+
27
+ - Exit code 0; JSON gains `"changed": false` plus the current status.
28
+ - NOTHING is recorded: no status update, no inline evidence row, no
29
+ event append. A no-op that logs is not a no-op — repeated agent
30
+ retries must not inflate the audit trail.
31
+ - Human-readable output states plainly that the entity was already in
32
+ the requested state (e.g. `Feature F-0001 already passing; no
33
+ change recorded.`).
34
+ - Supplied `--evidence` / `--reason` text on a no-op is NOT recorded;
35
+ the response must make that explicit (e.g.
36
+ `"evidence_recorded": false`) so callers do not believe evidence
37
+ was attached. Attaching fresh evidence to an already-terminal state
38
+ (re-verification) is out of scope here and belongs to the evidence
39
+ entry-path design.
40
+
41
+ Changed transitions additionally gain `"changed": true` (additive
42
+ JSON field; existing fields untouched).
43
+
44
+ ## What must NOT change
45
+
46
+ - Invalid TARGET states and disallowed transitions (e.g. rubric or
47
+ guard violations, unknown entities) keep their existing typed
48
+ errors and exit codes. Only the exact same-state case becomes a
49
+ no-op.
50
+ - Evidence-backed terminal-state validation invariants are untouched
51
+ (a no-op changes nothing, so nothing new to validate).
52
+ - No behavior change for transitions that DO change state, other
53
+ than the additive `changed` field.
54
+
55
+ ## Acceptance Criteria
56
+
57
+ - For each of the four commands: same-state call → exit 0,
58
+ `changed: false`, row count of events/evidence unchanged (assert
59
+ counts before/after), status unchanged, and repeated invocation is
60
+ stable (call twice more, same result).
61
+ - Same-state call with `--evidence "..."` → `evidence_recorded:
62
+ false` in JSON and no evidence row.
63
+ - Changed-state calls still record exactly as before and now carry
64
+ `changed: true`.
65
+ - Unknown entity / invalid target status still typed errors (regression
66
+ tests kept).
67
+ - Docs: `docs/golden-path.md` or command docs note the idempotent
68
+ semantics in one short paragraph.
69
+ - `ruff check .` passes; full `python3 -m pytest` passes; `pcl init`
70
+ smoke against a temp dir passes.
71
+
72
+ ## Do Not
73
+
74
+ - Do not make disallowed transitions succeed.
75
+ - Do not append events or evidence on no-ops.
76
+ - Do not add a `--force` re-record path (that is evidence-path design
77
+ territory).
78
+ - Do not touch schema or raw SQL outside the existing service layer.
@@ -0,0 +1,95 @@
1
+ # Task 0093: `pcl evidence add` + Adhoc Bundles (v0.2.2, F2/F6)
2
+
3
+ Design source: `docs/evidence-entry-paths-design.md`
4
+ (**APPROVED 2026-07-07**, Parts 1-2 and the approval record). Where
5
+ this spec and the design doc disagree, the design doc wins. No
6
+ migration, no new runtime dependency; schema stays v5.
7
+
8
+ ## Goal
9
+
10
+ Operators and agents produce reviewable artifacts outside the job
11
+ loop (test output, screenshots, visual-check reports) and PLH has no
12
+ honest way to accept them as evidence. Add the missing primitive.
13
+
14
+ ## Scope
15
+
16
+ ### 1. `pcl evidence add`
17
+
18
+ ```bash
19
+ pcl evidence add --file work/reports/pytest-out.txt \
20
+ --summary "pytest run for suggestion E-0017/VS-01" \
21
+ --command "python3 -m pytest tests/test_context.py" --json
22
+ ```
23
+
24
+ - `--file` is required and repeatable; every path must exist and be
25
+ readable at record time (missing/unreadable → typed error, nothing
26
+ recorded). `--summary` required. `--command` optional — it is the
27
+ CALLER'S claim of how the artifact was produced; PLH stores it
28
+ verbatim and never runs or verifies it (docs and help must say
29
+ this).
30
+ - One file → evidence `type = 'adhoc_artifact'` (approved). Two or
31
+ more files → `type = 'adhoc_bundle'` (approved).
32
+ - In both cases PLH writes a small manifest JSON under
33
+ `.project-loop/evidence/adhoc/` recording, per member: relative
34
+ path, size_bytes, sha256 — pinned AT RECORD TIME. Members are
35
+ referenced in place, NOT copied (approved; a `--copy` mode is a
36
+ possible later addition, do not add it now).
37
+ - The evidence row's `path` points at the manifest; `command` and
38
+ `summary` come from the flags. One evidence row per invocation, one
39
+ standard event via `append_event` (SQLite + JSONL both — never a
40
+ side-channel writer; see agent-tasks/0089 clarification).
41
+ - Manifest contract name: `adhoc-evidence/v0` with a
42
+ `contract_version` field. Deterministic member ordering (input
43
+ order preserved; duplicates by path → typed error).
44
+ - JSON output returns the evidence id, type, manifest path, and the
45
+ member list with hashes.
46
+
47
+ ### 2. Strict validation integration
48
+
49
+ - `pcl validate --strict` verifies for adhoc evidence rows that the
50
+ manifest file exists and parses; missing/corrupt manifest is an
51
+ ERROR (state integrity).
52
+ - Member hash drift (file changed or deleted since recording) is a
53
+ WARNING, not an error (approved): drift is the working tree moving
54
+ on; the pinned hash remains the recorded claim. Warning text must
55
+ name the evidence id, member path, and which aspect drifted
56
+ (missing vs hash mismatch).
57
+
58
+ ### 3. Documentation
59
+
60
+ - New section in `docs/data-model.md` or `docs/golden-path.md`:
61
+ the adhoc evidence flow, the claim/pointer epistemic boundary, and
62
+ the worked example ending in
63
+ `pcl verification feedback ... --evidence E-00xx`.
64
+ - `docs/evidence-entry-paths-design.md` stays the design record; do
65
+ not duplicate it wholesale.
66
+
67
+ ## Acceptance Criteria
68
+
69
+ - Single file → `adhoc_artifact`; multiple files → `adhoc_bundle`;
70
+ manifest carries per-member path/size/sha256; JSON output matches.
71
+ - Determinism: same files, same flags → identical manifest content
72
+ except created_at/evidence id.
73
+ - Missing file, unreadable file, duplicate path → distinct typed
74
+ errors, no evidence row, no event, no manifest file left behind.
75
+ - `validate --strict`: green after add; deleting a member → WARNING
76
+ (still ok); editing a member → WARNING naming the hash mismatch;
77
+ deleting the MANIFEST → ERROR.
78
+ - End-to-end test: `evidence add` → `verification feedback
79
+ --status executed --evidence <new id>` succeeds (closes the M2
80
+ dogfood gap).
81
+ - Events mirrored in SQLite and JSONL; strict audit integrity stays
82
+ green (regression test).
83
+ - `ruff check .` passes; full `python3 -m pytest` passes; `pcl init`
84
+ smoke against a temp dir passes.
85
+
86
+ ## Do Not
87
+
88
+ - Do not copy member files or add `--copy` yet.
89
+ - Do not execute `--command` or capture output (`--capture` is out of
90
+ scope by design).
91
+ - Do not add an M:N evidence link table or any migration.
92
+ - Do not use "verified"/"safe" language for adhoc evidence — it is a
93
+ recorded claim with pinned hashes.
94
+ - Do not touch `verification feedback` flags (`--output-file` is
95
+ formally superseded, not implemented).
@@ -0,0 +1,71 @@
1
+ # Task 0094: Job Completion Evidence Linkage (v0.2.2, F3)
2
+
3
+ Design source: `docs/evidence-entry-paths-design.md`
4
+ (**APPROVED 2026-07-07**, Part 3). Depends on 0093 being merged (its
5
+ adhoc evidence rows are natural inputs here, and both touch cli.py /
6
+ validators tests). No migration; schema stays v5.
7
+
8
+ ## Goal
9
+
10
+ In the ax1-moc1 dogfood run, `pcl jobs list --json` showed empty
11
+ evidence for jobs whose `output_path` files existed, and there was no
12
+ way to attach evidence when completing a job. Close both gaps using
13
+ the EXISTING `latest_evidence_id` pointer on agent jobs.
14
+
15
+ ## Scope
16
+
17
+ ### 1. `pcl jobs complete <job-id> --evidence E-00xx`
18
+
19
+ - Optional repeatable? NO — single `--evidence` flag (the
20
+ one-pointer model matches `latest_evidence_id`; multiple artifacts
21
+ are one adhoc bundle from 0093).
22
+ - The referenced evidence row must exist → typed error otherwise,
23
+ nothing changed.
24
+ - Sets `latest_evidence_id` on the job as part of the existing
25
+ completion flow; completion event payload gains the evidence id.
26
+ All existing completion semantics (summary, status transition,
27
+ guards) unchanged.
28
+
29
+ ### 2. Jobs-list evidence visibility audit (the ax1-moc1 symptom)
30
+
31
+ - Reproduce first: in the ax1-moc1 run, jobs completed through the
32
+ normal flow showed `evidence: []`/empty in `pcl jobs list --json`
33
+ even though `output_path` existed and ingest had run. Find out
34
+ why (linkage never set? read path not surfacing it? ingest path
35
+ only sets it on certain flows?) and fix the actual cause — do not
36
+ paper over it in the list renderer.
37
+ - After the fix: a job whose output was ingested surfaces its
38
+ evidence reference in `jobs read` / `jobs list --json` and
39
+ dashboard-data.
40
+
41
+ ### 3. Documentation
42
+
43
+ - `docs/golden-path.md` / agent adapter docs: one short paragraph —
44
+ complete a job with `--evidence` when the artifact is already
45
+ recorded (0093 flow), otherwise ingest output as before.
46
+
47
+ ## Acceptance Criteria
48
+
49
+ - `jobs complete --evidence E-00xx` sets `latest_evidence_id`,
50
+ appends the completion event with the evidence id, and the linkage
51
+ appears in `jobs read --json`, `jobs list --json`, and
52
+ dashboard-data.
53
+ - Unknown evidence id → typed error; job stays incomplete and
54
+ unchanged.
55
+ - Root-cause test for the visibility bug: a test that reproduces the
56
+ original empty-evidence symptom path and asserts it is fixed
57
+ (write the test against the actual discovered cause, and explain
58
+ the cause in the task report).
59
+ - Existing completion without `--evidence` behaves exactly as
60
+ before.
61
+ - `ruff check .` passes; full `python3 -m pytest` passes; `pcl init`
62
+ smoke against a temp dir passes; strict validate/audit integrity
63
+ regression stays green.
64
+
65
+ ## Do Not
66
+
67
+ - Do not add repeatable `--evidence` or an M:N link table.
68
+ - Do not auto-create evidence from `output_path` without ingest —
69
+ linkage requires a real evidence row.
70
+ - Do not change ingest contracts (`agent-output/v1`) or job state
71
+ machine semantics.
@@ -0,0 +1,156 @@
1
+ # Task 0095: Supporting Evidence Health in Verification Stats (v0.2.3, P0)
2
+
3
+ Origin: GPT-5.5-pro v0.2.2 review agenda, blind spot B ("feedback stats
4
+ do not look at the health of supporting evidence"). No migration, no
5
+ new runtime dependency; schema stays v5.
6
+
7
+ ## Goal
8
+
9
+ `verification_feedback` rows can reference a `supporting_evidence_id`.
10
+ Since v0.2.2 that evidence is often an `adhoc_artifact` / `adhoc_bundle`
11
+ whose members are referenced (not copied) and hash-pinned. Stats can
12
+ therefore show a healthy `executed_pass_rate` while the artifacts
13
+ backing those feedbacks have since gone missing or drifted.
14
+
15
+ Add a **derived, read-only health axis** to `pcl verification stats
16
+ --json` that reports whether the supporting evidence behind executed
17
+ feedback is still reviewable today. Do NOT change any existing metric
18
+ and do NOT rewrite any feedback row: PLH records facts append-only;
19
+ health is a separate, current-time observation about reviewability.
20
+
21
+ ## Vocabulary (binding)
22
+
23
+ - Health values: `ok` | `warning` | `error` | `unknown`.
24
+ - Health describes "current reviewability of the referenced
25
+ artifacts". It never asserts the original claim was true or false.
26
+ - Forbidden in new output, help text, and docs for this feature:
27
+ "verified", "proven", "guaranteed", "invalid(ated)". A drifted
28
+ artifact does not invalidate a past feedback; it makes it harder to
29
+ review now.
30
+
31
+ ## Scope
32
+
33
+ ### 1. Shared adhoc health assessment
34
+
35
+ Extract the adhoc manifest/member checks that already exist in
36
+ `src/pcl/validators.py` (`_validate_adhoc_evidence_manifests` /
37
+ `_validate_adhoc_members`) into a shared, structured assessment
38
+ function in `src/pcl/evidence.py`, e.g.:
39
+
40
+ ```python
41
+ def assess_adhoc_evidence(paths, *, evidence_id, evidence_type, manifest_path_value) -> dict
42
+ # -> {"health": "ok"|"warning"|"error", "findings": [{"code": ..., "path": ...?, "detail": ...?}]}
43
+ ```
44
+
45
+ Structured finding codes (at minimum): `manifest_not_local`,
46
+ `manifest_missing`, `manifest_not_file`, `manifest_corrupt`,
47
+ `contract_version_unsupported`, `evidence_id_mismatch`,
48
+ `evidence_type_mismatch`, `members_invalid`, `member_entry_invalid`,
49
+ `member_missing`, `member_hash_mismatch`.
50
+
51
+ Severity mapping mirrors today's validator semantics exactly:
52
+ structural manifest problems are `error`; member drift (missing file
53
+ or hash mismatch) is `warning`; everything intact is `ok`.
54
+
55
+ `validators.py` must consume this shared function so drift semantics
56
+ have a single source. Protective invariant, scoped: **the rendered
57
+ `pcl validate` / `pcl validate --strict` messages for the existing
58
+ test fixtures must remain unchanged — all existing validator tests
59
+ pass unmodified.** If message-identical rendering from structured
60
+ findings proves impossible for some edge case, stop and report
61
+ instead of changing a message.
62
+
63
+ The assessment must tolerate (ignore) unknown extra keys on manifest
64
+ members — task 0096 will add fields such as `path_scope` later.
65
+
66
+ ### 2. `supporting_evidence_health` in stats
67
+
68
+ In `verification_feedback_stats` (`src/pcl/verification_feedback.py`),
69
+ assess every **distinct** `supporting_evidence_id` referenced by
70
+ feedback rows already loaded for stats (all statuses, not just
71
+ executed — a `skipped` feedback can also carry evidence):
72
+
73
+ - Evidence row absent in `evidence` table → `error` with finding
74
+ `evidence_row_missing`. (Normally impossible — record-time checks
75
+ existence — but deletion/corruption must surface, not crash.)
76
+ - Evidence row present, `type` in (`adhoc_artifact`, `adhoc_bundle`)
77
+ → result of the shared assessment.
78
+ - Evidence row present, any other type (`context_receipt`, ingested
79
+ agent output, test evidence, ...) → `unknown` with finding
80
+ `health_not_assessed_for_type`. v0 assesses adhoc only; do not
81
+ invent checks for other types.
82
+
83
+ Each distinct evidence id is assessed (and its member files hashed)
84
+ at most once per stats invocation.
85
+
86
+ New sibling section in the returned `stats` object (additive only —
87
+ no existing key changes, no metric formula changes):
88
+
89
+ ```json
90
+ "supporting_evidence_health": {
91
+ "assessed_evidence_count": 2,
92
+ "feedback_events_with_supporting_evidence_count": 3,
93
+ "health_counts": {"ok": 1, "warning": 0, "error": 0, "unknown": 1},
94
+ "by_evidence_id": {
95
+ "E-0018": {"health": "ok", "findings": []},
96
+ "E-0017": {"health": "unknown",
97
+ "findings": [{"code": "health_not_assessed_for_type",
98
+ "detail": "context_receipt"}]}
99
+ }
100
+ }
101
+ ```
102
+
103
+ Additionally, each entry in the existing
104
+ `latest_feedback_by_suggestion` map gains a
105
+ `supporting_evidence_health` key: the health string when that
106
+ feedback row has a `supporting_evidence_id`, else `null`.
107
+
108
+ ### 3. Read surfaces and docs
109
+
110
+ - `pcl verification stats --json` carries the new section (it already
111
+ prints the stats dict; no new flag).
112
+ - Docs: extend `docs/verification-feedback.md` with a
113
+ "Supporting evidence health" section covering the four health
114
+ values, the adhoc-only v0 scope, and the binding vocabulary rule
115
+ (health ≠ truth; feedback rows are never rewritten).
116
+
117
+ ## Non-goals
118
+
119
+ - No change to `pcl validate` behavior or output (refactor only).
120
+ - No dashboard/report rendering of health (v0.2.4 UX round).
121
+ - No health for non-adhoc evidence types beyond `unknown`.
122
+ - No caching of hash checks across invocations.
123
+ - No new events, no DB writes: stats stays a pure read. Protective
124
+ invariant, scoped: **a `pcl verification stats` invocation must not
125
+ append to `events.jsonl` nor change any table row** (assert in a
126
+ test via row counts / file size before and after).
127
+
128
+ ## Tests
129
+
130
+ 1. Feedback with adhoc supporting evidence, members intact → `ok`;
131
+ health appears in `by_evidence_id` and in
132
+ `latest_feedback_by_suggestion`.
133
+ 2. Overwrite one member file after recording → `warning` with
134
+ `member_hash_mismatch`; delete a member → `warning` with
135
+ `member_missing`. Existing metrics (`executed_pass_rate` etc.)
136
+ unchanged by drift.
137
+ 3. Delete the manifest file → `error` with `manifest_missing`.
138
+ 4. Supporting evidence of a non-adhoc type → `unknown`.
139
+ 5. Feedback without `supporting_evidence_id` → excluded from
140
+ `health_counts`; `supporting_evidence_health: null` in
141
+ `latest_feedback_by_suggestion`.
142
+ 6. Same evidence id referenced by two feedback rows → assessed once,
143
+ counted once in `health_counts`.
144
+ 7. Stats invocation performs no writes (events.jsonl byte size and
145
+ evidence/feedback row counts identical before/after).
146
+ 8. All existing validator and stats tests pass unmodified.
147
+
148
+ ## Definition of done
149
+
150
+ - Implementation + tests green (`python3 -m pytest`).
151
+ - Live smoke against this repo's own `.project-loop` (it already has
152
+ VF-0001/VF-0002 and E-0017/E-0018 from dogfood): stats shows
153
+ `ok` for E-0018 (adhoc) and `unknown` for E-0017 (context_receipt);
154
+ then temporarily drift a member copy in a scratch project (not the
155
+ live DB) to show `warning`.
156
+ - Docs updated. Evidence paths for all claims.
@@ -0,0 +1,185 @@
1
+ # Task 0096: Evidence Add Path Guards — Scope + Sensitive Shape (v0.2.3, P0)
2
+
3
+ Origin: GPT-5.5-pro v0.2.2 review agenda, blind spots C (project
4
+ boundary) and D (secret-shaped files), merged into one task because
5
+ both are record-time guards on the same code path
6
+ (`src/pcl/evidence.py::_adhoc_members`). No migration, no new runtime
7
+ dependency; schema stays v5. Runs AFTER 0095 is merged (both touch
8
+ `evidence.py` / `validators.py`).
9
+
10
+ ## Goal
11
+
12
+ `pcl evidence add` accepts any existing local file. Two gaps:
13
+
14
+ 1. A file outside the project root is silently recorded with a
15
+ `../...` relative member path — invisible in the manifest, likely
16
+ unreproducible on another machine.
17
+ 2. An agent can pass `.env`, a private key, or a credentials file and
18
+ PLH records it without any friction.
19
+
20
+ Add explicit accounting for the project boundary and a name-shaped
21
+ sensitive-path guard. PLH is NOT a content scanner and must not
22
+ become one: both guards look at paths only, never file contents, and
23
+ docs must say so.
24
+
25
+ ## Part A: path scope accounting
26
+
27
+ ### Member field
28
+
29
+ Every manifest member (and the members echoed in the
30
+ `adhoc_evidence_recorded` event payload and the CLI JSON result)
31
+ gains:
32
+
33
+ ```json
34
+ "path_scope": "in_project" | "outside_project"
35
+ ```
36
+
37
+ Determination: after the existing `resolve()`, the member is
38
+ `in_project` iff `resolved.relative_to(paths.root.resolve())`
39
+ succeeds — the same boundary `_relative_path` already uses.
40
+
41
+ ### Behavior
42
+
43
+ - Default: `outside_project` members are recorded, with a warning.
44
+ - Text mode: warning line on stderr.
45
+ - JSON mode: additive top-level `"warnings": [...]` array in the
46
+ result (present only when non-empty), one entry per
47
+ outside-project member, e.g.
48
+ `"evidence member outside project root: ../tmp/report.txt"`.
49
+ - `pcl.yaml` opt-in hard boundary:
50
+
51
+ ```yaml
52
+ evidence:
53
+ allow_outside_root: false
54
+ ```
55
+
56
+ When set to `false`, any outside-project member → typed error
57
+ `evidence_add_outside_root` (exit 2). Absent key or `true` =
58
+ default warning behavior. Read the key with the same tolerant
59
+ pcl.yaml reading approach used elsewhere (see
60
+ `_configured_yaml_list` in `src/pcl/code_context/scan.py` for the
61
+ house style; a scalar sibling helper is fine).
62
+
63
+ ## Part B: sensitive-shaped path guard
64
+
65
+ ### Patterns
66
+
67
+ - Reuse `DEFAULT_SENSITIVE_EXCLUDES` and `_path_pattern_matches` from
68
+ `pcl.code_context` (import them; do NOT copy the pattern list —
69
+ one source of truth).
70
+ - Optional additional patterns from `pcl.yaml`:
71
+
72
+ ```yaml
73
+ evidence:
74
+ sensitive_exclude:
75
+ - "*.sqlite3"
76
+ ```
77
+
78
+ - `code_index.sensitive_include_override` does NOT apply here — it is
79
+ index-scoped. There is no override list for evidence; the override
80
+ is the explicit CLI flag below.
81
+
82
+ ### Matching
83
+
84
+ For each member, match patterns against:
85
+
86
+ 1. the recorded member path (the project-relative / `../`-relative
87
+ form that goes into the manifest), and
88
+ 2. the file's basename (so `/Users/x/.env` recorded as
89
+ `../../.env` still matches `.env`; directory patterns like
90
+ `.aws/` cannot anchor across `../` prefixes otherwise).
91
+
92
+ ### Behavior
93
+
94
+ - If any member matches and `--allow-sensitive-evidence` was NOT
95
+ passed → typed error `evidence_add_sensitive_path` (exit 2) listing
96
+ the matched paths and patterns in `details`, and telling the caller
97
+ about `--allow-sensitive-evidence`. This is the default in ALL
98
+ modes — the CLI is non-interactive; there is no prompt.
99
+ - With `--allow-sensitive-evidence`:
100
+ - members are recorded; each matched member gains
101
+ `"sensitive_pattern": "<pattern>"` in the manifest/event/result;
102
+ - the manifest gains top-level
103
+ `"sensitive_path_warning_count": <int>` (count of matched
104
+ members); the event payload carries the same count;
105
+ - a warning is still emitted (stderr in text mode, `warnings` array
106
+ entry in JSON mode).
107
+ - Help text and docs must state: this is a filename-shape check only;
108
+ PLH does not scan file contents and recording with the flag is the
109
+ caller's explicit decision.
110
+
111
+ ## Guard ordering and atomicity
112
+
113
+ Both guards run inside the pre-DB stage (`_adhoc_members`), after the
114
+ existing exists/readable/duplicate checks, before any ID allocation,
115
+ manifest write, DB insert, or event append. Protective invariant,
116
+ scoped, same as 0093: **on any typed error from `pcl evidence add`,
117
+ zero traces — no evidence row, no JSONL event, no manifest file, no
118
+ consumed evidence ID, and the `evidence/adhoc/` directory file count
119
+ is unchanged** (assert in tests).
120
+
121
+ Evaluation order when multiple guards fire: report the sensitive
122
+ error first (it is the safety guard), then outside-root. A single
123
+ typed error is enough; do not build a multi-error report.
124
+
125
+ ## Validators (`src/pcl/validators.py`)
126
+
127
+ - New optional member fields `path_scope`, `sensitive_pattern` and
128
+ manifest field `sensitive_path_warning_count` are accepted:
129
+ - absent → fine (pre-0096 manifests stay valid, no new errors);
130
+ - present with an invalid value (unknown scope string,
131
+ non-string pattern, negative/non-int count) → error.
132
+ - New warning, applies to old and new manifests alike since it is
133
+ derivable from the path itself: a member path starting with `../`
134
+ → warning `Adhoc evidence <id> member <path> is outside the project
135
+ root.` This complements, not replaces, the existing drift warnings.
136
+ - The 0095 shared assessment function gains a corresponding finding
137
+ code `member_outside_project_root` at `warning` severity, so stats
138
+ health reflects the same fact. Existing fixtures without outside
139
+ members must produce byte-identical validate output.
140
+
141
+ ## Non-goals
142
+
143
+ - No content scanning, no entropy heuristics, no secret detection.
144
+ - No change to code index sensitive behavior or context receipts.
145
+ - No dashboard/report highlighting (v0.2.4 UX round).
146
+ - No copy/snapshot mode (task 0097 designs it).
147
+ - No interactive confirmation prompts.
148
+
149
+ ## Tests
150
+
151
+ 1. In-project file → `path_scope: "in_project"`, no warnings key,
152
+ output otherwise identical to v0.2.2 shape plus the new field.
153
+ 2. File under a temp dir outside root → recorded, member has
154
+ `outside_project`, JSON result has `warnings`, manifest path is
155
+ `../...`.
156
+ 3. Same with `evidence.allow_outside_root: false` → typed
157
+ `evidence_add_outside_root`, exit 2, zero traces.
158
+ 4. `.env` inside project without flag → typed
159
+ `evidence_add_sensitive_path`, exit 2, zero traces.
160
+ 5. `.env` with `--allow-sensitive-evidence` → recorded;
161
+ `sensitive_pattern` on the member;
162
+ `sensitive_path_warning_count: 1`; warning emitted.
163
+ 6. Outside-project `/tmp/.../credentials-prod.json` without flag →
164
+ blocked via basename matching.
165
+ 7. `evidence.sensitive_exclude` additional pattern matches → blocked
166
+ without flag.
167
+ 8. Bundle mixing one sensitive + one clean member without flag →
168
+ blocked, zero traces (no partial manifest).
169
+ 9. Sensitive + outside-root simultaneously, no flag → the sensitive
170
+ error is the one reported.
171
+ 10. Validators: pre-0096 manifest (no new fields) still valid;
172
+ manifest with `../` member path → outside-root warning; invalid
173
+ `path_scope` value → error.
174
+ 11. Strict validate output for existing fixtures unchanged.
175
+
176
+ ## Definition of done
177
+
178
+ - Implementation + tests green (`python3 -m pytest`).
179
+ - Live smoke in a scratch project (`pcl init /tmp/pcl-demo` style):
180
+ demonstrate cases 2, 4, 5 with real files and show the manifest
181
+ JSON. Do NOT add sensitive-named files to the live PLH repo DB.
182
+ - `docs/evidence-entry-paths-design.md` gains a short "Path guards
183
+ (0096)" section documenting scope accounting, the guard, the
184
+ config keys, and the not-a-content-scanner boundary.
185
+ - Evidence paths for all claims.
@@ -0,0 +1,54 @@
1
+ # Task 0097: Evidence Durability Modes — Design Only (v0.2.3, P1)
2
+
3
+ Origin: GPT-5.5-pro v0.2.2 review agenda, blind spot A ("hash-pin is
4
+ not durability"). **This task produces a design document only — no
5
+ code, no schema change, no CLI change.** Authored by the
6
+ orchestrator (not dispatched to an implementation worker) because it
7
+ is a judgment/trade-off document requiring approval, not a build.
8
+
9
+ ## Problem
10
+
11
+ v0.2.2 adhoc evidence records member path + size + sha256 but never
12
+ copies the file. This is honest ("existed with this content at record
13
+ time") but weak for later review: cleanup deletes
14
+ `work/reports/pytest-out.txt`, CI artifacts expire, screenshots live
15
+ outside the repo, overwritten files leave only a drift warning.
16
+
17
+ A naive `--copy` does not fix this either, because
18
+ `.project-loop/evidence/` is **gitignored** (`.gitignore:20`): a copy
19
+ survives local cleanup but still does not travel to another machine
20
+ or reviewer. Durability design is inseparable from the git/versioning
21
+ boundary of `.project-loop`, so the boundary question must be settled
22
+ before any implementation.
23
+
24
+ ## Deliverable
25
+
26
+ `docs/evidence-durability-design.md` covering at minimum:
27
+
28
+ 1. Modes: `reference` (today, stays default) vs explicit `--copy`
29
+ (member files copied under `.project-loop/evidence/adhoc-files/`)
30
+ vs a possible `--snapshot`/export-bundle variant; what each does
31
+ and does not promise.
32
+ 2. Manifest accounting: `storage_mode: reference | copied` per
33
+ member or per manifest; interaction with drift detection (a copy
34
+ can also drift or be deleted).
35
+ 3. The gitignore boundary problem: options (keep evidence local-only;
36
+ carve out a committed evidence subdirectory; an explicit
37
+ `pcl evidence export` bundle for hand-off) with a recommendation.
38
+ 4. Interaction with 0096 guards: copying must never weaken them —
39
+ sensitive-shaped members and outside-root members and copy mode
40
+ compose (e.g. copying an outside-root file pulls it inside the
41
+ boundary: is that a feature or a loophole? decide and say why).
42
+ 5. Size discipline: soft cap for copied members, `large_evidence_member`
43
+ warning, relation to strict-validate hash cost (review blind spot
44
+ F stays backlog; the design should not preclude it).
45
+ 6. Truthfulness boundary: PLH never claims copied content is correct,
46
+ only that it was copied from the named path at record time.
47
+ 7. Decision points listed explicitly for approval; no default-copy —
48
+ copying stays opt-in per invocation.
49
+
50
+ ## Definition of done
51
+
52
+ - Design doc committed to `main`, marked as awaiting approval.
53
+ - Open decisions presented for approval before any implementation
54
+ task is cut (implementation would be a v0.2.4+ task).