@zhivex-ai/harness 1.3.0-rc.3 → 1.3.0

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 (157) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +12 -10
  3. package/SECURITY.md +1 -1
  4. package/SUPPORT.md +4 -4
  5. package/contracts/engine-api.json +334 -0
  6. package/contracts/public-api.json +267 -1
  7. package/contracts/stable-api-signatures.json +43 -43
  8. package/dist/acp-cli.js +54 -18
  9. package/dist/approvals/approval-history.d.ts +22 -0
  10. package/dist/approvals/explicit-review.d.ts +24 -0
  11. package/dist/approvals/host-policy-identity.d.ts +3 -0
  12. package/dist/cli/arguments.d.ts +6 -2
  13. package/dist/cli/checkpoints.d.ts +230 -0
  14. package/dist/cli/cli-profiles.d.ts +4 -2
  15. package/dist/cli/governance-report.d.ts +5 -0
  16. package/dist/cli/policy-decisions.d.ts +9 -0
  17. package/dist/cli/policy.d.ts +5 -0
  18. package/dist/cli/presentation.d.ts +3 -1
  19. package/dist/cli/terminal/terminal-ui.d.ts +4 -0
  20. package/dist/{cli-entry-xmf48p6a.js → cli-entry-1gfg3brj.js} +14921 -10692
  21. package/dist/cli-entry-bx3vjw7h.js +656 -0
  22. package/dist/{index-fvca1xea.js → cli-entry-d5788aay.js} +339 -58
  23. package/dist/{cli-qgwvtk0w.js → cli-etsmtst3.js} +918 -2222
  24. package/dist/cli.js +3 -5
  25. package/dist/client/acp-mcp-admission.d.ts +32 -0
  26. package/dist/client/acp-mcp-host.d.ts +19 -0
  27. package/dist/client/acp-mcp-session.d.ts +14 -0
  28. package/dist/client/acp-stdio.d.ts +2 -0
  29. package/dist/client/acp.d.ts +4 -1
  30. package/dist/client/adapter.d.ts +13 -1
  31. package/dist/client/json-contracts.d.ts +107 -4
  32. package/dist/client/local-service.d.ts +2 -0
  33. package/dist/client/protocol.d.ts +127 -1
  34. package/dist/client/service-events.d.ts +4 -0
  35. package/dist/compat/cli-options.d.ts +13 -1
  36. package/dist/compat/code-support.js +23 -87
  37. package/dist/{config-q32jm1e6.js → config-c002f06f.js} +1 -1
  38. package/dist/{config-6gtpxvjv.js → config-j3jga5wh.js} +3 -1
  39. package/dist/context/adaptive-compaction.d.ts +1 -0
  40. package/dist/context/compaction.d.ts +1 -1
  41. package/dist/context/request-measurements.d.ts +17 -0
  42. package/dist/context/request-projection.d.ts +10 -0
  43. package/dist/context/task-memory.d.ts +1 -0
  44. package/dist/engine/acp.d.ts +2 -0
  45. package/dist/engine/acp.js +197 -1
  46. package/dist/engine/client.js +11 -4
  47. package/dist/engine/desktop-providers-v1.d.ts +4 -0
  48. package/dist/engine/desktop-providers-v1.js +18 -0
  49. package/dist/engine/desktop-state-v1.d.ts +10 -0
  50. package/dist/engine/desktop-state-v1.js +168 -0
  51. package/dist/engine/index.d.ts +12 -0
  52. package/dist/engine/index.js +571 -71
  53. package/dist/engine/mcp-stdio-v1.d.ts +11 -0
  54. package/dist/engine/mcp-stdio-v1.js +108 -0
  55. package/dist/engine/models.d.ts +3 -0
  56. package/dist/engine/models.js +894 -0
  57. package/dist/engine/protocol.d.ts +1 -0
  58. package/dist/engine/protocol.js +24 -0
  59. package/dist/engine/service.js +12 -5
  60. package/dist/execution/acceptance-snapshot.d.ts +2 -0
  61. package/dist/execution/execution-environment.d.ts +10 -0
  62. package/dist/execution/mcp-oci-channel.d.ts +11 -0
  63. package/dist/execution/mcp-oci-server.d.ts +38 -0
  64. package/dist/execution/mcp-oci-workspace.d.ts +23 -0
  65. package/dist/execution/mcp-resource-recovery.d.ts +19 -0
  66. package/dist/execution/mcp-workspace-snapshot.d.ts +20 -0
  67. package/dist/hostile-repository-demo.js +3169 -1163
  68. package/dist/{index-f4sb0e2q.js → index-2jrdcj6b.js} +17 -2
  69. package/dist/{index-77h9qr5h.js → index-3ah1f369.js} +40 -10
  70. package/dist/{index-pgqz45fj.js → index-42gp2hy8.js} +197 -1091
  71. package/dist/{index-41fkzt91.js → index-4jw3tvy8.js} +10 -2
  72. package/dist/index-6m08wvab.js +1768 -0
  73. package/dist/index-8705zxpr.js +145 -0
  74. package/dist/{index-d0wrghff.js → index-8vm2m34s.js} +225 -1416
  75. package/dist/index-8zzhggxv.js +477 -0
  76. package/dist/index-a97bezbz.js +1073 -0
  77. package/dist/index-azmwjp95.js +1004 -0
  78. package/dist/{cli-entry-0mmeag20.js → index-gq9xagx2.js} +122 -836
  79. package/dist/index-h0mqx2ed.js +1373 -0
  80. package/dist/index-hnaxfpb5.js +5589 -0
  81. package/dist/{index-2aymdsqc.js → index-qfpz5y2v.js} +24 -0
  82. package/dist/{index-kfgt9yqq.js → index-w2sj0wkw.js} +33 -10
  83. package/dist/index-wg1sd3at.js +80 -0
  84. package/dist/index-xqxeypt5.js +888 -0
  85. package/dist/index-yb239ghk.js +961 -0
  86. package/dist/index-z0qxmkm2.js +3389 -0
  87. package/dist/index.js +85 -72
  88. package/dist/integrations/mcp-host-session.d.ts +26 -0
  89. package/dist/integrations/mcp-stdio-admission.d.ts +54 -0
  90. package/dist/integrations/mcp-stdio-client.d.ts +44 -0
  91. package/dist/integrations/mcp-stdio-framing.d.ts +18 -0
  92. package/dist/integrations/mcp-stdio-launch.d.ts +20 -0
  93. package/dist/integrations/mcp-stdio-session.d.ts +7 -0
  94. package/dist/integrations/mcp-stdio-tools.d.ts +12 -0
  95. package/dist/internal/desktop/catalog.d.ts +2 -0
  96. package/dist/internal/desktop/persistence.d.ts +2 -3
  97. package/dist/internal/desktop/providers.d.ts +1 -0
  98. package/dist/models/catalog.d.ts +2 -0
  99. package/dist/persistence/governance-context.d.ts +126 -0
  100. package/dist/persistence/governance-report.d.ts +299 -0
  101. package/dist/persistence/host-database-backup.d.ts +28 -0
  102. package/dist/persistence/mcp-execution-journal.d.ts +19 -0
  103. package/dist/persistence/mcp-reconciliation.d.ts +33 -0
  104. package/dist/persistence/mcp-resource-journal.d.ts +54 -0
  105. package/dist/persistence/workspace-checkpoints.d.ts +138 -0
  106. package/dist/providers/anthropic-continuation.d.ts +5 -0
  107. package/dist/providers/providers.d.ts +1 -1
  108. package/dist/providers/vertex-auth.d.ts +27 -0
  109. package/dist/runtime/delegation-contracts.d.ts +9 -0
  110. package/dist/runtime/delegation-correction.d.ts +9 -0
  111. package/dist/runtime/delegation-result.d.ts +73 -0
  112. package/dist/runtime/error-diagnostics.d.ts +86 -0
  113. package/dist/runtime/harness.d.ts +11 -1
  114. package/dist/runtime/policy-decisions.d.ts +66 -0
  115. package/dist/runtime/policy-inspection.d.ts +52 -0
  116. package/dist/runtime/provider-diagnostics.d.ts +1 -0
  117. package/dist/runtime/runtime-instructions.d.ts +8 -0
  118. package/dist/runtime/task-acceptance-checks.d.ts +103 -0
  119. package/dist/runtime/task-acceptance-delivery.d.ts +107 -0
  120. package/dist/runtime/task-acceptance-host.d.ts +20 -0
  121. package/dist/runtime/task-acceptance-record.d.ts +107 -0
  122. package/dist/runtime/task-acceptance-validation.d.ts +25 -0
  123. package/dist/runtime/task-acceptance.d.ts +47 -0
  124. package/dist/runtime/time-to-safe-fix.d.ts +83 -0
  125. package/dist/runtime/tool-policy-file.d.ts +23 -0
  126. package/dist/runtime/tool-policy-paths.d.ts +5 -0
  127. package/dist/runtime/tool-policy.d.ts +6 -0
  128. package/dist/service-cli.js +14 -7
  129. package/dist/{service-client-cli-gs78wrxe.js → service-client-cli-3365rfav.js} +307 -248
  130. package/dist/verify-historical-migrations.js +3134 -1129
  131. package/dist/workspace/path-policy.d.ts +4 -0
  132. package/dist/zhx.js +3 -5
  133. package/docs/ACP.md +14 -2
  134. package/docs/ANTHROPIC.md +33 -0
  135. package/docs/CLI.md +132 -0
  136. package/docs/CLIENT_PROTOCOL.md +45 -0
  137. package/docs/CODE_RELEASE.md +35 -18
  138. package/docs/ENGINE_API.md +216 -7
  139. package/docs/EXTENSIBILITY.md +46 -3
  140. package/docs/FIRST_USE.md +6 -6
  141. package/docs/LOCAL_SERVICE.md +13 -0
  142. package/docs/MCP_STDIO.md +20 -0
  143. package/docs/README.md +1 -0
  144. package/docs/STABILITY.md +4 -2
  145. package/docs/SUPPORT_MATRIX.md +1 -1
  146. package/docs/TOOL_POLICY.md +81 -0
  147. package/docs/VERTEX.md +50 -0
  148. package/docs/adr/0002-isolated-mcp-stdio.md +135 -0
  149. package/docs/fixtures/mcp-stdio-contract-v1.json +189 -0
  150. package/docs/support-matrix.json +2 -0
  151. package/evaluations/representative-assembly-matrix.json +46 -1
  152. package/evaluations/task-acceptance-routes.json +7 -0
  153. package/examples/README.md +3 -3
  154. package/package.json +43 -12
  155. package/dist/cli-entry-64pdp3k5.js +0 -17
  156. package/dist/cli-entry-7h9savv5.js +0 -375
  157. package/dist/index-5wjwe91x.js +0 -9434
@@ -0,0 +1,4 @@
1
+ /** Shared lexical exclusions for workspace access and acceptance preflight. */
2
+ export declare const HARD_IGNORES: Set<string>;
3
+ export declare const isSensitiveName: (name: string) => boolean;
4
+ export declare const isHardIgnored: (relativePath: string) => boolean;
package/dist/zhx.js CHANGED
@@ -1,10 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ HARNESS_VERSION,
3
4
  shortCliHelp
4
- } from "./cli-entry-7h9savv5.js";
5
- import {
6
- HARNESS_VERSION
7
- } from "./cli-entry-64pdp3k5.js";
5
+ } from "./cli-entry-bx3vjw7h.js";
8
6
  import {
9
7
  __require
10
8
  } from "./cli-entry-1bx83sw4.js";
@@ -18,6 +16,6 @@ if (argv.length === 1 && ["--version", "-v", "version"].includes(argv[0])) {
18
16
  process.stdout.write(`${shortCliHelp(HARNESS_VERSION)}
19
17
  `);
20
18
  } else {
21
- const { runCli } = await import("./cli-qgwvtk0w.js");
19
+ const { runCli } = await import("./cli-etsmtst3.js");
22
20
  await runCli(argv);
23
21
  }
package/docs/ACP.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  The harness provides an experimental Agent Client Protocol v1 **subset** for an editor or other local client: initialization, new sessions, text prompts, one-time permissions and cancellation. It runs over JSON-RPC 2.0, one JSON message per line on stdio.
4
4
 
5
- This is not full ACP conformance. In particular, ACP requires support for client-supplied stdio MCP servers; this adapter rejects them. Test compatibility with your editor before relying on it. The negotiation response marks the subset in `_meta.zhivex`.
5
+ This is not full ACP conformance. Client-supplied stdio MCP servers require the explicit host integration below; the default CLI rejects them. Test compatibility with your editor before relying on it. The negotiation response marks the subset in `_meta.zhivex` and advertises `clientMcp` only when a host admission provider is attached.
6
6
 
7
7
  ## Launch
8
8
 
@@ -41,7 +41,7 @@ Only one prompt executes at a time per connection. Other simultaneous prompts re
41
41
 
42
42
  - Host owns the workspace, provider, model, credentials, policies and tools. `session/new.cwd` must match the configured workspace.
43
43
  - Text prompts only; no image, audio or embedded resources.
44
- - No client-provided MCP servers, client filesystem operations or client terminals.
44
+ - Client stdio MCP only through explicit host rules and OCI admission. HTTP/SSE MCP, client filesystem operations and client terminals are unsupported.
45
45
  - No session load/resume, model switching, modes, or authentication protocol. Durable sessions remain accessible through existing harness interfaces.
46
46
  - Frames are limited to 1 MiB, prompts to 64 KiB, concurrent protocol handlers to 64 and sessions to 256 per connection. Oversized frames or handler floods terminate the connection and cancel work.
47
47
  - A transport connection should belong to a single trusted local client. This is not an unauthenticated network service.
@@ -52,4 +52,16 @@ Create the existing `createHarnessClientAdapter(harness)`, then call `createAcpC
52
52
 
53
53
  `serveAcpStdio(adapter, { workspace, input, output })` supplies framing and permission-response correlation for Node readable/writable streams.
54
54
 
55
+ ### Client MCP with host admission
56
+
57
+ The experimental `@zhivex-ai/harness/acp` export `createAcpMcpHost` composes the durable adapter and per-run isolated MCP lifecycle. Supply `harness` options with explicit tenant/user identity, `rules: AcpMcpHostRule[]`, an admission `authority`, immutable `provisionerImageId`, `hostId` and `resolveSecret`. Admission authorities come from `@zhivex-ai/harness/mcp/stdio/v1`; see [isolated MCP](MCP_STDIO.md).
58
+
59
+ Each rule matches a client's exact name, absolute command and arguments, and maps them to a host-owned OCI launch proposal. Image, executable, limits and tool allowlist belong to the host. `environmentBindings` explicitly maps client variables to admitted `ZHIVEX_MCP_*` names; their values are treated as sensitive. Configuration from the workspace cannot create these rules or grant admission.
60
+
61
+ Pass the returned `adapter`, `workspace` and `mcpSessionProvider` to `serveAcpStdio`, or to `createAcpConnection` with your transport callbacks. Always await `host.close()` in a `finally` block after transport shutdown. The provider is bound to that adapter; another adapter or a fabricated provider is rejected.
62
+
63
+ Registration is per ACP session. Before every run and approval continuation, the host snapshots the workspace, obtains fresh admission and starts the mapped servers in isolated Docker containers. Up to eight servers share the run while retaining independent receipts and tool namespaces. Tool effects still require client permission; admitting a server does not approve its tools. A partial startup failure closes previously started members. Cancellation while admission is pending prevents a late approval from launching a process.
64
+
65
+ Client descriptors live only in the host's memory and expire when it closes. This integration does not enable ACP session loading across restarts. A restarted client must create a new session. Durable effect journals and resource recovery still protect against uncertain outcomes; cancellation cannot undo effects already committed.
66
+
55
67
  Protocol references: [initialization](https://agentclientprotocol.com/protocol/v1/initialization), [session setup](https://agentclientprotocol.com/protocol/v1/session-setup), [prompt lifecycle and cancellation](https://agentclientprotocol.com/protocol/v1/prompt-turn), [permissions](https://agentclientprotocol.com/protocol/v1/tool-calls).
@@ -0,0 +1,33 @@
1
+ # Anthropic direct API (provisional)
2
+
3
+ HAR-HU-41 adds `anthropic` through `@zhivex-ai/anthropic@0.12.4`. CLI and
4
+ Desktop use the same registry and curated catalogue. Set `ANTHROPIC_API_KEY` or
5
+ use the client's secure credential setup. Diagnostics expose presence and endpoint
6
+ validity only. `ANTHROPIC_BASE_URL` is optional and must be a trusted HTTPS API base including `/v1` (default `https://api.anthropic.com/v1`).
7
+ An unset, empty or whitespace-only endpoint uses that explicit default, without
8
+ inheriting another endpoint from the host process environment. The CLI does not
9
+ send a stored key to an overridden endpoint without setup consent.
10
+ OAuth, Vertex and Bedrock are separate routes and are not enabled by this integration.
11
+
12
+ ```sh
13
+ zhx run --provider anthropic --model claude-sonnet-5 "Inspect this repository"
14
+ ```
15
+
16
+ The default is an explicit catalogue choice, not a discovery or account-access
17
+ claim. Other curated choices are `claude-haiku-4-5` and `claude-opus-5-5`; an explicit
18
+ model ID can be supplied. IDs were checked against [Anthropic's model overview](https://platform.claude.com/docs/en/models/overview)
19
+ on 2026-09-28. All entries remain unverified in Harness; limits/pricing remain
20
+ unknown until curated evidence is added. A missing/unavailable model is an error,
21
+ not an automatic fallback.
22
+
23
+ Harness reconstructs the SDK 0.12.4 thinking/signature SSE deltas into bounded signed blocks before durable history. Orphan, unsigned and oversized blocks fail closed.
24
+ The integration retains signed provider-specific continuation content, tool call IDs and
25
+ receipts, input/output usage, typed HTTP errors and abort signals. Contract tests
26
+ exercise both generation and streaming without live requests. Adding the route
27
+ with its default endpoint preserves the existing registry transport fingerprint;
28
+ changing its endpoint changes the binding and prevents stale durable resumes.
29
+
30
+ Anthropic remains **provisional** pending HAR-HU-45's installed-artifact live
31
+ certification. The [common task suite](https://github.com/Zhivex/zhivex-harness/blob/main/docs/TASK_ACCEPTANCE.md) is available for that
32
+ campaign; local mocks do not certify the provider. No new release is published by
33
+ this implementation.
package/docs/CLI.md CHANGED
@@ -663,3 +663,135 @@ Activity shows phase and total elapsed time. Preparing edits, waiting for approv
663
663
  applied file changes and verification are distinct states. `/diff` reviews workspace
664
664
  changes, including changes outside the current run; file receipts identify mutations
665
665
  recorded by this harness.
666
+ ## Trusted tool policy
667
+
668
+ For an additional host-owned tool policy, use `--tool-policy <absolute-policy.json>`
669
+ on run, chat, review or resume. The policy is experimental and must be outside the
670
+ repository with private ownership/permissions. See [tool policy semantics](TOOL_POLICY.md).
671
+ Clients using `--service` cannot supply this option; configure the service host.
672
+
673
+ ## Reviewed workspace checkpoints
674
+
675
+ Use `zhx checkpoints capture <sessionId> <turnId> <path> [paths...]` to capture
676
+ explicit files at an existing terminal conversation turn. Discover turn IDs with
677
+ `zhx sessions inspect <sessionId>`. Capture stores the current contents; it does
678
+ not reconstruct historical file versions. Checkpoints cover only the selected
679
+ existing UTF-8 text files, at most 20 files of 64 KiB each. Creation, deletion,
680
+ binary files and permission rollback are excluded. This is not a full snapshot.
681
+
682
+ Capture is opt-in at the idle boundary between turns: wait for all source runs
683
+ to terminate, select the files, capture, and only then start the next task or
684
+ external edit. Capture does not start a run or authorize changes. If capture
685
+ fails, no checkpoint was established; resolve the error before proceeding with
686
+ work that needs a recovery point. There is no automatic capture on each turn.
687
+ The stored manifest records the selected paths, digests, contents and modes;
688
+ inspection reports file sizes, coverage and unsupported current files.
689
+
690
+ ```sh
691
+ zhx checkpoints list <sessionId>
692
+ zhx checkpoints inspect <checkpointId>
693
+ zhx checkpoints prepare <checkpointId>
694
+ zhx checkpoints review <operationId>
695
+ # After reviewing the exact before/after diff:
696
+ zhx checkpoints apply <operationId> <reviewedProposalId>
697
+ ```
698
+
699
+ Preparation binds the current file digests without changing files. Apply requires
700
+ the exact proposal identifier printed in the review; `--yes` cannot replace it.
701
+ The digest is an identity check, not proof of human review. Read the diff before
702
+ invoking apply. Subsequent file or permission changes cause a conflict. Missing,
703
+ protected, binary or oversized files are shown as unavailable and are not recreated.
704
+
705
+ Apply preserves the original conversation and returns its derivative. On an
706
+ interactive terminal it opens that derivative in the console. With `--json`, it
707
+ returns a versioned document containing the derivative session; noninteractive
708
+ text output prints the command to open it later. These commands use local state
709
+ without constructing a model or requiring provider credentials. Use the same
710
+ `--workspace`, `--state-dir`, `--tenant`, `--user` and `--namespace` as the source.
711
+ They currently do not support `--service`.
712
+
713
+ After an interruption, list the source session's checkpoints and review the saved
714
+ operation. Repeating apply for a completed operation returns the existing derivative.
715
+ If its stage is `forking`, inspect the source's child conversations and reconcile
716
+ the exact child titled `restore:<operationId>` using
717
+ `zhx checkpoints recover <operationId> <existingForkSessionId>`. Recovery does not
718
+ apply files; review and apply separately. Partial filesystem changes or a conflicting
719
+ base require manual recovery and are never silently overwritten.
720
+
721
+ ### Checkpoint capacity and reviewed removal
722
+
723
+ `zhx checkpoints storage` reports the current workspace/scope policy and capacity.
724
+ The limit is 100 combined checkpoint and restore records, at most 2 MiB per
725
+ serialized record. A capture uses one slot; preparing a restore uses another.
726
+ Updating an existing restore can finish at capacity. There is no automatic
727
+ eviction: a full store rejects new records while preserving existing evidence.
728
+ Serialized bytes are logical record sizes, not SQLite file size or free disk space.
729
+
730
+ Free slots by explicitly reviewing exact IDs; no age-based or implicit selection
731
+ is performed. List a session to find its checkpoint and restore IDs. A checkpoint
732
+ referenced by any retained restore cannot be removed. Pending restore evidence
733
+ cannot be removed, even when the store is full. Completed restore records can be
734
+ selected explicitly together with their checkpoint, after all references have
735
+ been resolved.
736
+
737
+ ```sh
738
+ zhx checkpoints storage
739
+ zhx checkpoints prune-review checkpoint:<checkpointId> restore:<completedRestoreId>
740
+ # Read the records, scope and counts in the review, then reuse that exact selection:
741
+ zhx checkpoints prune-apply <reviewedPlanId> checkpoint:<checkpointId> restore:<completedRestoreId>
742
+ ```
743
+
744
+ The review writes nothing and works at capacity. Apply requires the returned
745
+ SHA-256 plan identity and checks the entire scoped inventory again in a SQLite
746
+ transaction. Any inventory change requires a new review. A failed deletion rolls
747
+ back the whole selection. Removal is permanent for those stored records; it does
748
+ not delete workspace files, conversations or the restored derivative. The plan
749
+ hash checks identity; it is not proof that a person reviewed the selection.
750
+
751
+ State export preserves retained captures and completed restore records and
752
+ refuses pending restore authority. Export/import never prune to fit capacity.
753
+ Import accepts an empty destination or an identical prior import, not a merge
754
+ with changed checkpoint history. These administrative retention commands run
755
+ locally; Desktop can continue using the same retained checkpoints afterward.
756
+
757
+ ### Inspect the configured policy
758
+
759
+ `zhx policy --json` returns the versioned `policy-inspection` document for a locally
760
+ constructed host. It accepts the host's runtime settings, including `--tool-policy`.
761
+ `zhx policy --service <credentials.json> --json` queries the existing host instead;
762
+ runtime overrides are rejected in service mode. Omit `--json` for a readable
763
+ summary. Neither form starts an agent run or authorizes a pending approval.
764
+ The local form uses normal host initialization; the service form does not create
765
+ a session. Backend and limits describe configuration, not successful OCI execution.
766
+
767
+ `run`, `resume`, and local `chat` display policy explanations on stderr in text mode.
768
+ In chat, `/approve` shows the explanation and opens complete review when the host
769
+ requires it, including after restarting a pending conversation. The run/resume JSON
770
+ final document includes `policyEvidence` scoped to the current invocation: at most
771
+ 64 events and 256 KiB, with `observed` and `truncated` indicating omitted evidence.
772
+ JSONL emits policy decisions as versioned `run-event` records in the same sequence
773
+ as other events. A service-backed run uses the same event projection and bounded
774
+ final evidence. These observations do not replace durable tool execution receipts.
775
+
776
+ ### Portable governance report (Experimental)
777
+
778
+ `zhx runs report <runId> [envelope.json] [--session <sessionId>] [--json]`
779
+ exports a bounded projection from durable runs and their journals. Default output
780
+ is Markdown; `--json` emits strict versioned `harness-governance-report` JSON.
781
+ The existing `runs export` inspection format is unchanged. The command does not
782
+ construct a provider, execute tools, resume runs, or inspect current workspace
783
+ bytes. The optional envelope file is read as bounded regular-file JSON.
784
+
785
+ Session selection verifies that the root run belongs to that session and includes
786
+ retained policy decisions. Activity replay applies the existing retention policy;
787
+ expired or truncated history is explicitly incomplete. The report excludes
788
+ prompts, arguments, outputs, free-form errors and arbitrary metadata. Identifiers
789
+ and paths become domain-separated hash references: pseudonyms, not anonymity.
790
+
791
+ Execution completion, recorded delivery and pending semantic review are separate.
792
+ Missing usage stays null; partial usage is labelled incomplete; costs are estimates,
793
+ not invoices. The exporter version is not evidence of the execution artifact.
794
+ An envelope link matches the recorded patch identifier; envelope integrity and
795
+ expiry are checked separately. Patch bytes and producer authenticity remain
796
+ unverified. No envelope v1 fields are added. Concurrent source changes and hard
797
+ capacity limits reject export; bounded tree/history truncation is reported.
@@ -85,6 +85,38 @@ or a replacement for the engine's signed approval validation.
85
85
  | run.get | projectId, sessionId, runId | run | NOT_FOUND |
86
86
  | approval.resolve | projectId, sessionId, runId, expectedRevision, idempotencyKey, decisions | run | APPROVAL_MISMATCH |
87
87
  | run.cancel | projectId, sessionId, runId, expectedRevision, idempotencyKey | run | REVISION_CONFLICT |
88
+ | checkpoint.list | projectId, sessionId | checkpoints | NOT_FOUND |
89
+ | checkpoint.inspect | projectId, sessionId, checkpointId | checkpoint | NOT_FOUND |
90
+ | checkpoint.capture | projectId, sessionId, expectedRevision, idempotencyKey, turnId, paths | checkpoint | EXECUTION_FAILED |
91
+ | restore.prepare | projectId, sessionId, checkpointId, expectedRevision, idempotencyKey, expected (path/digest map) | restore | REVISION_CONFLICT |
92
+ | restore.get | projectId, sessionId, operationId | restore | NOT_FOUND |
93
+ | restore.apply | projectId, sessionId, operationId, expectedRevision, idempotencyKey, reviewedProposalId | restore | EXECUTION_FAILED |
94
+ | restore.recoverFork | projectId, sessionId, operationId, expectedRevision, idempotencyKey, forkSessionId | restore | EXECUTION_FAILED |
95
+
96
+ Checkpoint mutations use the source session revision. Checkpoint/restore IDs must
97
+ belong to that session and the host workspace/scope. Capture requires an existing
98
+ terminal turn and explicit paths (at most twenty existing text files, 64 KiB each).
99
+ Inspection reports unavailable files and mode conflicts and explicitly excludes
100
+ creation, deletion, binary files, mode rollback and full workspace snapshots.
101
+
102
+ Prepare uses the exact digests observed during inspection and returns the prepared
103
+ operation plus a diff. Clients must show that diff and obtain explicit review before
104
+ sending its `reviewedProposalId` to apply. A digest identifies content; it is not proof
105
+ of a human decision. Hosts must enforce their UI review boundary. The Desktop generic
106
+ command IPC does not accept apply/recover requests; its dedicated review flow is required.
107
+ Local CLI checkpoint commands use the same engine API. Desktop exposes checkpoint
108
+ review through dedicated host-issued tickets; generic IPC cannot apply or reconcile
109
+ a restore. The CLI does not yet route checkpoint commands through `--service`.
110
+
111
+ Restore responses contain operation metadata and an available/unavailable preview,
112
+ without duplicating the captured contents. Successful apply includes the derivative
113
+ session to open and preserves the original. Listing includes interrupted and completed
114
+ operations. After reconnecting, query the same operation before resuming: completion
115
+ is durable and applying again returns the existing derivative. An uncertain fork must
116
+ be reconciled with its exact existing child ID via `restore.recoverFork`; this does not
117
+ apply files or authorize a subsequent restore. Stale contents, missing files, mode
118
+ changes and partial filesystem outcomes fail closed. Apply/recovery also reject source
119
+ conversations with unfinished durable runs.
88
120
 
89
121
  Session documents contain sessionId, revision, optional title and ordered runId/status
90
122
  references. Lists use the existing bounded session store (default 50; no pagination
@@ -210,3 +242,16 @@ The local-service constructor optionally accepts a trusted `approvalNow` clock.
210
242
  It is not a client command or IPC capability. Desktop expiry tests advance only
211
243
  the service clock to prove server-side rejection while the review receipt remains
212
244
  unexpired in the main process.
245
+
246
+ ### Experimental policy inspection
247
+
248
+ `policy.get` takes only `projectId` and returns `{ kind: "policy", policy }`.
249
+ The versioned policy document is the same host snapshot returned by
250
+ `inspectHarnessPolicy` from `@zhivex-ai/harness/engine`. It contains configuration,
251
+ not proof of tool or OCI execution. Clients cannot supply policy overrides in
252
+ this command. The read remains available while mutation admission is paused or
253
+ a run is active, and does not create a session, authorize an approval or execute
254
+ a tool. Rule paths and host filesystem locations are omitted.
255
+ While a host-prepared runtime is active, the query reflects that runtime. Before
256
+ preparation and after release it reflects the base host; decision events retain
257
+ the digest and backend of the runtime that evaluated them.
@@ -1,10 +1,14 @@
1
1
  # Code release procedure
2
2
 
3
- Code is released independently of Harness. The initial candidate is
4
- `@zhivex-ai/code@0.1.0-rc.1`, with the sole binary `zhivex-code`, npm tag `next`,
5
- and the exact dependency `@zhivex-ai/harness@1.3.0-rc.3`. Harness must first be
6
- published and verified through its protected release workflow. This document
7
- records preparation, not successful publication.
3
+ Code is released independently of Harness. The prepared stable release is
4
+ `@zhivex-ai/code@0.1.0`, with the sole binary `zhivex-code`, npm tag `latest`,
5
+ and the exact dependency `@zhivex-ai/harness@1.3.0`. Harness must first be
6
+ published and verified through its protected release workflow. Code RC2 is
7
+ already published on `next` and RC1 is still on `latest`; trusted
8
+ publishing succeeded in [run 36902929707](https://github.com/Zhivex/zhivex-harness/actions/runs/36902929707).
9
+ The stable release uses that existing OIDC path; no new credentials or publisher
10
+ configuration are part of preparation. This document records preparation, not
11
+ successful stable publication.
8
12
 
9
13
  ## Release preparation
10
14
 
@@ -12,19 +16,23 @@ records preparation, not successful publication.
12
16
  2. Wait for the latest `ci.yml` and `codeql.yml` **push runs on main** to succeed
13
17
  for the exact commit. Keep the Code manifest, version and engine pin unchanged
14
18
  after selecting that commit.
15
- 3. From a clean checkout of that main commit, create an annotated
16
- `code-v0.1.0-rc.1` tag and push it. Never move or overwrite release tags.
19
+ 3. Wait for Harness `1.3.0` publication and successful registry/provenance
20
+ verification as ordered in [the Harness release procedure](https://github.com/Zhivex/zhivex-harness/blob/main/docs/RELEASE.md).
21
+ From a clean checkout of that main commit, create an annotated
22
+ `code-v0.1.0` tag and push it. Never move or overwrite release tags.
17
23
  4. Dispatch `release-code.yml` **at that tag**, with input `tag` matching it and
18
- `mode=bootstrap`. Dispatching main while supplying a different tag is rejected.
24
+ `channel=latest`, `mode=oidc`, and `confirm_publication=true`. Dispatching
25
+ main while supplying a different tag is rejected.
19
26
 
20
27
  ```sh
21
- gh workflow run release-code.yml --ref code-v0.1.0-rc.1 \
22
- -f tag=code-v0.1.0-rc.1 -f mode=bootstrap -f confirm_publication=false
28
+ gh workflow run release-code.yml --ref code-v0.1.0 \
29
+ -f tag=code-v0.1.0 -f channel=latest -f mode=oidc -f confirm_publication=true
23
30
  ```
24
31
 
25
32
  The workflow validates tag identity, main ancestry, exact CI/CodeQL, Code source
26
33
  and package boundaries. It downloads the pinned Harness version from npm and
27
- verifies its integrity; missing publication or provenance stops the release.
34
+ verifies its integrity and SLSA artifact/workflow/tag/source binding; missing
35
+ publication or provenance stops the release.
28
36
  It builds Code once, inspects package contents, installs it against the actual
29
37
  registry dependency without overrides, and tests the retained Code and Harness
30
38
  artifacts with npm, pnpm, Yarn and Bun. The paired matrix uses explicit engine
@@ -36,13 +44,18 @@ inside the GitHub-hosted build job. It retains `code.tgz`, `code.sigstore.json`,
36
44
  `SHA512SUMS`, and installed acceptance in `code-release-<full-source-sha>`.
37
45
  Bootstrap mode **does not publish**. No npm token is copied into GitHub.
38
46
 
39
- ## First publication
47
+ ## Historical first publication / future package bootstrap
40
48
 
41
49
  npm requires the package to exist before configuring its trusted publisher;
42
50
  staged publishing also requires an existing package. An authenticated scope
43
51
  owner performs the first publication using the successful workflow's retained
44
52
  artifact and provenance bundle. Do not rebuild the tarball locally.
45
53
 
54
+ These bootstrap commands apply only if authenticated first publication is
55
+ explicitly authorized for a new package. They are unnecessary for the existing
56
+ Code package. Set `RELEASE_CHANNEL` from `bun run scripts/code-release.ts channel`
57
+ and keep it consistent with the artifact.
58
+
46
59
  Download the artifact from the exact successful run, then verify it in a clean
47
60
  checkout of its annotated Code tag. `CODE_EXPECTED_SHA` must be that tag's full
48
61
  commit SHA. Install npm 11.6.1 into an isolated tools directory and set
@@ -51,12 +64,12 @@ commit SHA. Install npm 11.6.1 into an isolated tools directory and set
51
64
  ```sh
52
65
  (cd release-code-artifacts && shasum -a 512 -c SHA512SUMS)
53
66
  bun run scripts/code-release.ts inspect release-code-artifacts/code.tgz
54
- CODE_EXPECTED_SHA="$(git rev-list -n 1 code-v0.1.0-rc.1)" \
67
+ CODE_EXPECTED_SHA="$(git rev-list -n 1 code-v0.1.0)" \
55
68
  node scripts/code-bootstrap-provenance.cjs verify \
56
69
  release-code-artifacts/code.tgz release-code-artifacts/code.sigstore.json
57
70
  node "$CODE_PROVENANCE_NPM_ROOT/bin/npm-cli.js" publish \
58
71
  ./release-code-artifacts/code.tgz --ignore-scripts --access public \
59
- --tag next --provenance-file ./release-code-artifacts/code.sigstore.json
72
+ --tag "$RELEASE_CHANNEL" --provenance-file ./release-code-artifacts/code.sigstore.json
60
73
  bun run scripts/code-release.ts verify release-code-artifacts/code.tgz
61
74
  ```
62
75
 
@@ -74,16 +87,20 @@ repository `zhivex-harness`, workflow filename `release-code.yml`, and environme
74
87
  `npm`. Enable the allowed action `npm publish`; the OIDC job uses direct
75
88
  publishing after GitHub approval, not `npm stage publish`. Preserve the GitHub
76
89
  environment's required human approval. Then prepare a
77
- new Code RC/version and annotated tag through the same PR and main CI process.
78
- Dispatch its tag with `mode=oidc` and `confirm_publication=true`.
90
+ new Code stable or RC version and annotated tag through the same PR and main CI process.
91
+ Dispatch its tag with the matching channel, `mode=oidc` and
92
+ `confirm_publication=true`. Stable versions require `latest` and a stable exact
93
+ Harness dependency; canonical RC versions require `next`. Version/channel drift
94
+ fails before engine downloads. An RC may pin a stable engine. Stable publication
95
+ does not upgrade beta/experimental APIs, provisional providers or Desktop alpha.
79
96
 
80
97
  All Code tags share one workflow concurrency group. Before publishing, the
81
- registry gate also rejects moving `next` back to an older RC, including when
98
+ registry gate rejects moving the selected channel back to an older release, including when
82
99
  GitHub schedules queued workflows out of order.
83
100
 
84
101
  The publish job downloads the validated artifact without rebuilding it,
85
102
  rechecks identity and digest after protected approval, and uses npm OIDC plus
86
- provenance. It verifies registry tarball bytes, the `next` distribution tag and
103
+ provenance. It verifies registry tarball bytes, the selected `latest`/`next` distribution tag and
87
104
  SLSA source/workflow identity. A successful dispatch or tag is not publication;
88
105
  only successful registry verification confirms the release. When a run has
89
106
  already published, rerun only the failed publish job to retain original bytes.