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