planr 1.9.0 → 1.10.0-alpha.1

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 (62) hide show
  1. package/README.md +30 -3
  2. package/docs/RELEASE.md +37 -7
  3. package/docs/contracts/EVIDENCE_CONTRACT_V1.md +283 -0
  4. package/docs/contracts/fixtures/evidence/v1/examples/coverage-verdict.json +66 -0
  5. package/docs/contracts/fixtures/evidence/v1/examples/evidence-attempt.json +39 -0
  6. package/docs/contracts/fixtures/evidence/v1/examples/evidence-policy.json +117 -0
  7. package/docs/contracts/fixtures/evidence/v1/examples/evidence-receipt.json +93 -0
  8. package/docs/contracts/fixtures/evidence/v1/examples/evidence-waiver.json +31 -0
  9. package/docs/contracts/fixtures/evidence/v1/examples/proof-obligation.json +67 -0
  10. package/docs/contracts/fixtures/evidence/v1/examples/proof-preset.json +28 -0
  11. package/docs/contracts/fixtures/evidence/v1/examples/untrusted-evidence-proposal.json +20 -0
  12. package/docs/contracts/fixtures/evidence/v1/examples/verification-capability-instance.json +39 -0
  13. package/docs/contracts/fixtures/evidence/v1/examples/verification-capability-manifest.json +52 -0
  14. package/docs/contracts/fixtures/evidence/v1/negative/aborted-zero-exit-attempt.json +39 -0
  15. package/docs/contracts/fixtures/evidence/v1/negative/adapter-registration-missing-execution-contract.json +97 -0
  16. package/docs/contracts/fixtures/evidence/v1/negative/available-empty-probe-capability.json +27 -0
  17. package/docs/contracts/fixtures/evidence/v1/negative/blocked-coverage-with-stale-reason.json +27 -0
  18. package/docs/contracts/fixtures/evidence/v1/negative/empty-trust-bindings-receipt.json +72 -0
  19. package/docs/contracts/fixtures/evidence/v1/negative/failed-zero-exit-attempt.json +39 -0
  20. package/docs/contracts/fixtures/evidence/v1/negative/forged-trusted-receipt.json +35 -0
  21. package/docs/contracts/fixtures/evidence/v1/negative/inconclusive-clean-exit-attempt.json +39 -0
  22. package/docs/contracts/fixtures/evidence/v1/negative/inconclusive-coverage-with-blocked-reason.json +27 -0
  23. package/docs/contracts/fixtures/evidence/v1/negative/minimal-policy-missing-owned-inputs.json +5 -0
  24. package/docs/contracts/fixtures/evidence/v1/negative/mismatched-probe-execution-id-capability.json +42 -0
  25. package/docs/contracts/fixtures/evidence/v1/negative/passed-empty-attempt.json +22 -0
  26. package/docs/contracts/fixtures/evidence/v1/negative/policy-default-preset-unregistered.json +111 -0
  27. package/docs/contracts/fixtures/evidence/v1/negative/policy-weakening-without-waiver.json +111 -0
  28. package/docs/contracts/fixtures/evidence/v1/negative/process-probe-missing-output-limits.json +49 -0
  29. package/docs/contracts/fixtures/evidence/v1/negative/satisfied-empty-coverage-verdict.json +14 -0
  30. package/docs/contracts/fixtures/evidence/v1/negative/skipped-zero-exit-attempt.json +39 -0
  31. package/docs/contracts/fixtures/evidence/v1/negative/stale-coverage-with-inconclusive-reason.json +27 -0
  32. package/docs/contracts/fixtures/evidence/v1/negative/timed-out-zero-exit-attempt.json +39 -0
  33. package/docs/contracts/fixtures/evidence/v1/negative/unavailable-zero-exit-attempt.json +39 -0
  34. package/docs/contracts/fixtures/evidence/v1/negative/unbound-waiver.json +21 -0
  35. package/docs/contracts/fixtures/evidence/v1/negative/unsatisfied-coverage-without-gap.json +63 -0
  36. package/docs/contracts/fixtures/evidence/v1/negative/waived-coverage-forbidden-gap-reason.json +28 -0
  37. package/docs/contracts/fixtures/evidence/v1/negative/waived-coverage-missing-waiver-id.json +27 -0
  38. package/docs/contracts/fixtures/evidence/v1/schemas/evidence-contract-v1.schema.json +2705 -0
  39. package/docs/documentation/COVERAGE.md +8 -5
  40. package/docs/documentation/INFORMATION_ARCHITECTURE.md +1 -1
  41. package/docs/fixtures/mcp-contract.json +16 -0
  42. package/npm/native/darwin-arm64/planr +0 -0
  43. package/npm/native/darwin-arm64/planr-host-capability-validator +0 -0
  44. package/npm/native/darwin-x86_64/planr +0 -0
  45. package/npm/native/darwin-x86_64/planr-host-capability-validator +0 -0
  46. package/npm/native/linux-arm64/planr +0 -0
  47. package/npm/native/linux-arm64/planr-host-capability-validator +0 -0
  48. package/npm/native/linux-x86_64/planr +0 -0
  49. package/npm/native/linux-x86_64/planr-host-capability-validator +0 -0
  50. package/package.json +15 -2
  51. package/plugins/planr/.claude-plugin/plugin.json +1 -1
  52. package/plugins/planr/.codex-plugin/plugin.json +1 -1
  53. package/plugins/planr/skills/planr-goal/SKILL.md +4 -2
  54. package/plugins/planr/skills/planr-loop/SKILL.md +7 -5
  55. package/plugins/planr/skills/planr-review/SKILL.md +5 -1
  56. package/plugins/planr/skills/planr-verify-web/SKILL.md +3 -1
  57. package/plugins/planr/skills/planr-work/SKILL.md +12 -1
  58. package/scripts/host-capability-experiment.mjs +2477 -0
  59. package/scripts/host-capability-runtime/v1/schemas/host-capability-expected-manifest.schema.json +377 -0
  60. package/scripts/host-capability-runtime/v1/schemas/host-capability-observed-raw.schema.json +439 -0
  61. package/scripts/host-capability-runtime/v1/schemas/host-capability-provenance.schema.json +178 -0
  62. package/scripts/planr-host-capability-validator +51 -0
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![Planr — turn chaotic agent work into a verified task graph](public/planr_banner1.webp)
4
4
 
5
- Planr is a local-first planning and execution coordination tool for coding agents. It combines reviewable Markdown plans with a dependency-aware work map so Codex, Claude Code, Cursor, Grok Build, generic MCP clients, and human operators can drive the same work safely — from idea to verified completion.
5
+ Planr is a local-first planning and execution coordination tool for coding agents. It combines reviewable Markdown plans with a dependency-aware work map so Codex, Claude Code, Cursor, Grok Build, Pi, generic MCP clients, and human operators can drive the same work safely — from idea to verified completion.
6
6
 
7
7
  [**View the Demo →**](https://x.com/kevinkern/status/2066957434564808884?s=20)
8
8
 
@@ -53,7 +53,7 @@ curl -fsSL https://raw.githubusercontent.com/instructa/planr/main/scripts/instal
53
53
  > On an affected Linux release, build from source on the target distribution or upgrade to v1.7.3.
54
54
  <!-- planr:linux-release-portability:end surface=README schema=1 -->
55
55
 
56
- Then initialize a project. When selected, Claude Code and Cursor also receive standalone project worker/reviewer roles; Codex workflow skills come from its plugin. Grok Build is a separate explicit opt-in and is not included by `all`:
56
+ Then initialize a project. When selected, Claude Code and Cursor also receive standalone project worker/reviewer roles; Codex workflow skills come from its plugin. Grok Build and Pi are separate explicit opt-ins and are not included by `all`:
57
57
 
58
58
  ```bash
59
59
  planr project init "My Product" --client all
@@ -61,6 +61,16 @@ planr project init "My Product" --client all
61
61
 
62
62
  Manual downloads, from-source builds, and client wiring details: [Install Guide](https://planr.so/docs/getting-started/installation).
63
63
 
64
+ To add Pi's native Agent Skills and optional pi-subagents roles to a trusted repository, select it explicitly:
65
+
66
+ ```bash
67
+ planr install pi --dry-run
68
+ planr install pi
69
+ planr project init "My Product" --client pi
70
+ ```
71
+
72
+ Planr writes repository-local `.pi/skills/` workflow assets and optional `.pi/agents/` roles only. It does not install Pi, pi-subagents, MCP config, hooks, global settings, provider credentials, or session state. Full setup and trust guidance: [Pi integration](https://planr.so/docs/integrations/pi).
73
+
64
74
  ## Install The Plugin (Skills)
65
75
 
66
76
  The plugin under `plugins/planr` carries the ten Planr workflow skills. Optional model-routing declarations live in repository-local files such as `.planr/agents.toml` and `.planr/policy.toml`; external tools may manage those files, but Planr does not install or invoke a routing engine. The `planr` CLI (above) is required separately.
@@ -123,6 +133,22 @@ Planr writes portable `.grok/config.toml` MCP configuration plus native `.grok/a
123
133
 
124
134
  </details>
125
135
 
136
+ <a id="install-pi"></a>
137
+ <details>
138
+ <summary><strong>Pi</strong></summary>
139
+
140
+ Preview or install the repository-local Pi integration:
141
+
142
+ ```bash
143
+ planr install pi --dry-run
144
+ planr install pi
145
+ planr doctor --client pi --json
146
+ ```
147
+
148
+ Planr writes native `.pi/skills/` workflow assets and optional `.pi/agents/` role files for `pi-subagents`. It writes no MCP configuration, hooks, extension package, global Pi settings, provider credentials, model pin, or session reference. Pi is intentionally explicit opt-in and is not part of `--client all`. See the [Pi integration guide](https://planr.so/docs/integrations/pi).
149
+
150
+ </details>
151
+
126
152
  <a id="install-plugin-opencode"></a>
127
153
  <details>
128
154
  <summary><strong>opencode</strong></summary>
@@ -200,6 +226,7 @@ The watcher is likewise a human-only observer. It defaults to the condensed diag
200
226
 
201
227
  ## What's new
202
228
 
229
+ - **1.9.0 — First-class Pi integration:** Added an explicit repository opt-in that installs native Pi Agent Skills plus optional `pi-subagents` worker/reviewer roles without treating Pi as an MCP host. The integration writes no Pi global settings, hooks, provider credentials, model pin, or session reference, and `--client all` remains unchanged for existing Codex, Claude Code, Cursor, and Grok setup. See the [Pi integration guide](https://planr.so/docs/integrations/pi), [Pi contract](docs/contracts/PI_INTEGRATION_V1.md), and [1.9.0 changelog](CHANGELOG.md#190---2026-07-27).
203
230
  - **1.8.0 — First-class Grok Build integration:** Added an explicit repository opt-in that installs portable project MCP configuration plus native Grok agents and all ten Planr workflow skills. The integration writes no plugin, hooks, model setting, xAI credentials, or provider runtime dependency; authenticated verification remains maintainer-local and never runs in CI. See the [Grok Build guide](https://planr.so/docs/integrations/grok-build) and [1.8.0 changelog](CHANGELOG.md#180---2026-07-27).
204
231
  - **1.7.2 — Reproducible release candidates:** Locked the pnpm workspace inventory, made external eval fixtures self-contained, refreshed reviewed workflow runtimes, and made all four published architectures execute the exact tagged version before upload. Model-backed evaluation remains a local, candidate-bound maintainer gate; this patch makes no unmeasured speed or quality claim. See the [1.7.2 changelog](CHANGELOG.md#172---2026-07-25) and [release guidance](https://planr.so/docs/operations/release).
205
232
  - **1.7.1 — Leaner agent guidance and safer local releases:** Slimmed the hot-path Planr skills while preserving their execution and review contracts, moved maintainer benchmark inputs and results outside the public repository, added a fail-closed local release-evidence gate without API keys in CI, and verified the optional external Switchloom v0.3.2 integration. The public 1.7 eval CLI remains available in this patch. See the [1.7.1 changelog](CHANGELOG.md#171---2026-07-25) and [release guidance](https://planr.so/docs/operations/release).
@@ -220,7 +247,7 @@ Full documentation lives at [planr.so/docs](https://planr.so/docs).
220
247
  - [Plugins and Model Routing](https://planr.so/docs/plugins) · [Recipes](https://planr.so/docs/guides/recipes)
221
248
  - [Integrations and Host Hooks](https://planr.so/docs/integrations)
222
249
  - [CLI Reference](https://planr.so/docs/reference/cli) · [MCP Reference](https://planr.so/docs/reference/mcp)
223
- - [Codex](https://planr.so/docs/integrations/codex) · [Claude Code](https://planr.so/docs/integrations/claude-code) · [Cursor](https://planr.so/docs/integrations/cursor) · [Grok Build](https://planr.so/docs/integrations/grok-build)
250
+ - [Codex](https://planr.so/docs/integrations/codex) · [Claude Code](https://planr.so/docs/integrations/claude-code) · [Cursor](https://planr.so/docs/integrations/cursor) · [Grok Build](https://planr.so/docs/integrations/grok-build) · [Pi](https://planr.so/docs/integrations/pi)
224
251
  - [Daily Worker Loop](https://planr.so/docs/guides/daily-worker-loop)
225
252
  - [Task Graph Model](https://planr.so/docs/concepts/graph-and-readiness)
226
253
  - [Architecture](https://planr.so/docs/contributing/architecture)
package/docs/RELEASE.md CHANGED
@@ -24,25 +24,44 @@ full candidate verification and independent review on that exact commit.
24
24
 
25
25
  `scripts/release.sh` is the only supported publication path. It runs on clean
26
26
  `main`, requires every version and generated reference to already match the
27
- requested version, reruns the local eval and deterministic gates, and rejects
28
- any command that changes the reviewed source. Only then does it create and push
29
- the annotated tag. Editing manifests by hand or publishing an unprepared commit
30
- skips this ownership boundary.
27
+ requested version, verifies an independently green CI run and human approval
28
+ for the exact `HEAD` SHA, and only then creates and pushes the annotated tag.
29
+ It does not replay the Rust, docs, or packaging suites already proven by that
30
+ CI run. Security, secret, dependency, and workflow scanners are deliberate
31
+ local maintainer preflight commands rather than automatic pull-request or push
32
+ CI evidence. Editing manifests by hand or publishing an unprepared commit skips
33
+ this ownership boundary.
31
34
 
32
35
  ```bash
33
36
  scripts/prepare-release-candidate.sh 1.2.0
34
37
  ```
35
38
 
39
+ ```bash
40
+ export PLANR_RELEASE_CI_RECEIPT=/path/to/downloaded/promotion-receipt.json
41
+ export PLANR_RELEASE_APPROVAL=/path/to/exact-sha-release-approval.json
42
+ scripts/release.sh 1.2.0 "one-line release summary"
43
+ ```
44
+
45
+ Download `release-promotion-<sha>` from the successful `CI` run for the exact
46
+ main commit. The approval file uses schema `planr.release-approval.v1` and
47
+ contains only `approval_id`, `source_sha`, `version`, `decision: "approved"`,
48
+ `approved_by`, and `approved_at` in addition to `schema_version`. Publication
49
+ queries the recorded GitHub Actions run and rejects a stale SHA, non-main or
50
+ non-push run, failed conclusion, repository mismatch, or non-approved decision.
51
+
52
+ External evaluation is conditional. When the evaluated workflow subject or its
53
+ explicit evaluation policy changed since the previous release tag, also set:
54
+
36
55
  ```bash
37
56
  export PLANR_RELEASE_EVAL_SUITE="$HOME/projects/planr-evals/suites/planr-lean-skills-dogfood.suite.json"
38
57
  export PLANR_RELEASE_EVAL_RECEIPT=/path/to/sanitized-release-eval-receipt.json
39
58
  export PLANR_RELEASE_EVAL_DB=/path/to/planr-evals/results/eval.sqlite
40
- scripts/release.sh 1.2.0 "one-line release summary"
59
+ export PLANR_RELEASE_PLANR_BIN=/path/to/reviewed/candidate/planr
41
60
  ```
42
61
 
43
62
  Maintainer benchmarks, baselines, model/effort runs, and results live outside
44
63
  the public repository in `~/projects/planr-evals`; that workspace and its exact
45
- layout are not a Planr runtime contract. All three paths above are explicit so a
64
+ layout are not a Planr runtime contract. All external evaluation paths above are explicit so a
46
65
  release cannot silently use the product repository's ordinary `.planr` database
47
66
  or a stale bundled suite. The receipt is a short-lived local pointer containing
48
67
  only `schema_version`, comparison and candidate-run identities, suite and
@@ -76,7 +95,7 @@ The two scripts enforce, in order:
76
95
  4. the candidate build synchronizes `Cargo.lock`, then regenerates and strictly checks both references without Git mutation;
77
96
  5. candidate source, changelog, contracts, and generated files are committed and independently reviewed before publication approval;
78
97
  6. publication requires clean `main`, the exact prepared versions/references, a committed changelog section, and no existing tag;
79
- 7. the candidate binary validates the sanitized receipt and recomputed comparison, then deterministic tests, package, and security gates run without changing source;
98
+ 7. publication validates the exact-SHA CI and approval receipts; when the evaluated subject or policy changed, the reviewed candidate binary also validates the sanitized eval receipt and recomputed comparison;
80
99
  8. publication creates and pushes only the annotated `vx.y.z` tag for that reviewed commit.
81
100
 
82
101
  Two independent gates back the script:
@@ -145,6 +164,11 @@ scripts/ci-local.sh
145
164
  scripts/security-local.sh
146
165
  ```
147
166
 
167
+ `scripts/security-local.sh`, `cargo audit --deny warnings`, and local
168
+ `zizmor .` are on-demand maintainer checks. Pull-request and push workflows do
169
+ not install or execute BetterLeaks, Trivy, TruffleHog, cargo-audit, zizmor, or
170
+ equivalent dependency/security scanners.
171
+
148
172
  The external consumer E2E suite must pass when available on the release machine.
149
173
  Pull-request CI separately builds both Linux architectures through the canonical
150
174
  containerized release script, runs the full portability contract without
@@ -164,6 +188,9 @@ cat dist/planr-*/SHA256SUMS
164
188
  The artifact contains:
165
189
 
166
190
  - `planr`
191
+ - `scripts/host-capability-experiment.mjs`
192
+ - `scripts/host-capability-runtime/v1/schemas/*.schema.json`
193
+ - `scripts/planr-host-capability-validator`
167
194
  - `README.md`
168
195
  - `LICENSE.md`
169
196
  - `SHA256SUMS`
@@ -187,6 +214,9 @@ npm pack --dry-run
187
214
  The package must include:
188
215
 
189
216
  - `npm/bin/planr.js`
217
+ - `scripts/host-capability-experiment.mjs`
218
+ - `scripts/host-capability-runtime/v1/schemas/*.schema.json`
219
+ - `scripts/planr-host-capability-validator`
190
220
  - `docs/`
191
221
  - `docs/fixtures/mcp-contract.json`
192
222
  - `plugins/`
@@ -0,0 +1,283 @@
1
+ # Evidence Contract v1
2
+
3
+ Status: frozen for implementation
4
+
5
+ Evidence Contract v1 is Planr's local-first contract for proving acceptance criteria. It defines the durable vocabulary for proof obligations, observation requirements, capability declarations, execution attempts, untrusted proposals, trusted receipts, coverage verdicts, policy, presets, waivers, statuses, compatibility, and extension naming. It does not add public commands by itself and does not grant closure authority until later implementation slices wire the contract into storage, audit, review, trace, pick, and active-goal enforcement.
6
+
7
+ ## Ownership
8
+
9
+ - Product and build plans own authored acceptance criteria and the reviewed `ProofObligation` records bound to those criteria.
10
+ - The Evidence domain owns `ProofObligation`, `ObservationRequirement`, `VerificationCapabilityManifest`, `VerificationCapabilityInstance`, `EvidenceAttempt`, `UntrustedEvidenceProposal`, `EvidenceReceipt`, `CoverageVerdict`, `EvidencePolicy`, `ProofPreset`, and `EvidenceWaiver`.
11
+ - Planr assigns trusted provenance only from Planr-observed execution, verified host events, accepted MCP attestation, validated artifact import, or explicit approval-backed user attestation.
12
+ - Public JSON, agent-authored JSON, adapter stdout, logs, and artifacts may propose claims, but they cannot construct trusted provenance, execution identity, freshness, target binding, receipt digest, or closure authority.
13
+ - `src/canonical_json.rs` is the future single production owner for RFC 8785/JCS-compatible canonical bytes and SHA-256 digests used by this contract.
14
+ - `src/execution.rs` is the future shared owner for bounded process execution, cancellation, process-tree cleanup, output limits, and stdout/stderr digests.
15
+ - CLI, MCP, HTTP, docs, audit, hooks, review, trace, and pick surfaces are renderers or consumers. They must use the same Evidence application service and cannot implement alternate coverage decisions.
16
+
17
+ ## Existing-System Boundaries
18
+
19
+ - Eval remains the owner of comparative candidate evaluation, immutable eval runs, case results, samples, comparisons, invalidations, and eval evidence references. Eval evidence keeps `closure_authority = false`; an eval verdict may support review but cannot close or reopen Planr work by itself.
20
+ - Route Audit remains the owner of requested, resolved, and effective routing evidence. Evidence may consume a mapped provenance view, but it must not copy requested route declarations into effective execution proof.
21
+ - Agent Profiles, model-routing capability classes, usage-policy capability classes, MCP protocol capabilities, and context tags are dispatch or protocol metadata. They are not verification capability instances and do not prove runtime availability.
22
+ - Planr logs remain narrative and supporting records. A legacy `kind = verification` log is preserved as a claim and can be referenced, but it never automatically satisfies a binding observation.
23
+ - Pre-Evidence plans and non-binding scopes keep their historical closure compatibility until an operator explicitly migrates a plan into binding Evidence. Migration is plan-scoped, previewable, idempotent, and materializes ordinary immutable `ProofObligation` rows; it must not rewrite plans, logs, reviews, artifacts, or historical claims.
24
+ - Planr artifacts remain files or references with digests. An artifact alone is not trusted evidence unless a trusted receipt binds it to the source revision, target, environment, execution identity, observation results, and policy.
25
+
26
+ ## Versioning And Compatibility
27
+
28
+ - `schema_version` for all v1 objects is `evidence.contract.v1`.
29
+ - Additive optional fields are allowed only when old readers can ignore them without changing coverage, trust, freshness, or closure decisions.
30
+ - Status enum values, failure reason codes, provenance source kinds, namespace rules, digest algorithms, and trusted/untrusted boundaries are frozen for v1.
31
+ - Removing fields, renaming statuses, weakening required trust checks, changing digest semantics, or treating legacy logs as binding proof requires a new major contract.
32
+ - Unknown object kinds, observation types, schema versions, status values, provenance kinds, or namespaces are invalid for trusted coverage unless an explicit project extension registers them.
33
+ - Canonical JSON bytes and digests are computed over the object without non-contractual display fields. The frozen schema fixture in `docs/contracts/fixtures/evidence/v1/schemas/evidence-contract-v1.schema.json` names each object's required fields.
34
+
35
+ ## Contract Digests
36
+
37
+ Digest preimages use RFC 8785/JCS canonical JSON bytes over the contract object after the digest field being produced is removed. No other contract field is implicitly excluded.
38
+
39
+ - `EvidenceReceipt.receipt_digest`: hash the complete receipt object without the top-level `receipt_digest` field. Source, target, environment, capability, provenance, execution identity, observations, attempts, artifacts, raw result, config digest, fixture disclosure, permissions, sandbox, proof gaps, and timings all remain in the preimage.
40
+ - `EvidencePolicy.policy_digest`: hash the complete policy object without the top-level `policy_digest` field. Defaults, presets, observation schema registrations, adapter registrations, extension namespaces, trust/freshness/fixture/completion/layering policy all remain in the preimage. Nested `PolicyLayer.policy_digest` values are included as references to already-materialized lower-layer policies and must not repeat the enclosing policy digest.
41
+
42
+ The canonical fixture vectors are executable through `node scripts/verify-evidence-contract-vectors.mjs`.
43
+
44
+ ## Namespaces And Extensions
45
+
46
+ Built-in observation types and proof presets are starter vocabulary only. They are conveniences for common API, process, browser, desktop, mobile, deployment, filesystem, database, queue, and artifact cases, not a closed enum.
47
+
48
+ Observation type names and preset names use one of these namespaces:
49
+
50
+ - `planr.*`: reserved for Planr-owned built-ins.
51
+ - `mcp.*`: reserved for MCP attestation vocabulary that Planr validates.
52
+ - `host.*`: reserved for verified host-native capture contracts.
53
+ - Reverse-domain namespaces such as `com.example.queue.job.processed`.
54
+ - Project-local namespaces such as `project.queue.job.processed` inside the repository that defines them.
55
+
56
+ Custom observation types must reference a versioned JSON Schema and a registration digest in repository-local Evidence policy. Unknown, unregistered, or unavailable custom types remain uncovered and cannot be silently accepted as a weaker built-in.
57
+
58
+ ## Object Model
59
+
60
+ ### ProofObligation
61
+
62
+ A reviewed, binding or advisory contract for one acceptance criterion.
63
+
64
+ Required fields:
65
+
66
+ - `id`, `schema_version`, `criterion_id`, `plan_id`, optional `item_id`.
67
+ - `title`, `binding`, `observations`, `fixture_policy`, `freshness_policy`, `assurance_policy`.
68
+ - `policy_digest`, `config_digest`, `created_at`, and optional `supersedes`.
69
+
70
+ `binding = true` means closure must evaluate Evidence coverage. `binding = false` may be rendered as guidance but cannot block or satisfy closure.
71
+
72
+ ### ObservationRequirement
73
+
74
+ One atomic fact that must be observed.
75
+
76
+ Required fields:
77
+
78
+ - `id`, namespaced `type`, `subject`, `expected`, `target`, `environment`, `runtime_target`.
79
+ - Optional `payload_schema`, `state_transitions`, `persistence`, `negative_assertions`, `freshness_policy`, and `assurance_policy`.
80
+
81
+ The `type` says what fact is being observed, not which tool must observe it. Tool preference belongs in policy.
82
+
83
+ ### VerificationCapabilityManifest
84
+
85
+ A versioned static declaration from an adapter, host, or attestor.
86
+
87
+ Required fields:
88
+
89
+ - `id`, `schema_version`, `version`, `adapter_kind`, `adapter_digest`.
90
+ - Supported surfaces, observation type/schema/digest triples, interactions, artifacts, runtime targets, provenance path, permissions, costs, determinism, repeatability, independence, blind spots, and availability probe contract.
91
+ - Process adapters declare a closed `availability_probe.kind = process` contract with executable name, arguments, optional working directory, timeout, stdout/stderr byte limits, and the payload schema binding for emitted observations.
92
+
93
+ A manifest is a claim about what a method can observe. It is not proof that the method is available now.
94
+
95
+ ### VerificationCapabilityInstance
96
+
97
+ A runtime availability snapshot for one exact manifest, host, surface, version, environment, and permission set.
98
+
99
+ Required fields:
100
+
101
+ - `id`, `schema_version`, `manifest_id`, `manifest_digest`, `host`, `surface`, `host_version`, `adapter_version`, `environment`, `permissions`, `availability`, `probe_result`, `observed_payload_contract`, `limitations`, `captured_at`.
102
+
103
+ `probe_result.probe_execution_id` is the single authoritative runtime probe execution identity for a capability instance. A separate top-level probe execution ID is not part of the contract.
104
+
105
+ Instances expire or become stale when manifest, host, environment, permission, schema, or policy inputs change.
106
+
107
+ ### EvidenceAttempt
108
+
109
+ An immutable record of each verification attempt.
110
+
111
+ Required fields:
112
+
113
+ - `id`, `schema_version`, `criterion_id`, `obligation_id`, `capability_instance_id`.
114
+ - `started_at`, `ended_at`, `status`, resolved command or tool call, exit/signal/error details, retry lineage, stdout/stderr digests, raw result reference, artifact references, and output bounds.
115
+
116
+ Attempts are durable whether they pass, fail, time out, abort, skip, become unavailable, or end inconclusively. A later passing attempt does not erase earlier failures.
117
+
118
+ Attempt status and execution result must agree: `passed` requires clean exit code `0`; `failed` requires a non-zero exit code; `timed_out`, `skipped`, and `unavailable` require no exit code or signal and the matching error value; `aborted` requires no exit code plus an abort signal and error; `inconclusive` requires a completed exit with an inconclusive error marker.
119
+
120
+ ### UntrustedEvidenceProposal
121
+
122
+ Adapter, host, import, or agent input before Planr assigns provenance.
123
+
124
+ Required fields:
125
+
126
+ - `id`, `schema_version`, `source_kind`, `submitted_at`, `claims`, `artifact_refs`, `producer_metadata`.
127
+
128
+ Forbidden authoritative fields:
129
+
130
+ - Trusted provenance, execution identity, source revision binding, target digest binding, environment identity, freshness result, policy result, coverage result, receipt digest, or closure authority.
131
+
132
+ ### EvidenceReceipt
133
+
134
+ The trusted outer envelope created only by Planr or an accepted attestation verifier after validation.
135
+
136
+ Required fields:
137
+
138
+ - `id`, `schema_version`, `criterion_id`, `obligation_id`, `receipt_status`.
139
+ - Source revision/tree state, target digest/URI/deployment ID, environment identity, vantage point.
140
+ - Capability manifest and instance digests, Planr-assigned provenance, execution/tool-call ID.
141
+ - Observation results, attempt IDs and retry history, artifact references and digests.
142
+ - Fixture/mock disclosure, permission and sandbox state, proof gaps, started/ended timestamps, and `receipt_digest`.
143
+
144
+ Receipts can satisfy coverage only when trusted, fresh, policy-compliant, target-matched, schema-valid, and observation-equivalent to the requirement.
145
+
146
+ ### CoverageVerdict
147
+
148
+ The canonical coverage result for a criterion, item, plan, or goal.
149
+
150
+ Required fields:
151
+
152
+ - `id`, `schema_version`, `scope`, `evaluated_at`, `status`, `observation_coverage`, `validation_details`, `suggested_next_action`, `actionable_now`.
153
+
154
+ Allowed statuses:
155
+
156
+ - `satisfied`: every binding observation is covered by trusted, fresh, policy-compliant receipts.
157
+ - `unsatisfied`: one or more observations lack sufficient proof and a product or test failure is indicated.
158
+ - `blocked`: proof cannot currently be produced because a required capability, permission, sandbox, environment, or dependency is unavailable.
159
+ - `inconclusive`: attempted evidence cannot decide the required observation.
160
+ - `waived`: every remaining binding gap is covered by a valid scoped waiver.
161
+ - `stale`: previously sufficient evidence was invalidated by source, target, environment, policy, adapter, schema, configuration, or freshness change.
162
+
163
+ Gap coverage must match the verdict status:
164
+
165
+ - `unsatisfied` uses `missing` or `unsatisfied` gap entries with missing/product/verifier/policy/trust/schema/fixture/waiver/unsupported-observation reasons.
166
+ - `blocked` uses `blocked` gap entries with capability, permission, sandbox, environment, dependency, or runtime-target reasons.
167
+ - `inconclusive` uses `inconclusive` gap entries with timeout, abort, inconclusive-result, or verifier-failed reasons.
168
+ - `waived` uses `waived` gap entries, requires `waiver_id`, and records the underlying waived reason rather than `waiver_missing` or `waiver_expired`.
169
+ - `stale` uses `stale` gap entries with stale source, target, environment, policy, adapter schema, or configuration reasons.
170
+
171
+ ### EvidencePolicy, ProofPreset, EvidenceWaiver
172
+
173
+ Repository policy lives in `.planr/evidence.yaml`. It owns defaults, named presets, observation schema registrations, adapter registrations, trust/freshness/fixture/completion policy, and extension namespaces.
174
+
175
+ Adapter registrations bind the manifest ID, repository-local manifest path, manifest digest, observation types, payload schema bindings, provenance path, and closed execution contract used by Planr-observed process adapters.
176
+
177
+ Policy layer scope uses the frozen `EvidenceScope` chain. Repository policy defaults and extension declarations are document-level policy. Product-level policy is represented by `goal`, plan-level policy by `plan`, item-specific branches by `item`, and criterion-level policy by `criterion`.
178
+
179
+ Policy layers may strengthen lower-level requirements. Weakening requires an explicit waiver. Waivers include identity, reason, scope, exact observation IDs, source/target binding, created-at, expires-at, approval reference, and audit trail.
180
+
181
+ ## Status And Failure Vocabularies
182
+
183
+ `EvidenceAttempt.status` values:
184
+
185
+ - `passed`, `failed`, `skipped`, `timed_out`, `aborted`, `unavailable`, `inconclusive`.
186
+
187
+ `EvidenceReceipt.receipt_status` values:
188
+
189
+ - `trusted`, `rejected`, `untrusted`, `stale`, `superseded`.
190
+
191
+ `VerificationCapabilityInstance.availability.status` values:
192
+
193
+ - `available`, `unavailable`, `degraded`, `permission_denied`, `sandbox_blocked`, `unsupported`, `probe_failed`.
194
+
195
+ Coverage gap/failure reason codes:
196
+
197
+ - `missing_observation`, `missing_capability`, `permission_denied`, `sandbox_blocked`, `environment_unavailable`, `external_dependency_unavailable`, `product_failed`, `verifier_failed`, `timed_out`, `aborted`, `inconclusive_result`, `stale_source`, `stale_target`, `stale_environment`, `stale_policy`, `stale_adapter_schema`, `stale_configuration`, `target_mismatch`, `schema_mismatch`, `manifest_mismatch`, `untrusted_provenance`, `fixture_disallowed`, `mock_disallowed`, `insufficient_assurance`, `waiver_missing`, `waiver_expired`, `unknown_observation_type`, `unsupported_runtime_target`.
198
+
199
+ Legacy/operator aliases are rendered as aliases only and resolve to the canonical codes above: `capability_unavailable` -> `missing_capability`, `dependency_unavailable` -> `external_dependency_unavailable`, `policy_failed` -> `stale_policy`, `trust_failed` -> `untrusted_provenance`, and `stale_evidence` -> `stale_source`. Unknown legacy reasons are classified as `verifier_failed` rather than `product_failed`.
200
+
201
+ Explicit pre-Evidence migration input uses `schema_version = "planr.evidence.migration.v1"`, a single `plan_id`, and an `obligations[]` array of full `ProofObligation` objects whose `plan_id` matches the migration plan and whose `binding` is `true`. Preview is non-mutating. Apply is atomic for the migration payload: any conflict or malformed obligation leaves the plan with no newly bound partial obligations. Reapplying an identical payload is `unchanged`.
202
+
203
+ Process adapters may report a host boundary failure only with an exact single-field JSON line on stdout or stderr:
204
+
205
+ - `{"planr_adapter_boundary":"permission_denied"}`
206
+ - `{"planr_adapter_boundary":"sandbox_blocked"}`
207
+
208
+ Planr treats those structured lines as adapter boundary signals for failed process attempts and capability probes. Numeric exit codes alone do not imply `sandbox_blocked`; shell exit code 126 remains permission denied.
209
+
210
+ ## Trust And Provenance Rules
211
+
212
+ - Public deserialization always produces an `UntrustedEvidenceProposal` or authored policy object, never a trusted receipt.
213
+ - Adapter output can report observed facts and artifact references, but Planr binds the actual source revision, target, environment, execution identity, timings, retries, sandbox, permissions, output bounds, and receipt digest.
214
+ - Requested route metadata, declared agent profile metadata, and model names are not effective execution proof.
215
+ - A user approval can attest a fact only through the waiver or user-attestation path, with identity, reason, scope, expiry where applicable, and audit trail. It cannot silently convert agent JSON into Planr-observed execution.
216
+ - Artifacts referenced by trusted receipts require content digests and repository/root containment or explicit external URI policy.
217
+ - Fixture and mock use must be disclosed and accepted by policy for the exact observation.
218
+
219
+ ## Canonical Fixtures
220
+
221
+ The v1 frozen fixtures are:
222
+
223
+ - `docs/contracts/fixtures/evidence/v1/schemas/evidence-contract-v1.schema.json`
224
+ - `docs/contracts/fixtures/evidence/v1/examples/proof-obligation.json`
225
+ - `docs/contracts/fixtures/evidence/v1/examples/verification-capability-manifest.json`
226
+ - `docs/contracts/fixtures/evidence/v1/examples/verification-capability-instance.json`
227
+ - `docs/contracts/fixtures/evidence/v1/examples/evidence-attempt.json`
228
+ - `docs/contracts/fixtures/evidence/v1/examples/untrusted-evidence-proposal.json`
229
+ - `docs/contracts/fixtures/evidence/v1/examples/evidence-receipt.json`
230
+ - `docs/contracts/fixtures/evidence/v1/examples/coverage-verdict.json`
231
+ - `docs/contracts/fixtures/evidence/v1/examples/evidence-policy.json`
232
+ - `docs/contracts/fixtures/evidence/v1/examples/proof-preset.json`
233
+ - `docs/contracts/fixtures/evidence/v1/examples/evidence-waiver.json`
234
+ - `docs/contracts/fixtures/evidence/v1/negative/available-empty-probe-capability.json`
235
+ - `docs/contracts/fixtures/evidence/v1/negative/mismatched-probe-execution-id-capability.json`
236
+ - `docs/contracts/fixtures/evidence/v1/negative/empty-trust-bindings-receipt.json`
237
+ - `docs/contracts/fixtures/evidence/v1/negative/failed-zero-exit-attempt.json`
238
+ - `docs/contracts/fixtures/evidence/v1/negative/forged-trusted-receipt.json`
239
+ - `docs/contracts/fixtures/evidence/v1/negative/timed-out-zero-exit-attempt.json`
240
+ - `docs/contracts/fixtures/evidence/v1/negative/aborted-zero-exit-attempt.json`
241
+ - `docs/contracts/fixtures/evidence/v1/negative/skipped-zero-exit-attempt.json`
242
+ - `docs/contracts/fixtures/evidence/v1/negative/unavailable-zero-exit-attempt.json`
243
+ - `docs/contracts/fixtures/evidence/v1/negative/inconclusive-clean-exit-attempt.json`
244
+ - `docs/contracts/fixtures/evidence/v1/negative/passed-empty-attempt.json`
245
+ - `docs/contracts/fixtures/evidence/v1/negative/unbound-waiver.json`
246
+ - `docs/contracts/fixtures/evidence/v1/negative/minimal-policy-missing-owned-inputs.json`
247
+ - `docs/contracts/fixtures/evidence/v1/negative/policy-default-preset-unregistered.json`
248
+ - `docs/contracts/fixtures/evidence/v1/negative/policy-weakening-without-waiver.json`
249
+ - `docs/contracts/fixtures/evidence/v1/negative/satisfied-empty-coverage-verdict.json`
250
+ - `docs/contracts/fixtures/evidence/v1/negative/unsatisfied-coverage-without-gap.json`
251
+ - `docs/contracts/fixtures/evidence/v1/negative/process-probe-missing-output-limits.json`
252
+ - `docs/contracts/fixtures/evidence/v1/negative/adapter-registration-missing-execution-contract.json`
253
+ - `docs/contracts/fixtures/evidence/v1/negative/waived-coverage-missing-waiver-id.json`
254
+ - `docs/contracts/fixtures/evidence/v1/negative/waived-coverage-forbidden-gap-reason.json`
255
+ - `docs/contracts/fixtures/evidence/v1/negative/blocked-coverage-with-stale-reason.json`
256
+ - `docs/contracts/fixtures/evidence/v1/negative/inconclusive-coverage-with-blocked-reason.json`
257
+ - `docs/contracts/fixtures/evidence/v1/negative/stale-coverage-with-inconclusive-reason.json`
258
+
259
+ Replayable schema validation:
260
+
261
+ ```bash
262
+ set -e
263
+ schema='docs/contracts/fixtures/evidence/v1/schemas/evidence-contract-v1.schema.json'
264
+ node scripts/verify-evidence-contract-vectors.mjs
265
+ npx --yes ajv-cli@5.0.0 validate --spec=draft2020 --validate-formats=false -s "$schema" -d 'docs/contracts/fixtures/evidence/v1/examples/*.json'
266
+ for fixture in docs/contracts/fixtures/evidence/v1/negative/*.json; do
267
+ case "$fixture" in
268
+ *policy-default-preset-unregistered.json)
269
+ npx --yes ajv-cli@5.0.0 validate --spec=draft2020 --validate-formats=false -s "$schema" -d "$fixture"
270
+ echo "$fixture accepted by schema for semantic validation"
271
+ continue
272
+ ;;
273
+ esac
274
+ if npx --yes ajv-cli@5.0.0 validate --spec=draft2020 --validate-formats=false -s "$schema" -d "$fixture" >/tmp/planr-evidence-negative.out 2>&1; then
275
+ cat /tmp/planr-evidence-negative.out
276
+ echo "unexpected valid negative fixture: $fixture" >&2
277
+ exit 1
278
+ fi
279
+ echo "$fixture rejected as expected"
280
+ done
281
+ ```
282
+
283
+ Later implementation slices must use these fixtures as no-drift inputs for production canonicalization, schema validation, and coverage behavior.
@@ -0,0 +1,66 @@
1
+ {
2
+ "id": "cverdict-api-health-v1",
3
+ "schema_version": "evidence.contract.v1",
4
+ "scope": {
5
+ "kind": "criterion",
6
+ "id": "criterion-api-health",
7
+ "plan_id": "pln-example",
8
+ "item_id": "item-example"
9
+ },
10
+ "evaluated_at": "2026-07-28T12:00:08Z",
11
+ "status": "satisfied",
12
+ "observation_coverage": [
13
+ {
14
+ "requirement_id": "obs-http-200",
15
+ "status": "covered",
16
+ "covering_receipt_ids": ["erec-planr-api-health-v1"],
17
+ "covered_observation_ids": ["obs-http-200"]
18
+ }
19
+ ],
20
+ "validation_details": {
21
+ "trust": {
22
+ "status": "passed",
23
+ "checked_at": "2026-07-28T12:00:08Z",
24
+ "receipt_ids": ["erec-planr-api-health-v1"],
25
+ "gap_reasons": []
26
+ },
27
+ "freshness": {
28
+ "status": "passed",
29
+ "checked_at": "2026-07-28T12:00:08Z",
30
+ "receipt_ids": ["erec-planr-api-health-v1"],
31
+ "gap_reasons": []
32
+ },
33
+ "target": {
34
+ "status": "passed",
35
+ "checked_at": "2026-07-28T12:00:08Z",
36
+ "receipt_ids": ["erec-planr-api-health-v1"],
37
+ "gap_reasons": []
38
+ },
39
+ "schema": {
40
+ "status": "passed",
41
+ "checked_at": "2026-07-28T12:00:08Z",
42
+ "receipt_ids": ["erec-planr-api-health-v1"],
43
+ "gap_reasons": []
44
+ },
45
+ "provenance": {
46
+ "status": "passed",
47
+ "checked_at": "2026-07-28T12:00:08Z",
48
+ "receipt_ids": ["erec-planr-api-health-v1"],
49
+ "gap_reasons": []
50
+ },
51
+ "fixture": {
52
+ "status": "passed",
53
+ "checked_at": "2026-07-28T12:00:08Z",
54
+ "receipt_ids": ["erec-planr-api-health-v1"],
55
+ "gap_reasons": []
56
+ },
57
+ "completion": {
58
+ "status": "passed",
59
+ "checked_at": "2026-07-28T12:00:08Z",
60
+ "receipt_ids": ["erec-planr-api-health-v1"],
61
+ "gap_reasons": []
62
+ }
63
+ },
64
+ "suggested_next_action": "none",
65
+ "actionable_now": false
66
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "id": "eatt-planr-api-health-v1",
3
+ "schema_version": "evidence.contract.v1",
4
+ "criterion_id": "criterion-api-health",
5
+ "obligation_id": "pob-planr-api-health-v1",
6
+ "capability_instance_id": "vcinst-planr-http-process-v1",
7
+ "started_at": "2026-07-28T12:00:05Z",
8
+ "ended_at": "2026-07-28T12:00:06Z",
9
+ "status": "passed",
10
+ "resolved_command": {
11
+ "kind": "command",
12
+ "command": ["curl", "-fsS", "http://127.0.0.1:4173/health"],
13
+ "cwd": "$PLANR_REPOSITORY_ROOT"
14
+ },
15
+ "exit": {
16
+ "exit_code": 0,
17
+ "signal": null,
18
+ "error": null
19
+ },
20
+ "retry_lineage": {
21
+ "attempt_number": 1,
22
+ "max_attempts": 1,
23
+ "previous_attempt_ids": []
24
+ },
25
+ "stdout_digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
26
+ "stderr_digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
27
+ "raw_result": {
28
+ "kind": "artifact",
29
+ "artifact_id": "artifact-http-response",
30
+ "digest": "sha256:8888888888888888888888888888888888888888888888888888888888888888"
31
+ },
32
+ "artifacts": [],
33
+ "output_bounds": {
34
+ "stdout_bytes": 16,
35
+ "stderr_bytes": 0,
36
+ "stdout_truncated": false,
37
+ "stderr_truncated": false
38
+ }
39
+ }