@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,135 @@
1
+ # ADR 0002: Host-admitted MCP stdio inside OCI
2
+
3
+ Status: proposed for implementation review (HAR-HU-46), 2026-09-29.
4
+ This is a design contract and acceptance fixture specification. It does not
5
+ activate stdio, change configuration schema 1, or claim isolated execution passed.
6
+
7
+ ## Evidence and compatibility baseline
8
+
9
+ - `src/integrations/mcp.ts`: configuration accepts `http`/`custom`; custom clients
10
+ require explicit host injection. Tool/resource allowlists, output bounds and
11
+ durable approvals already exist.
12
+ - `src/client/acp.ts`: client `mcpServers` must be empty. Preserve that rejection
13
+ until host admission and isolated launch are implemented together.
14
+ - `src/execution/execution-environment.ts`: OCI enforces network denial, read-only
15
+ root filesystem, unprivileged user, dropped capabilities, bounded resources,
16
+ private workspace volume and optional read-only dependencies. Its adapter has
17
+ finite `run`/`runBatch`, not an interactive stdio process lease. All MCP is
18
+ currently rejected with OCI enforcement before discovery.
19
+ - Installed `@zhivex-ai/core` 1.26.0 exposes `McpClient`, call options with abort,
20
+ timeout/idempotency key, and an HTTP transport; no executable stdio factory was
21
+ found in this dependency. The control-plane transport enum is not an executor.
22
+
23
+ MCP stdio uses UTF-8 newline-delimited JSON-RPC on stdin/stdout; stderr is a
24
+ separate diagnostic stream. Preserve message correlation and initialization.
25
+ Source: [MCP transport specification, 2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports).
26
+ The proposed initial protocol is explicitly 2025-11-25; unsupported negotiation
27
+ fails before discovery. HTTP's existing version behavior remains unchanged.
28
+
29
+ ## Boundary and authority
30
+
31
+ Choose the enforced OCI boundary, initially Docker with the existing platform
32
+ support policy. A future backend must pass the same fixtures before advertising
33
+ support. A process on the host, a filtered environment, a permission prompt or an
34
+ SDK transport alone is not this boundary. Missing Docker, attestation, resource
35
+ limits or interactive capability means rejection, never host fallback.
36
+
37
+ A client sends a *proposal*, not an executable command. Proposed fields are:
38
+ `schemaVersion: 1`, server ID, immutable image digest, absolute in-image executable,
39
+ argv array, protocol version, relative snapshot working directory, explicit tool
40
+ and resource allowlists, permissions, environment literals, secret references,
41
+ resource/deadline limits and snapshot identity. Unknown fields are rejected.
42
+ Host paths, shell command strings, PATH search, package installation at launch,
43
+ mutable image tags and interpreter flags that load host configuration are denied.
44
+ These are proposed host API fields, not accepted workspace configuration today.
45
+
46
+ The host validates and presents executable/argv, image, filesystem scope, allowed
47
+ tools, environment names, secret reference names and limits for explicit launch
48
+ admission. No image pull, subprocess, initialize or discovery occurs merely from
49
+ parsing configuration, opening a client session or importing a module. The host
50
+ may admit an already provisioned image only; image provisioning is a separate
51
+ host operation. The host issues an opaque single-use admission receipt bound to
52
+ principal, tenant/scope, workspace snapshot digest, session, full normalized
53
+ proposal digest, image identity, policy version and expiry. Client booleans,
54
+ model text and tool annotations cannot manufacture that receipt.
55
+
56
+ Admission checks are repeated immediately before launch. Configuration changes,
57
+ workspace/scope changes, expired receipts and reuse invalidate it. Raw receipt
58
+ capabilities are not serialized to the client or exported in run histories.
59
+ Launch admission grants no approval to call mutating tools. Existing per-call
60
+ approval remains required; server metadata cannot expand admitted permissions.
61
+
62
+ ## Execution policy v1
63
+
64
+ | Surface | Required enforcement |
65
+ | --- | --- |
66
+ | Startup | Acquire isolated execution lease and private snapshot, attest image/policy, consume admission once, then start exact executable/argv without shell. Failure removes partial resources. |
67
+ | Environment | Start empty except host-fixed HOME/TMPDIR inside bounded tmpfs and minimal runtime locale. Admit explicitly named literal values. Reject injection/control variables including PATH, NODE_OPTIONS, loader paths and runtime preload flags. Never inherit process.env. |
68
+ | Secrets | None by default. Host resolves admitted opaque references immediately before launch and injects only named values in the isolated process environment. Missing/expired references fail closed. No secret values in argv, proposal, fingerprints, receipts, logs or fixtures. Redact stdout-derived diagnostics as well as stderr. The admitted server can read its granted secrets; isolation does not make it trustworthy. |
69
+ | Network | Deny all egress/ingress, DNS and host/metadata access using OCI network none. No domain allowlist or proxy exception in v1. A server requiring network is unsupported. |
70
+ | Filesystem | Read-only image root; private snapshot at /workspace; bounded tmpfs; optional declared read-only dependency tree. No host home, repository bind mount, credential directory, Docker socket or arbitrary volume. Read-only permission mounts workspace read-only. Write permission affects only private snapshot. |
71
+ | Publication | Isolated writes never mutate the host tree. Capture reviewed patch, validate preimages/path rules and obtain separate durable host approval before importing, using the existing execution delivery contract. |
72
+ | Resource limits | Host hard maxima intersect requested limits: memory, CPU, pids, workspace/write bytes, tmpfs, output and elapsed runtime. No client may increase a host limit. Reject unsupported enforcement. |
73
+ | Lifetime | One isolated server per admitted session; no cross-tenant reuse. No auto-restart or adoption after host restart. Reconnect requires fresh launch admission. |
74
+
75
+ The reusable execution policy remains authoritative; this proposal cannot weaken
76
+ its limits. SDK `McpClient` describes messages, not confinement. Bridge the admitted
77
+ process streams into an internal client implementing listTools/callTool and the
78
+ resource subset already allowed by Harness. Keep HTTP and existing injected
79
+ custom clients unchanged in non-OCI runs. Do not reinterpret arbitrary injected
80
+ clients as isolated. Preserve allowlists, bounded pagination, schema validation,
81
+ redaction and approval wrappers above the bridge.
82
+
83
+ ## Lifecycle, framing and uncertain effects
84
+
85
+ Proposed lifecycle: proposed -> admitted -> starting -> initializing -> ready ->
86
+ closing -> closed, with failed terminal outcome at any nonterminal stage. Bind all
87
+ requests and audit events to admission and process-lease identities. Suggested
88
+ host defaults: start 10 s, initialize 10 s, existing list 5 s/call 30 s bounds,
89
+ maximum session 10 min, graceful stop 2 s followed by forced boundary removal.
90
+ These are finite absolute deadlines; receiving partial output cannot extend them.
91
+ Use the smaller host/request deadline and propagate AbortSignal. Limit in-flight
92
+ requests to one initially, 1 MiB UTF-8 frame and 64 KiB retained redacted stderr;
93
+ retain existing lower per-tool output limits. Apply backpressure with bounded
94
+ queues. Oversized/incomplete frames, invalid UTF-8/JSON, duplicate or unknown
95
+ response IDs and stdout log contamination close the transport with a typed error.
96
+ Server-initiated execution/sampling/elicitation requests are unsupported and must
97
+ not invoke host capabilities. Notifications cannot grant permissions.
98
+
99
+ On cancellation or timeout: stop new calls, best-effort protocol cancellation,
100
+ close stdin, terminate the isolated process tree, force-remove its boundary after
101
+ grace, reap handles and release leases. EOF/exit fails outstanding calls. A crash
102
+ or timeout after dispatch leaves a possibly effectful call `outcome_unknown` in
103
+ host audit until reconciled. Reconciliation requires confirmed resource cleanup, an explicit host-authorized decision bound to the journal revision and an evidence digest. Preserve the prior uncertain status and keep the original call key unreplayable; a future call requires a new admission and approval. Never replay it automatically, even with an SDK
104
+ idempotency key. Read-only calls are not automatically retried in v1 either.
105
+ Do not report cleanup success until the runtime confirms resources are gone;
106
+ otherwise retain a cleanup-required record for scoped orphan reconciliation.
107
+
108
+ The current finite OCI adapter cannot fulfill this contract unchanged. A future
109
+ optional interactive capability must expose attested launch, bounded stdin writes,
110
+ stdout/stderr reads, exit observation and idempotent close; acquisition owns the
111
+ lease. Missing capability fails before spawn. Do not implement stdio by calling
112
+ host spawn from `createHarnessMcpTools` or by buffering a never-ending `run`.
113
+
114
+ ## Threats and review gates
115
+
116
+ | Threat | Control and evidence required |
117
+ | --- | --- |
118
+ | Client commands run during session creation | Reject before admission; zero host/container processes and zero discovery calls. |
119
+ | TOCTOU, swapped image/argv or replayed admission | Digest/identity recheck at launch; receipt scope/expiry/single-use tests. |
120
+ | Secret/environment exfiltration | Empty inherited environment, restricted references, network denial, redacted audit; canary checks inside/outside boundary. |
121
+ | Filesystem escape and host mutation | No bind mounts, no-follow snapshot/import rules, resource limits and reviewed publication; symlink/traversal fixtures. |
122
+ | Tool metadata or prompt injection escalates authority | Independent host policy and per-call approvals; untrusted descriptions/results remain data. |
123
+ | Hung/forking/noisy process | Absolute deadlines, frame/queue/stderr/resource bounds and whole-boundary cleanup. |
124
+ | Cross-scope reuse or uncertain effect replay | Scoped leases/admission; persisted unknown outcome; no reconnect/restart replay. |
125
+ | False isolation claim | Real OCI and installed-package gates, not mocks alone; unsupported backend denied. |
126
+
127
+ The [fixture catalogue](../fixtures/mcp-stdio-contract-v1.json) specifies positive
128
+ and negative acceptance before implementation. Every case is currently
129
+ `specified_not_executed`, not a passed test. Implementation must supply observations
130
+ for launch counts, process identity, network probes, host/snapshot digests, resource
131
+ cleanup and sanitized errors as specified. A fake runtime may prove host admission
132
+ logic; only real OCI can establish filesystem/network/process enforcement.
133
+ Existing MCP/ACP regression tests protect today's rejection boundary. Delivery
134
+ requires Node and Bun installed consumers plus real supported OCI execution,
135
+ including crash/cancel/orphan fixtures, before changing support/ACP capabilities.
@@ -0,0 +1,189 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "status": "design_only",
4
+ "cases": [
5
+ {
6
+ "id": "admitted_read",
7
+ "kind": "positive",
8
+ "given": "Host admits immutable image and read-only snapshot",
9
+ "when": "initialize, list and call allowed read tool",
10
+ "observationsRequired": [
11
+ "exact argv launched only inside OCI",
12
+ "bounded result returned",
13
+ "host digest unchanged",
14
+ "cleanup confirmed"
15
+ ],
16
+ "status": "specified_not_executed"
17
+ },
18
+ {
19
+ "id": "admitted_write",
20
+ "kind": "positive",
21
+ "given": "Launch and mutating call approved separately",
22
+ "when": "write private snapshot and request delivery",
23
+ "observationsRequired": [
24
+ "no host change before import approval",
25
+ "reviewed preimage import applies once"
26
+ ],
27
+ "status": "specified_not_executed"
28
+ },
29
+ {
30
+ "id": "secret_reference",
31
+ "kind": "positive",
32
+ "given": "Host admits one secret reference",
33
+ "when": "read allowed env name and emit canary diagnostics",
34
+ "observationsRequired": [
35
+ "only named secret inside process",
36
+ "canary absent from audit and exports"
37
+ ],
38
+ "status": "specified_not_executed"
39
+ },
40
+ {
41
+ "id": "unadmitted_client",
42
+ "kind": "negative",
43
+ "given": "ACP/client supplies executable without host receipt",
44
+ "when": "open session and request discovery",
45
+ "observationsRequired": [
46
+ "no image pull",
47
+ "zero process starts",
48
+ "zero discovery calls"
49
+ ],
50
+ "status": "specified_not_executed"
51
+ },
52
+ {
53
+ "id": "receipt_drift",
54
+ "kind": "negative",
55
+ "given": "Valid receipt then image, argv, snapshot or scope changes",
56
+ "when": "attempt launch for each independent mutation",
57
+ "observationsRequired": [
58
+ "rejected before process start"
59
+ ],
60
+ "status": "specified_not_executed"
61
+ },
62
+ {
63
+ "id": "receipt_replay",
64
+ "kind": "negative",
65
+ "given": "Expired or consumed receipt",
66
+ "when": "attempt launch",
67
+ "observationsRequired": [
68
+ "rejected before process start"
69
+ ],
70
+ "status": "specified_not_executed"
71
+ },
72
+ {
73
+ "id": "missing_backend",
74
+ "kind": "negative",
75
+ "given": "No interactive OCI capability or unavailable runtime",
76
+ "when": "admit request",
77
+ "observationsRequired": [
78
+ "unsupported error",
79
+ "no host fallback"
80
+ ],
81
+ "status": "specified_not_executed"
82
+ },
83
+ {
84
+ "id": "environment_injection",
85
+ "kind": "negative",
86
+ "given": "Ambient credential canary and requested NODE_OPTIONS",
87
+ "when": "attempt admission",
88
+ "observationsRequired": [
89
+ "control variable rejected",
90
+ "ambient env never inherited"
91
+ ],
92
+ "status": "specified_not_executed"
93
+ },
94
+ {
95
+ "id": "network_escape",
96
+ "kind": "negative",
97
+ "given": "Admitted malicious process",
98
+ "when": "probe DNS, public IP and metadata IP",
99
+ "observationsRequired": [
100
+ "all probes denied by real OCI",
101
+ "no host proxy"
102
+ ],
103
+ "status": "specified_not_executed"
104
+ },
105
+ {
106
+ "id": "filesystem_escape",
107
+ "kind": "negative",
108
+ "given": "Snapshot contains symlink and traversal attempts",
109
+ "when": "read host home and write outside workspace",
110
+ "observationsRequired": [
111
+ "host files inaccessible",
112
+ "host digest unchanged",
113
+ "unsafe import denied"
114
+ ],
115
+ "status": "specified_not_executed"
116
+ },
117
+ {
118
+ "id": "permission_escalation",
119
+ "kind": "negative",
120
+ "given": "Read tool annotation claims write is safe",
121
+ "when": "call undeclared or mutating tool",
122
+ "observationsRequired": [
123
+ "host permissions prevail",
124
+ "no mutation without approval"
125
+ ],
126
+ "status": "specified_not_executed"
127
+ },
128
+ {
129
+ "id": "protocol_abuse",
130
+ "kind": "negative",
131
+ "given": "Noisy or hostile stdio server",
132
+ "when": "send oversized/incomplete frames, malformed UTF8, unknown/duplicate IDs and server requests",
133
+ "observationsRequired": [
134
+ "bounded buffers",
135
+ "typed error or unsupported-method response",
136
+ "no host execution"
137
+ ],
138
+ "status": "specified_not_executed"
139
+ },
140
+ {
141
+ "id": "hung_call",
142
+ "kind": "negative",
143
+ "given": "Server receives an approved effectful call then hangs",
144
+ "when": "expire absolute deadline",
145
+ "observationsRequired": [
146
+ "unknown outcome retained",
147
+ "no automatic replay",
148
+ "process tree terminated"
149
+ ],
150
+ "status": "specified_not_executed"
151
+ },
152
+ {
153
+ "id": "cancel_tree",
154
+ "kind": "negative",
155
+ "given": "Server forks children and ignores graceful termination",
156
+ "when": "cancel run",
157
+ "observationsRequired": [
158
+ "admission closed",
159
+ "forced removal after grace",
160
+ "no leaked descendants or leases"
161
+ ],
162
+ "status": "specified_not_executed"
163
+ },
164
+ {
165
+ "id": "crash_restart",
166
+ "kind": "negative",
167
+ "given": "Host or server crashes after dispatch",
168
+ "when": "reopen host session",
169
+ "observationsRequired": [
170
+ "no replay",
171
+ "fresh admission required",
172
+ "orphan cleanup scoped to owner"
173
+ ],
174
+ "status": "specified_not_executed"
175
+ },
176
+ {
177
+ "id": "cleanup_failure",
178
+ "kind": "negative",
179
+ "given": "Runtime cannot confirm boundary removal",
180
+ "when": "close session",
181
+ "observationsRequired": [
182
+ "cleanup-required retained",
183
+ "no false closed-success",
184
+ "bounded reconciliation"
185
+ ],
186
+ "status": "specified_not_executed"
187
+ }
188
+ ]
189
+ }
@@ -24,6 +24,8 @@
24
24
  { "id": "provider-meta", "dimension": "provider", "target": "Meta muse-spark-1.2", "level": "supported", "evidence": ["docs/LIVE_CERTIFICATION.md", "release-status.json"] },
25
25
  { "id": "provider-qwen", "dimension": "provider", "target": "Qwen qwen3.8-max", "level": "supported", "evidence": ["docs/LIVE_CERTIFICATION.md", "release-status.json"] },
26
26
  { "id": "provider-openai", "dimension": "provider", "target": "OpenAI gpt-5.6-luna", "level": "supported", "evidence": ["docs/LIVE_CERTIFICATION.md", "release-status.json"] },
27
+ { "id": "provider-vertex", "dimension": "provider", "target": "Google Cloud Vertex AI (ADC)", "level": "provisional", "evidence": ["docs/VERTEX.md", "tests/vertex-provider.test.ts", "tests/vertex-auth.test.ts"] },
28
+ { "id": "provider-anthropic", "dimension": "provider", "target": "Anthropic direct API / claude-sonnet-5", "level": "provisional", "evidence": ["docs/ANTHROPIC.md"] },
27
29
  { "id": "provider-gemini", "dimension": "provider", "target": "Gemini gemini-3.6-flash / 3.7-flash", "level": "provisional", "evidence": ["docs/LIVE_CERTIFICATION.md"] }
28
30
  ]
29
31
  }
@@ -48,7 +48,12 @@
48
48
  "v1.2.0",
49
49
  "v1.3.0-rc.1",
50
50
  "v1.3.0-rc.2",
51
- "v1.3.0-rc.3"
51
+ "v1.3.0-rc.3",
52
+ "v1.3.0-rc.4",
53
+ "v1.3.0-rc.5",
54
+ "v1.3.0-rc.6",
55
+ "v1.3.0-rc.7",
56
+ "v1.3.0"
52
57
  ],
53
58
  "expectedModels": [
54
59
  {
@@ -426,6 +431,46 @@
426
431
  "qwen": "qwen3.8-flash",
427
432
  "openai": "gpt-6-luna"
428
433
  }
434
+ },
435
+ {
436
+ "releaseTag": "v1.3.0-rc.4",
437
+ "models": {
438
+ "meta": "muse-spark-1.3",
439
+ "qwen": "qwen3.8-max",
440
+ "openai": "gpt-6-luna"
441
+ }
442
+ },
443
+ {
444
+ "releaseTag": "v1.3.0-rc.5",
445
+ "models": {
446
+ "meta": "muse-spark-1.3-contributor",
447
+ "qwen": "qwen3.8-flash",
448
+ "openai": "gpt-6-luna"
449
+ }
450
+ },
451
+ {
452
+ "releaseTag": "v1.3.0-rc.6",
453
+ "models": {
454
+ "meta": "muse-spark-1.3-contributor",
455
+ "qwen": "qwen3.8-flash",
456
+ "openai": "gpt-6-luna"
457
+ }
458
+ },
459
+ {
460
+ "releaseTag": "v1.3.0-rc.7",
461
+ "models": {
462
+ "meta": "muse-spark-1.3-contributor",
463
+ "qwen": "qwen3.8-flash",
464
+ "openai": "gpt-6-luna"
465
+ }
466
+ },
467
+ {
468
+ "releaseTag": "v1.3.0",
469
+ "models": {
470
+ "meta": "muse-spark-1.3-contributor",
471
+ "qwen": "qwen3.8-flash",
472
+ "openai": "gpt-6-luna"
473
+ }
429
474
  }
430
475
  ],
431
476
  "expectedCases": [
@@ -0,0 +1,7 @@
1
+ [
2
+ { "provider": "openai", "model": "gpt-6-luna", "route": "direct-api" },
3
+ { "provider": "qwen", "model": "qwen3.8-flash", "route": "direct-api" },
4
+ { "provider": "meta", "model": "muse-spark-1.3-contributor", "route": "direct-api" },
5
+ { "provider": "gemini", "model": "gemini-3.6-flash", "route": "direct-api" },
6
+ { "provider": "anthropic", "model": "claude-sonnet-5", "route": "direct-api" }
7
+ ]
@@ -2,19 +2,19 @@
2
2
 
3
3
  ## Isolated Bun installation
4
4
 
5
- Requirements: Bun 1.4.0+, Node.js 22.13.0+, and Git on macOS or Linux. After protected 1.2.0 publication, this installs the stable artifact in a temporary consumer, without building the source checkout or changing global tools:
5
+ Requirements: Bun 1.4.0+, Node.js 22.13.0+, and Git on macOS or Linux. After protected 1.3.0 publication, this installs the stable artifact in a temporary consumer, without building the source checkout or changing global tools:
6
6
 
7
7
  ```bash
8
8
  harness_demo_dir=$(mktemp -d)
9
9
  cd "$harness_demo_dir"
10
10
  printf '{"name":"harness-first-run","private":true}\n' > package.json
11
- bun add --exact --ignore-scripts @zhivex-ai/harness@1.3.0-rc.3
11
+ bun add --exact --ignore-scripts @zhivex-ai/harness@1.3.0
12
12
  ./node_modules/.bin/zhx --version
13
13
  ./node_modules/.bin/zhx --help
14
14
  ./node_modules/.bin/zhx doctor --provider openai --json
15
15
  ```
16
16
 
17
- Version must print `1.2.0`; help lists commands. Doctor does not contact a provider. Without `OPENAI_API_KEY`, it reports the missing credential and exits with code `3`; inspect the JSON checks before proceeding. A directory without Git initialization can also produce a diagnostic warning. No paid model call is required for these checks. Both `zhx` and `zhivex-harness` are installed aliases; Bun manages installation, and their shebang runs Node.
17
+ Version must print `1.3.0`; help lists commands. Doctor does not contact a provider. Without `OPENAI_API_KEY`, it reports the missing credential and exits with code `3`; inspect the JSON checks before proceeding. A directory without Git initialization can also produce a diagnostic warning. No paid model call is required for these checks. Both `zhx` and `zhivex-harness` are installed aliases; Bun manages installation, and their shebang runs Node.
18
18
 
19
19
  To continue in your actual project, use the [global installation and credential setup](../README.md#installation), then `zhx init --profile daily --provider openai` and `zhx doctor --profile daily`. Real tasks require the selected provider credential in the process environment. Profiles store provider/model choices, never credentials. See [CLI](../docs/CLI.md) and [support](../SUPPORT.md).
20
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhivex-ai/harness",
3
- "version": "1.3.0-rc.3",
3
+ "version": "1.3.0",
4
4
  "description": "Governed, provider-portable runtime for coding agents with durable approvals and isolated repository execution.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -69,6 +69,22 @@
69
69
  "./code-support": {
70
70
  "types": "./dist/compat/code-support.d.ts",
71
71
  "import": "./dist/compat/code-support.js"
72
+ },
73
+ "./models": {
74
+ "types": "./dist/engine/models.d.ts",
75
+ "import": "./dist/engine/models.js"
76
+ },
77
+ "./desktop/v1/state": {
78
+ "types": "./dist/engine/desktop-state-v1.d.ts",
79
+ "import": "./dist/engine/desktop-state-v1.js"
80
+ },
81
+ "./desktop/v1/providers": {
82
+ "types": "./dist/engine/desktop-providers-v1.d.ts",
83
+ "import": "./dist/engine/desktop-providers-v1.js"
84
+ },
85
+ "./mcp/stdio/v1": {
86
+ "types": "./dist/engine/mcp-stdio-v1.d.ts",
87
+ "import": "./dist/engine/mcp-stdio-v1.js"
72
88
  }
73
89
  },
74
90
  "files": [
@@ -113,14 +129,20 @@
113
129
  "benchmarks/README.md",
114
130
  "docs/ACP.md",
115
131
  "docs/WORKSPACE_CHECKPOINTS.md",
116
- "docs/ENGINE_API.md"
132
+ "docs/ENGINE_API.md",
133
+ "docs/ANTHROPIC.md",
134
+ "docs/MCP_STDIO.md",
135
+ "docs/adr/0002-isolated-mcp-stdio.md",
136
+ "docs/VERTEX.md",
137
+ "docs/TOOL_POLICY.md",
138
+ "docs/fixtures/mcp-stdio-contract-v1.json"
117
139
  ],
118
140
  "scripts": {
119
141
  "models:check": "bun run scripts/validate-model-catalog.ts",
120
142
  "models:import": "bun run scripts/generate-console-models.ts",
121
143
  "dev": "bun run build && node --env-file-if-exists=.env dist/cli.js",
122
144
  "start": "node dist/cli.js",
123
- "build": "bun run scripts/clean-dist.ts && bun build ./src/index.ts ./src/service-cli.ts ./src/acp-cli.ts ./src/engine/index.ts ./src/engine/protocol.ts ./src/engine/client.ts ./src/engine/service.ts ./src/engine/acp.ts ./src/compat/code-support.ts --root ./src --outdir ./dist --target node --packages external --splitting && bun build ./src/engine/protocol.ts --outdir ./dist/engine --target browser --packages external && bun build ./src/cli-entry.ts --outdir ./dist --target node --packages external --splitting && mv ./dist/cli-entry.js ./dist/cli.js && cp ./dist/cli.js ./dist/zhx.js && bun build ./scripts/verify-historical-migrations.ts --outfile ./dist/verify-historical-migrations.js --target node --packages external && bun build ./scripts/hostile-repository-demo.ts --outfile ./dist/hostile-repository-demo.js --target node --packages external && tsc --emitDeclarationOnly",
145
+ "build": "bun run scripts/clean-dist.ts && bun build ./src/index.ts ./src/service-cli.ts ./src/acp-cli.ts ./src/engine/index.ts ./src/engine/protocol.ts ./src/engine/client.ts ./src/engine/service.ts ./src/engine/acp.ts ./src/engine/models.ts ./src/engine/desktop-state-v1.ts ./src/engine/desktop-providers-v1.ts ./src/compat/code-support.ts ./src/engine/mcp-stdio-v1.ts --root ./src --outdir ./dist --target node --packages external --splitting && bun build ./src/engine/protocol.ts ./src/engine/models.ts --outdir ./dist/engine --target browser --packages external && bun build ./src/cli-entry.ts --outdir ./dist --target node --packages external --splitting && mv ./dist/cli-entry.js ./dist/cli.js && cp ./dist/cli.js ./dist/zhx.js && bun build ./scripts/verify-historical-migrations.ts --outfile ./dist/verify-historical-migrations.js --target node --packages external && bun build ./scripts/hostile-repository-demo.ts --outfile ./dist/hostile-repository-demo.js --target node --packages external && tsc --emitDeclarationOnly",
124
146
  "prepack": "bun run build",
125
147
  "architecture:check": "bun run scripts/check-architecture.ts",
126
148
  "docs:check": "bun run scripts/check-docs.ts",
@@ -173,25 +195,34 @@
173
195
  "build:code": "bun run --cwd packages/code build",
174
196
  "test:code": "bun run --cwd packages/code test",
175
197
  "smoke:engine-code": "bun run scripts/smoke-engine-code.ts",
198
+ "smoke:state-upgrade": "bun run scripts/smoke-state-upgrade.ts",
199
+ "smoke:global-code": "node scripts/smoke-global-code.mjs",
176
200
  "dev:code": "bun run build && bun run packages/code/scripts/link-local-engine.ts && bun run build:code",
177
- "typecheck:code": "bun run --cwd packages/code typecheck"
201
+ "typecheck:code": "bun run --cwd packages/code typecheck",
202
+ "evaluate:tasks": "bun run scripts/task-acceptance.ts",
203
+ "prepare:desktop": "bun run build && bun pm pack --ignore-scripts --quiet --filename desktop/.harness-candidate.tgz && bun run desktop/scripts/prepare-harness.ts desktop/.harness-candidate.tgz",
204
+ "smoke:mcp:installed": "bun run build && bun scripts/mcp-installed-smoke.ts"
178
205
  },
179
206
  "dependencies": {
180
- "@zhivex-ai/agents": "1.10.1",
181
- "@zhivex-ai/core": "1.26.0",
182
- "@zhivex-ai/gemini": "0.12.3",
207
+ "@zhivex-ai/agents": "1.10.2",
208
+ "@zhivex-ai/anthropic": "0.13.1",
209
+ "@zhivex-ai/core": "1.28.0",
210
+ "@zhivex-ai/gemini": "0.13.0",
183
211
  "@zhivex-ai/meta": "0.2.8",
184
- "@zhivex-ai/openai": "0.13.6",
185
- "@zhivex-ai/qwen": "0.16.2",
212
+ "@zhivex-ai/openai": "0.13.7",
213
+ "@zhivex-ai/qwen": "0.16.3",
214
+ "@zhivex-ai/vertex": "1.2.2",
215
+ "google-auth-library": "11.1.0",
186
216
  "zod": "4.6.5"
187
217
  },
188
218
  "overrides": {
189
- "@zhivex-ai/core": "1.26.0"
219
+ "@zhivex-ai/core": "1.28.0"
190
220
  },
191
221
  "devDependencies": {
192
- "@modelcontextprotocol/server": "2.0.0",
222
+ "@agentclientprotocol/sdk": "1.5.1",
223
+ "@modelcontextprotocol/server": "2.2.0",
193
224
  "@types/bun": "1.4.2",
194
- "@types/node": "^26.6.2",
225
+ "@types/node": "^26.6.3",
195
226
  "typescript": "7.0.2",
196
227
  "typescript-compiler-api": "npm:typescript@6.0.3"
197
228
  },
@@ -1,17 +0,0 @@
1
- // src/version.ts
2
- import { createRequire } from "node:module";
3
- var packageMetadata = createRequire(import.meta.url)("../package.json");
4
- if (typeof packageMetadata.version !== "string" || packageMetadata.version.length === 0) {
5
- throw new Error("package.json must contain a non-empty version.");
6
- }
7
- if (typeof packageMetadata.engines?.node !== "string" || packageMetadata.engines.node.length === 0) {
8
- throw new Error("package.json must contain a non-empty engines.node requirement.");
9
- }
10
- if (typeof packageMetadata.engines?.bun !== "string" || packageMetadata.engines.bun.length === 0) {
11
- throw new Error("package.json must contain a non-empty engines.bun requirement.");
12
- }
13
- var HARNESS_VERSION = packageMetadata.version;
14
- var NODE_ENGINE_RANGE = packageMetadata.engines.node;
15
- var BUN_ENGINE_RANGE = packageMetadata.engines.bun;
16
-
17
- export { HARNESS_VERSION, NODE_ENGINE_RANGE, BUN_ENGINE_RANGE };