planr 1.9.0 → 1.10.0-alpha.10

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 (90) hide show
  1. package/README.md +32 -5
  2. package/docs/ARCHITECTURE.md +45 -9
  3. package/docs/RELEASE.md +57 -10
  4. package/docs/SWITCHLOOM_COMPATIBILITY.md +9 -41
  5. package/docs/contracts/BROWSER_HARNESS_ADAPTER_V1.md +85 -0
  6. package/docs/contracts/EVAL_CONTRACT_V1.md +1 -1
  7. package/docs/contracts/EVIDENCE_ADAPTER_PROTOCOL_V1.md +98 -0
  8. package/docs/contracts/EVIDENCE_CONTRACT_V1.md +382 -0
  9. package/docs/contracts/V1_1_DIFFERENTIATION_CONTRACT.md +16 -16
  10. package/docs/contracts/fixtures/evidence/v1/examples/coverage-verdict.json +66 -0
  11. package/docs/contracts/fixtures/evidence/v1/examples/evidence-attempt.json +39 -0
  12. package/docs/contracts/fixtures/evidence/v1/examples/evidence-policy.json +108 -0
  13. package/docs/contracts/fixtures/evidence/v1/examples/evidence-receipt.json +93 -0
  14. package/docs/contracts/fixtures/evidence/v1/examples/evidence-waiver.json +31 -0
  15. package/docs/contracts/fixtures/evidence/v1/examples/proof-obligation.json +55 -0
  16. package/docs/contracts/fixtures/evidence/v1/examples/proof-preset.json +19 -0
  17. package/docs/contracts/fixtures/evidence/v1/examples/untrusted-evidence-proposal.json +20 -0
  18. package/docs/contracts/fixtures/evidence/v1/examples/verification-capability-instance.json +39 -0
  19. package/docs/contracts/fixtures/evidence/v1/examples/verification-capability-manifest.json +52 -0
  20. package/docs/contracts/fixtures/evidence/v1/negative/aborted-zero-exit-attempt.json +39 -0
  21. package/docs/contracts/fixtures/evidence/v1/negative/adapter-registration-missing-execution-contract.json +88 -0
  22. package/docs/contracts/fixtures/evidence/v1/negative/available-empty-probe-capability.json +27 -0
  23. package/docs/contracts/fixtures/evidence/v1/negative/blocked-coverage-with-stale-reason.json +27 -0
  24. package/docs/contracts/fixtures/evidence/v1/negative/empty-trust-bindings-receipt.json +72 -0
  25. package/docs/contracts/fixtures/evidence/v1/negative/failed-zero-exit-attempt.json +39 -0
  26. package/docs/contracts/fixtures/evidence/v1/negative/forged-trusted-receipt.json +35 -0
  27. package/docs/contracts/fixtures/evidence/v1/negative/inconclusive-clean-exit-attempt.json +39 -0
  28. package/docs/contracts/fixtures/evidence/v1/negative/inconclusive-coverage-with-blocked-reason.json +27 -0
  29. package/docs/contracts/fixtures/evidence/v1/negative/minimal-policy-missing-owned-inputs.json +5 -0
  30. package/docs/contracts/fixtures/evidence/v1/negative/mismatched-probe-execution-id-capability.json +42 -0
  31. package/docs/contracts/fixtures/evidence/v1/negative/passed-empty-attempt.json +22 -0
  32. package/docs/contracts/fixtures/evidence/v1/negative/policy-default-preset-unregistered.json +102 -0
  33. package/docs/contracts/fixtures/evidence/v1/negative/policy-weakening-without-waiver.json +102 -0
  34. package/docs/contracts/fixtures/evidence/v1/negative/process-probe-missing-output-limits.json +49 -0
  35. package/docs/contracts/fixtures/evidence/v1/negative/satisfied-empty-coverage-verdict.json +14 -0
  36. package/docs/contracts/fixtures/evidence/v1/negative/skipped-zero-exit-attempt.json +39 -0
  37. package/docs/contracts/fixtures/evidence/v1/negative/stale-coverage-with-inconclusive-reason.json +27 -0
  38. package/docs/contracts/fixtures/evidence/v1/negative/timed-out-zero-exit-attempt.json +39 -0
  39. package/docs/contracts/fixtures/evidence/v1/negative/unavailable-zero-exit-attempt.json +39 -0
  40. package/docs/contracts/fixtures/evidence/v1/negative/unbound-waiver.json +21 -0
  41. package/docs/contracts/fixtures/evidence/v1/negative/unsatisfied-coverage-without-gap.json +63 -0
  42. package/docs/contracts/fixtures/evidence/v1/negative/waived-coverage-forbidden-gap-reason.json +28 -0
  43. package/docs/contracts/fixtures/evidence/v1/negative/waived-coverage-missing-waiver-id.json +27 -0
  44. package/docs/contracts/fixtures/evidence/v1/schemas/evidence-contract-v1.schema.json +2685 -0
  45. package/docs/contracts/schemas/com.planr.web.dom_state.v1.schema.json +30 -0
  46. package/docs/documentation/CONTRACT.md +1 -1
  47. package/docs/documentation/COVERAGE.md +9 -6
  48. package/docs/documentation/INFORMATION_ARCHITECTURE.md +2 -2
  49. package/docs/fixtures/mcp-contract.json +27 -3
  50. package/npm/bin/native-launcher.js +67 -0
  51. package/npm/bin/planr-browser-harness-adapter.js +8 -0
  52. package/npm/bin/planr.js +5 -51
  53. package/npm/native/darwin-arm64/planr +0 -0
  54. package/npm/native/darwin-arm64/planr-browser-harness-adapter +0 -0
  55. package/npm/native/darwin-arm64/planr-host-capability-validator +0 -0
  56. package/npm/native/darwin-x86_64/planr +0 -0
  57. package/npm/native/darwin-x86_64/planr-browser-harness-adapter +0 -0
  58. package/npm/native/darwin-x86_64/planr-host-capability-validator +0 -0
  59. package/npm/native/linux-arm64/planr +0 -0
  60. package/npm/native/linux-arm64/planr-browser-harness-adapter +0 -0
  61. package/npm/native/linux-arm64/planr-host-capability-validator +0 -0
  62. package/npm/native/linux-x86_64/planr +0 -0
  63. package/npm/native/linux-x86_64/planr-browser-harness-adapter +0 -0
  64. package/npm/native/linux-x86_64/planr-host-capability-validator +0 -0
  65. package/package.json +19 -5
  66. package/plugins/planr/.claude-plugin/plugin.json +1 -1
  67. package/plugins/planr/.codex-plugin/plugin.json +1 -1
  68. package/plugins/planr/agents/pi/planr-reviewer.md +8 -4
  69. package/plugins/planr/agents/pi/planr-worker.md +26 -5
  70. package/plugins/planr/agents/planr-reviewer.md +11 -7
  71. package/plugins/planr/agents/planr-worker.md +28 -4
  72. package/plugins/planr/skills/planr/SKILL.md +12 -4
  73. package/plugins/planr/skills/planr-goal/SKILL.md +9 -4
  74. package/plugins/planr/skills/planr-loop/SKILL.md +119 -46
  75. package/plugins/planr/skills/planr-loop/agents/planr-reviewer.md +11 -7
  76. package/plugins/planr/skills/planr-loop/agents/planr-worker.md +27 -4
  77. package/plugins/planr/skills/planr-loop/references/host-dispatch.md +47 -6
  78. package/plugins/planr/skills/planr-loop/references/recovery-and-verification.md +6 -4
  79. package/plugins/planr/skills/planr-plan/SKILL.md +15 -2
  80. package/plugins/planr/skills/planr-review/SKILL.md +14 -10
  81. package/plugins/planr/skills/planr-status/SKILL.md +3 -1
  82. package/plugins/planr/skills/planr-summary/SKILL.md +3 -1
  83. package/plugins/planr/skills/planr-task-graph/SKILL.md +10 -4
  84. package/plugins/planr/skills/planr-verify-web/SKILL.md +23 -38
  85. package/plugins/planr/skills/planr-work/SKILL.md +34 -11
  86. package/scripts/host-capability-experiment.mjs +2481 -0
  87. package/scripts/host-capability-runtime/v1/schemas/host-capability-expected-manifest.schema.json +377 -0
  88. package/scripts/host-capability-runtime/v1/schemas/host-capability-observed-raw.schema.json +439 -0
  89. package/scripts/host-capability-runtime/v1/schemas/host-capability-provenance.schema.json +178 -0
  90. package/scripts/planr-host-capability-validator +57 -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>
@@ -180,8 +206,8 @@ Use $planr-goal to prepare an autonomous goal for the weekly overview feature.
180
206
  context (tag: goal-contract).
181
207
 
182
208
  Goal: ship the weekly overview feature. DONE when every in-scope map item is closed
183
- with log evidence, all reviews are closed complete, and a live verification log shows
184
- the feature working in the browser. Iteration budget: 10.
209
+ with implementation evidence, all reviews are closed complete, and canonical Evidence
210
+ coverage proves the feature working in the browser. Iteration budget: 10.
185
211
  ```
186
212
 
187
213
  Mid-project work (a new feature, refactor, or fix on an existing project) works the same — it gets its own feature-scoped plan and extends the existing map. Both journeys with example prompts: [Prompt Recipes](https://planr.so/docs/agents/prompt-recipes). Coding agents inspect progress with the compact default `planr map show` or, preferably, `planr map show --json`. The tree preserves exact dependency vocabulary while marking satisfied edges as `blocks✓`; active `blocks` stay red. The boxed `planr map show --view diagram` renderer is exclusively for human supervision and uses neutral `then` routes once those dependencies are satisfied. Agents must not invoke it. Humans can add `--full` for complete status, title, worker, critical-lane, and pressure details. Interactive map output colors states automatically; `--no-color` and `NO_COLOR` keep it plain.
@@ -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)
@@ -22,24 +22,26 @@ Planr V1 is a single Rust binary with explicit module ownership. The crate stays
22
22
  - `src/app/commands.rs`: general CLI use-case orchestration. Owns project, plan, map, item, link, pick, approval, log, close, review, context, search, doctor, and shared install command handlers.
23
23
  - `src/app/grok.rs`: Grok-specific install orchestration. Owns safe project TOML reconciliation, repository workflow writes, and the explicit no-hooks result.
24
24
  - `src/app/prompts.rs`: CLI, MCP, and HTTP prompt output. Host routing prompt composition remains in `src/app/agents.rs`.
25
- - `src/app/flow.rs`: compound work-flow boundary. Owns evidence log writing (with heartbeat folding), the close transition core, review-request creation, the pick work packet, and the `done` command that chains them for CLI, HTTP, and MCP surfaces.
25
+ - `src/app/flow.rs`: compound workflow boundary. Owns evidence log writing (with heartbeat folding), canonical FeatureRun settlement input normalization, the close transition core, the pick work packet, and the `done` command shared by CLI, HTTP, and MCP surfaces.
26
26
  - `src/app/git_review.rs`: Git and PR review evidence boundary. Owns worktree detection, scoped changed-file provenance, PR URL context, and dirty-worktree safety projections.
27
27
  - `src/app/mcp.rs`: MCP stdio boundary. Owns MCP protocol request routing, tool calls, resource reads, and prompt responses.
28
- - `src/app/packages.rs`: package import/export boundary. Owns reusable JSON templates, preview-before-import, review artifact package import, and local-first encrypted bundle metadata.
28
+ - `src/app/packages.rs`: package import/export boundary. Owns reusable JSON templates, preview-before-import, durable ReviewGate package projections, and local-first encrypted bundle metadata.
29
29
  - `src/app/http.rs`: localhost HTTP/SSE boundary. Owns HTTP request parsing, routes, SSE stream output, and HTTP response mapping.
30
30
  - `src/app/repository.rs`: application data access helpers. Owns Planr query/update helpers over projects, plans, graph items, links, runs, logs, artifacts, events, approvals, search, and map projections.
31
31
  - `src/app/lease.rs`: worker lease ownership. Owns the single pick query (`PickFilter`: exclude, work type, plan scope), worker ownership checks, runtime heartbeat/progress/pause state, and stale-pick detection.
32
- - `src/app/review.rs`: review-gate application logic. Owns review annotations, feedback ingestion, evidence artifacts, review closure, and review target lookup.
32
+ - `src/app/review.rs`: ReviewGate application logic. Owns review annotations, feedback ingestion, scoped evidence, durable attempt completion, finding resolution, and gate lookup.
33
33
  - `src/app/recovery.rs`: recovery automation logic. Owns item retry policy configuration, task conditions, stale/timed-out sweeps, retry scheduling, and recovery result projections.
34
- - `src/app/review_workspace.rs`: local review workspace boundary. Owns the browser review HTML, workspace data projection, and privacy-minimized Git diff evidence.
34
+ - `src/app/execution_run.rs`: canonical FeatureRun and ReviewGate application boundary. Owns run phases, outcome batching and settlement, typed escalation, role leases, durable findings/re-review, and final product review projections.
35
+ - `src/app/execution_state.rs`: canonical `planr.execution_state.v2` read boundary. It projects one run-scoped FeatureRun, active batch, role owner, persisted budget amounts/provenance/digest/deadline, ReviewGate, attempts, findings, stable reason code, and next action for CLI, MCP, HTTP, pick, trace, status, recovery, package, and audit consumers.
35
36
  - `src/app/surfaces.rs`: non-CLI runtime surfaces. Owns trace, scrub, artifact, event, debug, export, and import command handlers.
36
37
  - `src/app/inspection.rs`: local inspection helpers. Owns debug bundles, context/link snapshots, pick context, secret scans, export value assembly, run recording, search results, and Planr-directory import parsing.
37
- - `src/app/audit.rs`: goal contract audit boundary. Owns the clause-by-clause `plan audit` verdict (items settled, reviews complete, approvals clear, verification logged) and its human rendering.
38
+ - `src/app/audit.rs`: goal contract audit boundary. Owns the clause-by-clause `plan audit` verdict (items settled, required independent material reviews, exactly one current independent final product review, approvals clear, canonical Evidence coverage) and its human rendering. Claim-only verification logs remain isolated to frozen pre-Evidence compatibility.
38
39
  - `src/app/application.rs`: shared surface-mutation boundary. Owns the approval request/approve/deny, context, log, artifact, and close mutations reused verbatim by CLI, MCP, and HTTP handlers so the three surfaces cannot drift.
39
- - `src/app/repository/`: focused data-access submodules (`item.rs`, `plan.rs`, `project.rs`, `link.rs`, `context.rs`, `evidence.rs`, `search.rs`) split out of `src/app/repository.rs` by entity ownership.
40
+ - `src/app/repository/`: focused data-access submodules (`item.rs`, `plan.rs`, `project.rs`, `link.rs`, `context.rs`, `evidence.rs`, `execution_run.rs`, `search.rs`) split out of `src/app/repository.rs` by entity ownership. Execution-state reads select ReviewGates strictly by run id; project/plan-wide history is never projected as the current run.
40
41
  - `src/model.rs`: JSON-facing data transfer types and typed vocabulary. Owns serializable Planr DTOs plus the `ItemStatus`, `WorkType`, `LinkKind`, and `ApprovalStatus` enums with their parsing and display behavior, used by CLI JSON, MCP, HTTP, storage rows, and tests.
41
42
  - `src/storage/mod.rs`: SQLite connection boundary. Owns default database path, connection setup, pragma configuration, and storage submodule exports.
42
43
  - `src/storage/schema.rs`: SQLite schema boundary. Owns DDL, additive schema upgrade helpers, and schema version recording.
44
+ - `src/storage/execution_run_schema.rs`: the sole persisted compatibility boundary for FeatureRun rollout. It upgrades already-stored review/fix history into durable terminal history, but no application, packet, agent asset, or documentation path produces the superseded live shape.
43
45
  - `src/storage/rows.rs`: SQLite row mapping boundary. Owns row-to-DTO and row-to-JSON mapping functions.
44
46
  - `src/planpack.rs`: Markdown package generation and parsing. Owns project context templates, product/build plan templates, plan metadata parsing, hashes, search body extraction, and task extraction.
45
47
  - `src/agents.rs`: agent profile registry core. Owns `.planr/agents.toml` parsing, registry validation warnings, and the pure advisory `resolve_route` precedence logic (override > work_type > plan > default); no storage or host concerns.
@@ -53,6 +55,40 @@ Planr V1 is a single Rust binary with explicit module ownership. The crate stays
53
55
  - `src/rolefiles.rs`: static host workflow roles and Cursor skill payloads. It does not select or pin models; externally generated routing artifacts stay outside Planr ownership.
54
56
  - `src/util.rs`: small CLI-boundary utilities. Owns ids, timestamps, path helpers, output formatting, and safe file writes.
55
57
 
58
+ ## FeatureRun Execution Boundary
59
+
60
+ Every live worker decision is a typed work packet:
61
+
62
+ - `kind: "outcome"` is ordinary maker work; `mode: "finding_repair"` returns named findings to the same responsible maker and ReviewGate without creating a fix item.
63
+ - `kind: "review_gate"` is independently leased checker work. Attempts and findings remain children of that gate, never graph items.
64
+ - `kind: "verification"` is a coordinator-owned verifier lease over a frozen canonical source digest. Product source is read-only; trusted Evidence can commit only through the source-checked Evidence transaction. The coordinator calls `evidence verify` without another model.
65
+ - Releasing verification is an application-owned transition: the item lease, FeatureRun verifier role, and verification budget reconcile atomically back to `source_frozen`. `pick release --repair <reference>` additionally invalidates the frozen candidate and routes a fresh repair batch to the recorded maker; the failed verifier lease is never resumed.
66
+ - An accepted material checkpoint is source-bound after any product or admission repair. Repair settlement preserves the prior attempt, reopens the same gate with the active freeze revision/digest and repair-obligation lineage, and leaves verification unleaseable until a fresh independent acceptance of that exact binding.
67
+ - `kind: "hold"` is an admission or capability stop. A driver must report its classification and next action; it cannot reinterpret the hold as permission to replace the maker, weaken verification, or open an ad hoc review.
68
+
69
+ All four packets embed the same run-scoped `planr.execution_state.v2` projection. Host skills, generated roles, installed copies, and Stop hooks render that state but own no lifecycle or budget policy. Ordinary maker settlement uses plain `planr done`; only an allowed protected-risk interrupt uses structured escalation. Review findings are logged and resolved on the existing gate. Evidence runs once after stable source freeze and selectively reruns only invalidated obligations after a product repair.
70
+
71
+ The one exception is persisted database input in `src/storage/execution_run_schema.rs`. Existing user databases may contain historical review/fix graph rows, so the schema upgrade consumes them once into terminal history. That read boundary does not justify aliases, fallback commands, dual DTOs, or live legacy producers elsewhere.
72
+
73
+ ## Planr 2.0 Immutable Budget Boundary
74
+
75
+ The Planr 2.0 budget authority is one immutable `planr.feature_run_budget_contract.v2` created atomically with each FeatureRun. Bounded contracts contain a persisted UTC run-start anchor, complete wall-seconds/tool-call/token totals, exact maker/verification/review/repair/release allocations, per-dimension metering requirements, and a canonical digest. Unbounded mode is an explicit contract with no numeric limits or reserves. Every admitted bounded task carries positive maxima for all three dimensions and an overflow-checked absolute UTC deadline.
76
+
77
+ Ownership is singular and dependencies are one-way:
78
+
79
+ - `src/usage_policy.rs` owns the provider-neutral contract types, validation, provenance, phase protection, snapshots, and pure checked arithmetic.
80
+ - `src/execution_policy.rs` owns pure admission over typed concurrency plus persisted budget snapshots.
81
+ - `src/app/execution_run.rs` resolves authored policy once and binds the immutable contract to run creation.
82
+ - `src/app/feature_run_evidence.rs` owns transactional reservation, append-only observation, reconciliation, phase release, and hold sequencing.
83
+ - `src/app/execution_state.rs` owns the sole `planr.execution_state.v2` projection reused by CLI, MCP, HTTP, work packets, trace, status, generated roles, and skills.
84
+ - Storage owns insert-only persistence and integrity mechanics; host adapters only enforce supplied maxima/deadlines and report observations with provenance.
85
+
86
+ Runtime decisions never reload `.planr/policy.toml`, fabricate allowances, infer trusted usage from projections, synthesize missing active-run state, or expose a compatibility budget DTO. Missing, invalid, corrupt, or unenforceable budget state is a typed hold before dispatch.
87
+
88
+ An incompatible active FeatureRun is retired only through the plan-scoped application lifecycle in `src/app/execution_run.rs`. Pure eligibility and policy-cancel state changes live in `src/execution_run.rs`; `src/app/repository/execution_run.rs` ends the batch and leases, updates the run with optimistic concurrency, and records provenance in one transaction. CLI, MCP, and HTTP only transport the closed `incompatible-budget` reason and reuse the canonical result. Restart never writes a budget contract or successor run; a later ordinary pick remains the sole atomic run-plus-contract creation path.
89
+
90
+ A compatible budget-held FeatureRun resumes only through `planr run resolve-budget-hold --plan <id>`, owned by `src/app/feature_run_evidence.rs`. The application transaction revalidates the immutable contract, persisted snapshot, active reservation deadlines, exact held phase, canonical role owner, and lease generation before restoring that phase. Incompatible contracts require restart; capability holds, corrupt state, expired deadlines, missing reservations, unrepaired ceilings, and owner mismatches remain held. MCP and HTTP transport the same typed application result without policy or arithmetic.
91
+
56
92
  ## Eval Contract V1/V1.1 Ownership
57
93
 
58
94
  The frozen product contract lives in `docs/contracts/EVAL_CONTRACT_V1.md` until implementation promotes it into code. Its V1.1 efficiency-evidence amendment is additive and keeps the same owner split:
@@ -72,7 +108,7 @@ The frozen product contract lives in `docs/contracts/EVAL_CONTRACT_V1.md` until
72
108
  - Mutations shared by more than one surface (CLI, MCP, HTTP) belong in `src/app/application.rs`; surface handlers must call the shared helper instead of repeating SQL.
73
109
  - Markdown templates belong in `planpack.rs`; command handlers should request generated file sets instead of embedding large template bodies.
74
110
  - Agent install metadata and MCP schema descriptors belong in `src/integrations.rs`; client-specific strings should not drift across command handlers and docs.
75
- - DTO and vocabulary-enum changes belong in `src/model.rs`; JSON response shapes should reuse those DTOs before adding ad hoc maps.
111
+ - General graph DTO and vocabulary-enum changes belong in `src/model.rs`; FeatureRun/ExecutionBatch/ReviewGate status projection changes belong in `src/app/execution_state.rs`. JSON response shapes reuse those owners before adding ad hoc maps.
76
112
  - Item status, work type, link kind, and approval status values are typed enums; new states must be added to the enum, not smuggled in as strings.
77
113
  - Utility code must stay narrow. If a helper starts owning product behavior, move it to the owning module instead of growing `util.rs`.
78
114
  - Do not add catch-all `common`, `shared`, or broad utility modules. New modules must name a durable ownership boundary.
@@ -81,10 +117,10 @@ The frozen product contract lives in `docs/contracts/EVAL_CONTRACT_V1.md` until
81
117
 
82
118
  Planr remains a single crate for V1 because:
83
119
 
84
- - there is one deployable binary and no separate service or reusable library boundary;
120
+ - one crate owns the CLI and its optional companion executables;
85
121
  - the current behavior contract is tighter when CLI, MCP, HTTP, storage, and docs ship together;
86
122
  - module-level ownership gives the needed architecture separation without duplicating Cargo settings or release packaging;
87
- - npm, release, and external consumer tests assume one native binary named `planr`.
123
+ - npm, release, and external consumer tests treat `planr` as the product entry point. They also package provider-specific companion executables when Planr ships them.
88
124
 
89
125
  A Cargo workspace was tried and reverted: it produced anemic crates whose only job was being a layer, plus re-export shims in the binary. A workspace should be introduced only after a concrete deployable, reuse, compilation, or team ownership boundary exists and package/release scripts are updated in the same change.
90
126
 
package/docs/RELEASE.md CHANGED
@@ -24,25 +24,47 @@ 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 verifies that the changelog predecessor's local
29
+ tag object exactly matches the tag ref returned by `origin`. Only then does it
30
+ create and push the annotated tag.
31
+ It does not replay the Rust, docs, or packaging suites already proven by that
32
+ CI run. Security, secret, dependency, and workflow scanners are deliberate
33
+ local maintainer preflight commands rather than automatic pull-request or push
34
+ CI evidence. Editing manifests by hand or publishing an unprepared commit skips
35
+ this ownership boundary.
31
36
 
32
37
  ```bash
33
38
  scripts/prepare-release-candidate.sh 1.2.0
34
39
  ```
35
40
 
41
+ ```bash
42
+ export PLANR_RELEASE_CI_RECEIPT=/path/to/downloaded/promotion-receipt.json
43
+ export PLANR_RELEASE_APPROVAL=/path/to/exact-sha-release-approval.json
44
+ scripts/release.sh 1.2.0 "one-line release summary"
45
+ ```
46
+
47
+ Download `release-promotion-<sha>` from the successful `CI` run for the exact
48
+ main commit. The approval file uses schema `planr.release-approval.v1` and
49
+ contains only `approval_id`, `source_sha`, `version`, `decision: "approved"`,
50
+ `approved_by`, and `approved_at` in addition to `schema_version`. Publication
51
+ queries the recorded GitHub Actions run and rejects a stale SHA, non-main or
52
+ non-push run, failed conclusion, repository mismatch, or non-approved decision.
53
+
54
+ External evaluation is a stable-release gate. When the evaluated workflow
55
+ subject or its explicit evaluation policy changed since the previous release
56
+ tag, a stable release also requires:
57
+
36
58
  ```bash
37
59
  export PLANR_RELEASE_EVAL_SUITE="$HOME/projects/planr-evals/suites/planr-lean-skills-dogfood.suite.json"
38
60
  export PLANR_RELEASE_EVAL_RECEIPT=/path/to/sanitized-release-eval-receipt.json
39
61
  export PLANR_RELEASE_EVAL_DB=/path/to/planr-evals/results/eval.sqlite
40
- scripts/release.sh 1.2.0 "one-line release summary"
62
+ export PLANR_RELEASE_PLANR_BIN=/path/to/reviewed/candidate/planr
41
63
  ```
42
64
 
43
65
  Maintainer benchmarks, baselines, model/effort runs, and results live outside
44
66
  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
67
+ layout are not a Planr runtime contract. All external evaluation paths above are explicit so a
46
68
  release cannot silently use the product repository's ordinary `.planr` database
47
69
  or a stale bundled suite. The receipt is a short-lived local pointer containing
48
70
  only `schema_version`, comparison and candidate-run identities, suite and
@@ -75,8 +97,8 @@ The two scripts enforce, in order:
75
97
  3. frozen workspace synchronization cannot change `pnpm-lock.yaml`;
76
98
  4. the candidate build synchronizes `Cargo.lock`, then regenerates and strictly checks both references without Git mutation;
77
99
  5. candidate source, changelog, contracts, and generated files are committed and independently reviewed before publication approval;
78
- 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;
100
+ 6. publication requires clean `main`, the exact prepared versions/references, a committed changelog section, an exact local predecessor tag matching `origin`, and no existing target tag;
101
+ 7. publication validates the exact-SHA CI and approval receipts; a stable release whose evaluated subject or policy changed also validates the sanitized eval receipt and recomputed comparison;
80
102
  8. publication creates and pushes only the annotated `vx.y.z` tag for that reviewed commit.
81
103
 
82
104
  Two independent gates back the script:
@@ -103,7 +125,18 @@ The changelog section requirement applies verbatim (`## [1.2.0-alpha.1]`). What
103
125
  - npm publishes under the **`alpha` dist-tag** instead of `latest`: plain `npm install -g planr` keeps resolving stable, testers opt in with `npm install -g planr@alpha`.
104
126
  - The **Homebrew tap never moves** on pre-release tags.
105
127
 
106
- Only `-alpha.N`, `-beta.N`, and `-rc.N` suffixes are accepted; everything else the script rejects.
128
+ Only canonical SemVer core numbers and `-alpha.N`, `-beta.N`, or `-rc.N`
129
+ suffixes are accepted. Numeric identifiers have no leading zero unless the
130
+ identifier is exactly `0`.
131
+
132
+ Pre-release publication deliberately does not require a model-evaluation
133
+ receipt before publication. It still requires a clean exact commit on `main`,
134
+ the authenticated green CI promotion receipt, human approval bound to that SHA
135
+ and version, synchronized manifests and generated references, and the committed
136
+ changelog/release contracts. After publication, install that exact prerelease
137
+ and dogfood the installed artifact. That dogfood evidence informs and gates the
138
+ next promotion decision; it is never fabricated from the pre-publication source
139
+ tree. Stable publication keeps the conditional evaluation gate described above.
107
140
 
108
141
  ## Automated Release Pipeline
109
142
 
@@ -145,6 +178,11 @@ scripts/ci-local.sh
145
178
  scripts/security-local.sh
146
179
  ```
147
180
 
181
+ `scripts/security-local.sh`, `cargo audit --deny warnings`, and local
182
+ `zizmor .` are on-demand maintainer checks. Pull-request and push workflows do
183
+ not install or execute BetterLeaks, Trivy, TruffleHog, cargo-audit, zizmor, or
184
+ equivalent dependency/security scanners.
185
+
148
186
  The external consumer E2E suite must pass when available on the release machine.
149
187
  Pull-request CI separately builds both Linux architectures through the canonical
150
188
  containerized release script, runs the full portability contract without
@@ -164,6 +202,10 @@ cat dist/planr-*/SHA256SUMS
164
202
  The artifact contains:
165
203
 
166
204
  - `planr`
205
+ - `planr-browser-harness-adapter`
206
+ - `scripts/host-capability-experiment.mjs`
207
+ - `scripts/host-capability-runtime/v1/schemas/*.schema.json`
208
+ - `scripts/planr-host-capability-validator`
167
209
  - `README.md`
168
210
  - `LICENSE.md`
169
211
  - `SHA256SUMS`
@@ -187,13 +229,18 @@ npm pack --dry-run
187
229
  The package must include:
188
230
 
189
231
  - `npm/bin/planr.js`
232
+ - `npm/bin/planr-browser-harness-adapter.js`
233
+ - `npm/bin/native-launcher.js`
234
+ - `scripts/host-capability-experiment.mjs`
235
+ - `scripts/host-capability-runtime/v1/schemas/*.schema.json`
236
+ - `scripts/planr-host-capability-validator`
190
237
  - `docs/`
191
238
  - `docs/fixtures/mcp-contract.json`
192
239
  - `plugins/`
193
240
  - `README.md`
194
241
  - `LICENSE.md`
195
242
 
196
- `npm/native/` platform binaries exist only in the `npm-publish` CI job; the local dry-run does not include them.
243
+ `npm/native/` platform binaries exist only in the `npm-publish` CI job. The published package includes `planr`, `planr-browser-harness-adapter`, and `planr-host-capability-validator` for each platform. The local dry-run does not include these binaries.
197
244
 
198
245
  ## Install Smoke
199
246
 
@@ -1,46 +1,14 @@
1
- # Switchloom Compatibility
1
+ # Archived Switchloom v0.3.2 Compatibility Evidence
2
2
 
3
- This report records Planr-side compatibility evidence for the exact public `switchloom@0.3.2` package. It is intentionally narrow: Planr verifies the package identity, repository-local declaration boundary, and its own consumption/proof semantics. It does not turn Switchloom internals, generated semantic role names, routes, doctor output, or runtime telemetry into a future contract.
3
+ This document records a historical compatibility check performed for the external `switchloom@0.3.2` package. It is not a current Planr release gate or a promise about future Switchloom artifacts, routes, role names, host telemetry, or lifecycle behavior.
4
4
 
5
- ## Exact v0.3.2 Behavior Verified
5
+ The historical check established only that the pinned v0.3.2 package could generate repository-local `.planr/agents.toml` and `.planr/policy.toml` declarations that the Planr version at that time consumed successfully. The accompanying one-off cross-product oracle has been removed from Planr.
6
6
 
7
- - Public npm metadata for `switchloom@0.3.2` resolved from the npm registry:
8
- - `dist.integrity`: `sha512-g96AZIFKXpG1toAO+Gri1sjD8q0SxFxtRSLAcRcSVRGDCZ/dUtERepsOB+cSHHH7hUsT0jSKZYPfNqiLvfKk9Q==`
9
- - `dist.shasum`: `d7d72c74ac3ecd5a3e355edd8e297284cba04403`
10
- - `dist.tarball`: `https://registry.npmjs.org/switchloom/-/switchloom-0.3.2.tgz`
11
- - `npm pack switchloom@0.3.2 --pack-destination /private/tmp --json` returned a 9-entry package with the expected native binaries, wrapper, provenance file, README, license, and package manifest.
12
- - The packed tarball at `/private/tmp/switchloom-0.3.2.tgz` had SHA256 `0c04e94fc4372845edf395b3ea51139b8a4b46f34404940e06b3f4ec3ce22d20`.
13
- - The reviewed oracle contract expects the v0.3.2 Planr integration bundle `balanced-codex-openai@1.0.0+2.0.0`, bundle SHA256 `bf48f502080ff444ccb67bc4eeacc9391e77dbf5f0f8f277814e9abc2443e6c8`, 10 managed artifacts, 7 Codex-native roles, and 5 Planr work-type routes.
14
- - Repository docs now document the safe external operator flow with explicit `switchloom@0.3.2` commands, no normal-guidance `apply --yes`, and a caveat that the v0.3.2 tagged README preserves stale `0.3.1` examples.
15
- - The immutable live oracle used isolated source clone `/private/tmp/planr-switchloom-source.6gbzx2/source` and completed with `SWITCHLOOM_SOURCE_ROOT=/private/tmp/planr-switchloom-source.6gbzx2/source SWITCHLOOM_TARBALL=/private/tmp/switchloom-0.3.2.tgz PLANR_ORACLE_TEMP_PARENT=/private/tmp npm run verify:switchloom-cross-product`, exit 0. The live root is `/private/tmp/planr-switchloom-cross-product-Lbluca`, with oracle receipt `/private/tmp/planr-switchloom-cross-product-Lbluca/oracle-receipt.json`.
16
- - The retained replay of the same root and isolated source clone exited 0 and wrote `/private/tmp/planr-switchloom-cross-product-Lbluca/replay-receipt.json`. Replay first asserts the current source fingerprint matches the retained live receipt, then separately verifies the source remains unchanged during replay.
17
- - The live and replay receipts bind the same Switchloom source fingerprint before and after each mode: HEAD `8ff05776085d3175211e080143c513c5173abaa4`, clean status SHA256 `e3b0c442...`, inventory SHA256 `790de1be...`, file-hash SHA256 `97a26b12...`, and 303 paths. The maintainer's original sibling Switchloom worktree was not modified for this proof.
18
- - The successful live oracle proves exact package tarball SHA256 `0c04e94fc4372845edf395b3ea51139b8a4b46f34404940e06b3f4ec3ce22d20`, bundle SHA256 `bf48f502080ff444ccb67bc4eeacc9391e77dbf5f0f8f277814e9abc2443e6c8`, 7 profiles, 5 routes, 10 managed artifacts, Planr declaration consumption, Planr audit, uninstall and unrouted Planr behavior, no-auth fail-closed behavior, requested-only rejection, global sentinel preservation, and routing ownership.
19
- - The successful live oracle proves separate native maker and reviewer execution: maker `model_routing_terra_high` on `gpt-5.6-terra` with high effort, reviewer `model_routing_sol_high` on `gpt-5.6-sol` with high effort. Hidden spawn messages are intentionally opaque; the proof is exact successful parent `agent_type`, `task_name`, and `fork_turns` metadata correlated with matching direct child role rollouts, repo-local skill reads, and item-specific Planr evidence. It does not claim plaintext hidden-message recovery.
20
- - One malformed parent `spawn_agent` attempt in the retained live root was retained as a diagnostic and not counted as a successful spawn. The oracle still requires exactly two successful routed spawns and still rejects default, wrong-role, missing-role, or extra successful child execution.
21
- - A separate fresh root, `/private/tmp/planr-switchloom-cross-product-gHtZQI`, was correctly rejected: Codex claimed `spawn_agent` was unavailable and directly handled the work, producing 0 successful routed spawns. That run is negative evidence for host stochastic failure detection, not a passing compatibility run.
7
+ Planr's stable boundary remains:
22
8
 
23
- ## Stable Planr Boundary
9
+ - Planr works without Switchloom or routing declarations.
10
+ - Planr treats profiles, routes, model names, efforts, and fallbacks as provider-neutral repository data.
11
+ - Requested routing metadata is not effective execution proof.
12
+ - External tools own their install, compilation, generated host files, reload requirements, and uninstall lifecycle.
24
13
 
25
- - Planr Core is provider-neutral. It reads `.planr/agents.toml`, `.planr/policy.toml`, and route-audit evidence, but does not install, invoke, compile, apply, or uninstall Switchloom output.
26
- - `.planr/agents.toml` profiles, routes, model names, efforts, role names, and fallback chains are opaque data to Planr. Planr may place requested routing data in pick packets, but requested-only values are not effective execution proof.
27
- - `--profile` records the profile a worker reports for a run. Genuine runtime proof belongs in route-audit evidence that separates requested, host-resolved, and effective dimensions.
28
- - Missing effective host evidence remains explicitly unavailable. Planr must not infer it from generated declarations, policy files, or worker claims.
29
- - External lifecycle remains external: Switchloom owns compile, apply, generated host roles, host reload requirements, and uninstall. Planr validates its own consumption with `planr agents check` and records evidence through logs/reviews.
30
- - Planr works without routing declarations. After an external uninstall, unrouted Planr fallback behavior remains the stable Core contract.
31
-
32
- ## Not Guaranteed For Future Switchloom Work
33
-
34
- Future Switchloom work, including thread `019f8a71-5b6c-7c41-9850-7050516fcee4`, may change semantic role names, route names, doctor output, generated artifacts, runtime telemetry, and host-specific evidence shape. Planr must not contract those as stable.
35
-
36
- The stable compatibility promise is limited to Planr's boundary: consume provider-neutral declarations when present, keep requested values separate from effective evidence, reject requested-only metadata as proof, avoid owning external lifecycle, and continue operating when routing files are absent.
37
-
38
- Any future mismatch in package identity, generated artifacts, Planr declaration parsing, route-audit semantics, host evidence, source-worktree mutation, or security posture should become a new finding or fix item rather than an optimistic compatibility claim.
39
-
40
- ## Verification Notes
41
-
42
- - Rust formatting, clippy, full serial cargo tests, e2e, eval-contract, and routing-ownership tests passed when run outside the sandbox where HTTP/process tests are permitted.
43
- - Docs reference generation, typecheck, reference verification, maintenance verification, and Node 22 production build passed. Node 26 production docs builds hung in the optimized Next build phase and were terminated; the Node 22 build is the relevant repository runtime.
44
- - npm package dry-run passed using a temp npm cache because the user npm cache contains root-owned files.
45
- - Privacy checks passed. The docs app Next.js runtime was upgraded from `16.2.10` to `16.2.11` in `apps/docs/package.json` and `pnpm-lock.yaml`; the lockfile change is limited to Next core/env/SWC and mechanically recalculated peer snapshots. `npm run security:check` passed with BetterLeaks reporting no leaks and Trivy reporting 0 vulnerabilities for both `Cargo.lock` and `pnpm-lock.yaml`.
46
- - The immutable source clone proof supersedes earlier retained-replay-only evidence. Earlier concurrent external mutation and missing-receipt attempts were treated as real failures and are not counted as passing evidence.
14
+ For current Switchloom behavior, consult the external project and its versioned documentation. Any future compatibility claim requires a new bounded check owned by that integration; Planr does not retain a permanent package-specific oracle.
@@ -0,0 +1,85 @@
1
+ # Browser Harness adapter v1
2
+
3
+ Status: frozen for `planr-browser-harness-adapter` v1.
4
+
5
+ This reference defines Planr's first process adapter for the external
6
+ `browser-harness` tool. The adapter implements
7
+ `EVIDENCE_ADAPTER_PROTOCOL_V1.md`. Planr Core does not depend on this adapter.
8
+
9
+ ## Capability
10
+
11
+ The adapter supports `com.planr.web.dom_state` observations with the payload
12
+ schema `schema://com.planr.web.dom_state.v1`.
13
+
14
+ Each requirement uses these fields:
15
+
16
+ - `subject`: A CSS selector for the observed element.
17
+ - `expected.text`: The exact trimmed `textContent`, if text is required.
18
+ - `expected.visible`: The required rendered visibility, if visibility is
19
+ required.
20
+ - `state_transitions`: A shared array of at most 64 closed actions for the
21
+ batch. A `click` action has an accessibility `role` and `name`. A `fill` or
22
+ `select` action has a CSS selector `subject` and a string `value`.
23
+
24
+ All requirements in one batch must use the same transition array and the same
25
+ optional execution method. The adapter rejects arbitrary actions, arbitrary
26
+ JavaScript, mixed methods, and unsupported observation types before it starts
27
+ the browser tool.
28
+
29
+ ## Execution
30
+
31
+ An availability probe runs `browser-harness --version`. A real Evidence run
32
+ starts `browser-harness` once and sends one generated Python program over
33
+ stdin. The program completes these steps in one browser session:
34
+
35
+ 1. Open the bound HTTP or HTTPS target.
36
+ 2. Apply bounded fill and select actions through native DOM value setters and
37
+ input/change events.
38
+ 3. Find each click target in the accessibility tree by its role and name, then
39
+ click the center of its CDP box model.
40
+ 4. Read each DOM postcondition until it passes or the five-second observation
41
+ window ends.
42
+ 5. Return one structured result for the full requirement batch.
43
+ 6. Close the tab.
44
+
45
+ The generated program inserts requirement data only as JSON. A requirement
46
+ cannot add executable Python or JavaScript.
47
+
48
+ ## Result
49
+
50
+ Each `actual` object contains:
51
+
52
+ ```json
53
+ {
54
+ "schema_ref": "schema://com.planr.web.dom_state.v1",
55
+ "selector": "#status",
56
+ "text": "B",
57
+ "visible": true
58
+ }
59
+ ```
60
+
61
+ Planr Core validates this object against the registered JSON Schema. Core then
62
+ evaluates the requirement's `expected` predicate.
63
+
64
+ If every requirement selects the `browser-harness` agent skill, the adapter
65
+ also returns the matching supervised invocation record. This record is adapter
66
+ output. It becomes trusted only after Planr validates the observed process and
67
+ all sealed bindings.
68
+
69
+ ## Capture policy
70
+
71
+ The v1 success path disables Browser Harness recordings. The generated program
72
+ does not call screenshot, recording, or trace helpers. The structured DOM
73
+ observation is the retained proof for a non-visual criterion.
74
+
75
+ The adapter does not advertise a visual observation type. Planr therefore
76
+ rejects it during capability matching for a visual requirement. A recording or
77
+ screenshot cannot upgrade `com.planr.web.dom_state` into visual Evidence.
78
+
79
+ ## Canonical live fixture
80
+
81
+ `tests/fixtures/evidence/browser-harness/v1/form.html` and
82
+ `form-request.json` exercise the provider-free live boundary: one existing HTTP
83
+ target, one Browser Harness session, bounded fill/select/click actions, and one
84
+ structured DOM postcondition. The fixture requires a dedicated headless browser
85
+ endpoint and never starts a model provider.
@@ -1586,7 +1586,7 @@ Required fields:
1586
1586
  - `evidence_ref` string.
1587
1587
  - `target_kind` string enum: `run | comparison`.
1588
1588
  - `target_id` string.
1589
- - `planr_attachment_kind` string enum: `log | review | artifact`.
1589
+ - `planr_attachment_kind` string enum: `log | artifact`.
1590
1590
  - `planr_attachment_id` string.
1591
1591
  - `item_id` string.
1592
1592
  - `created_at` RFC 3339 timestamp.
@@ -0,0 +1,98 @@
1
+ # Evidence adapter protocol v1
2
+
3
+ Status: frozen for the `planr.evidence.adapter-request.v1` request and the
4
+ `planr.structured_observation_results.v2` result.
5
+
6
+ This reference defines the process protocol between Planr Core and a registered
7
+ Evidence adapter. It extends `EVIDENCE_CONTRACT_V1.md`. It does not change the
8
+ Evidence domain schema.
9
+
10
+ ## Trust ownership
11
+
12
+ Planr Core creates the adapter request, starts the registered process, and
13
+ validates the result. The adapter reports observations. It cannot assign
14
+ provenance, decide coverage, or close work.
15
+
16
+ Planr treats adapter output as untrusted input until all execution and binding
17
+ checks pass. A valid JSON result without a Planr-observed process execution
18
+ cannot create trusted Evidence.
19
+
20
+ ## Process transport
21
+
22
+ Planr starts the adapter with bounded time, stdout, and stderr limits. Planr
23
+ writes one JSON request to stdin and then closes stdin. The adapter writes one
24
+ JSON result to stdout.
25
+
26
+ An availability probe starts the same executable with closed, empty stdin. The
27
+ adapter can use that invocation to check runtime availability. A probe result
28
+ cannot satisfy an Evidence requirement.
29
+
30
+ Planr reserves the `PLANR_EVIDENCE_` environment variable namespace. An adapter
31
+ request does not use environment variables for target, environment, or contract
32
+ bindings.
33
+
34
+ ## `planr.evidence.adapter-request.v1`
35
+
36
+ The request has these fields:
37
+
38
+ - `schema_version`: `planr.evidence.adapter-request.v1`.
39
+ - `request_id`: A new Planr-assigned ID for this process execution.
40
+ - `request_digest`: The SHA-256 canonical JSON digest of the request without
41
+ `request_digest`.
42
+ - `obligation_id` and `criterion_id`: The exact Evidence obligation identity.
43
+ - `requirements`: The selected `ObservationRequirement` objects. The array
44
+ includes each subject, expected value, target, payload schema, and optional
45
+ execution method.
46
+ - `target` and `environment`: The runtime bindings selected by Planr.
47
+ - `fixture_disclosure`: The fixture and mock disclosure admitted by policy.
48
+ - `assurance_policy`: The policy that controls required capture strength.
49
+ - `result_contract`: The registered outer result schema binding.
50
+ - `execution_contract_digest`: The digest of the registered process contract.
51
+ - `execution_binding`: The sealed run-index subset and its requirement IDs.
52
+ - `retry`: The exact attempt number, maximum attempts, and predecessor IDs.
53
+
54
+ The request contains no provider-specific fields. A Browser Harness, native
55
+ browser, Playwright, mobile, desktop, game-engine, API, or CLI adapter receives
56
+ the same request shape.
57
+
58
+ ## `planr.structured_observation_results.v2`
59
+
60
+ A structured adapter result has these required fields:
61
+
62
+ - `schema_version`: `planr.structured_observation_results.v2`.
63
+ - `request_id` and `request_digest`: Exact copies from the current request.
64
+ - `target`, `observed_target`, and `environment`: The declared and observed
65
+ runtime identity.
66
+ - `execution_contract_digest`: An exact copy from the current request.
67
+ - `fixture_disclosure`: The actual fixture and mock use.
68
+ - `observations`: One result for every selected requirement and no other
69
+ results.
70
+
71
+ Each observation contains only `requirement_id`, `type`, and `actual`. The
72
+ `actual` object names its payload schema. Planr validates the object against the
73
+ registered JSON Schema and evaluates the expected predicate.
74
+
75
+ If a requirement selects an agent skill as its execution method, the result
76
+ also includes the structured `agent_skill` invocation record required by the
77
+ Evidence domain contract. The supervised adapter creates this record. Agent or
78
+ user JSON cannot submit it through another trusted path.
79
+
80
+ Adapters can include diagnostic top-level fields. Diagnostics do not affect
81
+ provenance or coverage.
82
+
83
+ ## Failure behavior
84
+
85
+ Planr rejects the result if the process fails or if any required binding does
86
+ not match. This includes a stale request ID, a stale request digest, a wrong
87
+ target, a wrong environment, a wrong execution contract, missing observations,
88
+ extra observations, a schema mismatch, and an unsatisfied expected predicate.
89
+
90
+ Planr records the failed attempt. Planr does not create a trusted passing
91
+ receipt from that result.
92
+
93
+ ## Version transition
94
+
95
+ `planr.structured_observation_results.v2` replaces
96
+ `planr.structured_observation_results.v1`. Planr does not keep a second trusted
97
+ compatibility path. Adapter manifests and policy registrations must use the v2
98
+ schema reference and artifact name.