@zhivex-ai/harness 0.7.0 → 0.9.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.
- package/CHANGELOG.md +45 -0
- package/README.md +31 -7
- package/ROADMAP.md +54 -9
- package/SECURITY.md +7 -1
- package/SUPPORT.md +2 -2
- package/dist/change-envelope.d.ts +271 -0
- package/dist/cli-stream.d.ts +14 -14
- package/dist/cli.d.ts +7 -1
- package/dist/cli.js +1457 -164
- package/dist/config.d.ts +1 -1
- package/dist/execution-environment.d.ts +49 -3
- package/dist/harness.d.ts +16 -1
- package/dist/hostile-repository-demo.js +812 -160
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1367 -188
- package/dist/workspace.d.ts +53 -0
- package/dist/zhx.js +1457 -164
- package/docs/CHANGE_ENVELOPES.md +116 -0
- package/docs/CLI.md +14 -4
- package/docs/DURABLE_OPERATIONS.md +14 -2
- package/docs/EXECUTION_ENVIRONMENTS.md +10 -4
- package/docs/EXTENSIBILITY.md +7 -3
- package/docs/LIVE_CERTIFICATION.md +17 -1
- package/docs/RELEASE.md +4 -4
- package/docs/REPOSITORY_EDITING.md +4 -0
- package/examples/change-envelope-input.json +26 -0
- package/examples/change.patch +6 -0
- package/package.json +14 -8
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Change envelopes
|
|
2
|
+
|
|
3
|
+
Zhivex Harness `0.9.x` adds `ChangeEnvelope v1`: a content-addressed change-admission document that can be produced by any coding agent and verified offline before another system accepts its patch artifact. It is a portable evidence contract, not a new patch format and not a replacement for the harness approval/import boundary.
|
|
4
|
+
|
|
5
|
+
## What it proves
|
|
6
|
+
|
|
7
|
+
An envelope binds these values into one canonical SHA-256 identifier:
|
|
8
|
+
|
|
9
|
+
- the logical workspace and exact source-tree digests supplied by the producer;
|
|
10
|
+
- an artifact identifier and the SHA-256 digest of the exact patch bytes;
|
|
11
|
+
- harness, policy, and execution-environment fingerprints;
|
|
12
|
+
- structured check status, timing, exit code, and optional digests of redacted output or the check runner;
|
|
13
|
+
- optional expiry, approval references/scopes, and external-attestation references.
|
|
14
|
+
|
|
15
|
+
Verification checks the strict schema, canonical envelope and evidence digests, rejects a future creation time, enforces expiry, exact patch bytes, and any caller-supplied preconditions. A check cannot complete after the envelope is created. Raw command output, prompts, approval reasoning, and credentials are intentionally not representable.
|
|
16
|
+
|
|
17
|
+
## Create and verify
|
|
18
|
+
|
|
19
|
+
The CLI is provider-free and performs no network requests. `create` reads the exact patch bytes, computes `patch.patchDigest`, rejects a conflicting declared digest, and writes canonical JSON to stdout:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
zhx changes create examples/change-envelope-input.json \
|
|
23
|
+
--patch examples/change.patch > change-envelope.json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Verify the envelope against those same bytes:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
zhx changes verify change-envelope.json \
|
|
30
|
+
--patch examples/change.patch
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Verification returns a `change-envelope-verification` JSON document. Exit `0` means every integrity, expiration, and supplied-precondition check passed; exit `1` means the document is well-formed enough to report but is not admissible. Invalid CLI syntax or an unreadable/non-JSON artifact returns exit `2`.
|
|
34
|
+
|
|
35
|
+
For deterministic replay, `--now <ISO-8601>` selects the verification instant. Production admission should normally omit it and use the current clock.
|
|
36
|
+
|
|
37
|
+
## Input contract
|
|
38
|
+
|
|
39
|
+
The creation input is strict JSON:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"createdAt": "2026-08-20T12:00:00.000Z",
|
|
44
|
+
"expiresAt": "2026-08-21T12:00:00.000Z",
|
|
45
|
+
"base": {
|
|
46
|
+
"workspaceDigest": "sha256:...",
|
|
47
|
+
"treeDigest": "sha256:..."
|
|
48
|
+
},
|
|
49
|
+
"patch": {
|
|
50
|
+
"patchId": "candidate-42"
|
|
51
|
+
},
|
|
52
|
+
"fingerprints": {
|
|
53
|
+
"harness": "sha256:...",
|
|
54
|
+
"policy": "sha256:...",
|
|
55
|
+
"environment": "sha256:..."
|
|
56
|
+
},
|
|
57
|
+
"checks": [
|
|
58
|
+
{
|
|
59
|
+
"checkId": "tests",
|
|
60
|
+
"status": "passed",
|
|
61
|
+
"redacted": true,
|
|
62
|
+
"startedAt": "2026-08-20T11:59:00.000Z",
|
|
63
|
+
"completedAt": "2026-08-20T11:59:01.000Z",
|
|
64
|
+
"durationMs": 1000,
|
|
65
|
+
"exitCode": 0,
|
|
66
|
+
"redactedOutputDigest": "sha256:..."
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The CLI fills `patchDigest` from `--patch`; the library-level `createChangeEnvelope` input requires it explicitly. Timestamps use millisecond-precision ISO-8601 UTC. Checks, approvals, scopes, and attestations are sorted canonically, so semantically identical set-like inputs produce the same envelope ID.
|
|
73
|
+
|
|
74
|
+
`workspaceDigest` identifies the governed workspace/scope chosen by the producer. `treeDigest` identifies the exact base tree to which the candidate applies. The envelope validates that these are SHA-256 values and binds them, but it does not guess their meaning or compute them from a Git repository: the admission system must supply and verify the correct values for its own source-control model.
|
|
75
|
+
|
|
76
|
+
## Verification preconditions
|
|
77
|
+
|
|
78
|
+
Pass a strict JSON object with `--preconditions` when an admission system has expected values:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"baseTreeDigest": "sha256:...",
|
|
83
|
+
"harnessFingerprint": "sha256:...",
|
|
84
|
+
"policyFingerprint": "sha256:...",
|
|
85
|
+
"environmentFingerprint": "sha256:...",
|
|
86
|
+
"requiredPassedChecks": ["tests", "typecheck"],
|
|
87
|
+
"requiredApprovalScopes": ["workspace:write", "checks:accept"],
|
|
88
|
+
"requiredAttestationDigests": ["sha256:..."]
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Supported preconditions cover the envelope ID, workspace/tree, patch ID/digest, harness/policy/environment, evidence digest, required passing check IDs, active approval digests/scopes, and referenced external-attestation bundle digests. The CLI always adds the digest of the exact `--patch` bytes and rejects a conflicting value in the precondition file. A recorded failed or skipped check is evidence, but it satisfies no `requiredPassedChecks` entry.
|
|
93
|
+
|
|
94
|
+
## Authenticity boundary
|
|
95
|
+
|
|
96
|
+
`ChangeEnvelope v1` is content-addressed, not signed. Anyone who can replace an envelope can recompute its SHA-256 identifiers. The verifier therefore reports:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
verificationScope = integrity-expiration-and-preconditions-only
|
|
100
|
+
approvals.authenticity = not-verified
|
|
101
|
+
externalAttestations.authenticity = not-verified
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
An `externalAttestations` entry binds only an attestation ID, format, media type, and bundle digest. Validate the referenced Sigstore, in-toto, SLSA, or organization-specific bundle with its native trust policy, then pass its expected digest as an admission precondition. Never treat a recorded approval reference as proof of who approved it.
|
|
105
|
+
|
|
106
|
+
## Library API
|
|
107
|
+
|
|
108
|
+
The package exports `createChangeEnvelope`, `verifyChangeEnvelope`, `canonicalizeChangeEnvelope`, `digestChangeEnvelopeArtifact`, the digest recomputation helpers, strict Zod schemas, and all corresponding TypeScript types. This keeps the contract agent-agnostic: a CI gate, code-review bot, local harness, or deployment controller can produce or consume the same document.
|
|
109
|
+
|
|
110
|
+
## Known limits
|
|
111
|
+
|
|
112
|
+
- The CLI binds a supplied patch artifact but does not apply it, infer a Git base, run checks, or mint approvals.
|
|
113
|
+
- Check evidence is a redacted summary supplied by the producer; a trusted runner fingerprint or external attestation is needed when provenance matters.
|
|
114
|
+
- Creation-time and expiration decisions depend on the verifier's clock.
|
|
115
|
+
- SHA-256 integrity does not provide signer identity, transparency logging, revocation, or policy authorization.
|
|
116
|
+
- The v1 contract supports bounded UTF-8 JSON metadata and a patch artifact of at most 64 MiB; large binary release artifacts need a separate artifact policy.
|
package/docs/CLI.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CLI contract
|
|
2
2
|
|
|
3
|
-
Zhivex Harness `0.
|
|
3
|
+
Zhivex Harness `0.9.x` is Bun-first and exposes a durable agent console, offline change-envelope operations, plus versioned JSON documents and JSON Lines events for automation.
|
|
4
4
|
|
|
5
5
|
## Commands
|
|
6
6
|
|
|
@@ -21,6 +21,8 @@ zhivex-harness runs inspect <runId>
|
|
|
21
21
|
zhivex-harness runs export <runId>
|
|
22
22
|
zhivex-harness runs cancel <runId> [--reason <text>] [--cascade] [--final]
|
|
23
23
|
zhivex-harness runs cleanup --before <date|timestamp> [--status <status>] [--limit <n>]
|
|
24
|
+
zhivex-harness changes create <input.json> --patch <artifact>
|
|
25
|
+
zhivex-harness changes verify <envelope.json> --patch <artifact> [--preconditions <file>] [--now <ISO-8601 UTC>]
|
|
24
26
|
zhivex-harness --version
|
|
25
27
|
zhivex-harness --help
|
|
26
28
|
```
|
|
@@ -53,7 +55,7 @@ Provider/model changes apply only to the next run. The console blocks them while
|
|
|
53
55
|
|
|
54
56
|
`--require-capability <name>`, `--subagent <profile>`, and `--reviewer <explorer|reviewer>` are repeatable. `--mcp-config <path>` loads a schema-versioned file inside the canonical workspace. Child limits use `--subagent-max-steps`, `--subagent-max-tool-calls`, `--subagent-max-tool-errors`, `--subagent-max-input-tokens`, `--subagent-max-output-tokens`, `--subagent-max-total-tokens`, and `--subagent-timeout-ms`. Parallel review is capped by `--max-parallel-reviews`.
|
|
55
57
|
|
|
56
|
-
`--route <profile=provider[:model]>` is repeatable for `explorer`, `implementer`, `tester`, and `reviewer`. Omit the model to use that provider's default. Duplicate roles and unknown providers fail before a model is created. Only routed roles are instantiated. `--max-cost-usd` cannot be combined with routes in `0.
|
|
58
|
+
`--route <profile=provider[:model]>` is repeatable for `explorer`, `implementer`, `tester`, and `reviewer`. Omit the model to use that provider's default. Duplicate roles and unknown providers fail before a model is created. Only routed roles are instantiated. `--max-cost-usd` cannot be combined with routes in `0.9.x`, because the current budget has one operator-supplied price pair and cannot price heterogeneous child usage accurately.
|
|
57
59
|
|
|
58
60
|
`review` is application-owned parallelism and accepts only read-only explorer/reviewer members. Model-directed delegation occurs only inside `run` or `chat` when the parent invokes an enabled `delegate_<profile>` tool.
|
|
59
61
|
|
|
@@ -76,12 +78,20 @@ Enforced execution is opt-in:
|
|
|
76
78
|
|
|
77
79
|
`--oci-allow-command` is repeatable, replaces the default executable allowlist, and must include `bun` so declared package checks can run. Commands are exact argv arrays, never shell strings. See [EXECUTION_ENVIRONMENTS.md](./EXECUTION_ENVIRONMENTS.md).
|
|
78
80
|
|
|
81
|
+
## Change admission
|
|
82
|
+
|
|
83
|
+
`changes create` and `changes verify` are local operator commands. They do not load a provider, inspect a repository, run checks, apply a patch, or contact a network service. Both require `--patch <artifact>` so the envelope is checked against exact bytes rather than a filename or mutable logical ID.
|
|
84
|
+
|
|
85
|
+
`create` accepts a strict JSON input, fills `patch.patchDigest`, and emits one canonical `change-envelope` JSON document. `verify` emits a `change-envelope-verification` document and can require expected bindings through `--preconditions <file>`. It returns exit `1` for an integrity, expiration, exact-patch, or precondition failure. `--now` exists for deterministic replay; omit it for normal admission.
|
|
86
|
+
|
|
87
|
+
The verifier never claims signer identity. Approval and attestation references remain `authenticity: "not-verified"` until an external trust verifier validates the referenced artifact. See [CHANGE_ENVELOPES.md](./CHANGE_ENVELOPES.md).
|
|
88
|
+
|
|
79
89
|
## Exit codes
|
|
80
90
|
|
|
81
91
|
| Code | Meaning |
|
|
82
92
|
| --- | --- |
|
|
83
93
|
| `0` | Command completed successfully. |
|
|
84
|
-
| `1` | Runtime, provider, or
|
|
94
|
+
| `1` | Runtime, provider, agent, or change-admission verification failure. |
|
|
85
95
|
| `2` | Invalid CLI usage. |
|
|
86
96
|
| `3` | `doctor` found a blocking configuration problem. |
|
|
87
97
|
|
|
@@ -98,7 +108,7 @@ All structured documents include:
|
|
|
98
108
|
```json
|
|
99
109
|
{
|
|
100
110
|
"schemaVersion": 1,
|
|
101
|
-
"kind": "providers | doctor | run-result | review-group | run-list | run-inspection | run-export | run-cancellation | run-cleanup | session-list | session"
|
|
111
|
+
"kind": "providers | doctor | run-result | review-group | run-list | run-inspection | run-export | run-cancellation | run-cleanup | session-list | session | change-envelope | change-envelope-verification"
|
|
102
112
|
}
|
|
103
113
|
```
|
|
104
114
|
|
|
@@ -47,7 +47,7 @@ zhivex-harness runs cleanup --before 2026-08-01T00:00:00Z
|
|
|
47
47
|
|
|
48
48
|
## Durable CLI sessions
|
|
49
49
|
|
|
50
|
-
The `0.
|
|
50
|
+
The `0.9.x` console maintains a scoped session index in prefixed tables inside `operations.sqlite`. A session is an ordered chain of immutable run references; it is not a mutable provider run. The index stores session ID/title, parent/fork metadata, run ID, provider, model, role, status, and timestamps. It never stores prompts, messages, tool calls/results, approval arguments, provider data, or environment values.
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
53
|
zhx chat
|
|
@@ -66,7 +66,7 @@ The store uses SQLite WAL transactions, optimistic revisions, workspace/scope ha
|
|
|
66
66
|
|
|
67
67
|
Every console turn preallocates a new run ID and binds it permanently to one provider/model. Provider or model changes take effect only on the next run and are blocked while an approval is pending. Before transferring context to another provider/model, the console creates a bounded deterministic redacted summary: text is truncated and common credentials are removed, while tool inputs, outputs, and provider payloads are replaced by tool/type names.
|
|
68
68
|
|
|
69
|
-
Per-role routes are stored as non-secret provider/model metadata in the durable resume envelope so an approval restart reconstructs the same subagent models and fingerprint. A route never performs in-run failover. Heterogeneous routes cannot be combined with the single-price `--max-cost-usd` contract in `0.
|
|
69
|
+
Per-role routes are stored as non-secret provider/model metadata in the durable resume envelope so an approval restart reconstructs the same subagent models and fingerprint. A route never performs in-run failover. Heterogeneous routes cannot be combined with the single-price `--max-cost-usd` contract in `0.9.x`.
|
|
70
70
|
|
|
71
71
|
## Budgets
|
|
72
72
|
|
|
@@ -104,6 +104,18 @@ The default compactor activates at 60 messages or an estimated 40,000 input toke
|
|
|
104
104
|
|
|
105
105
|
Operational artifacts are schema version `1`. By default they exclude raw messages, tool inputs, tool outputs, approval arguments, run metadata, and full output text. Traces, ledger previews, and journal errors apply the production secret/email redaction policy. This is a defensive export boundary, not a guarantee that arbitrary model-generated prose can never contain sensitive business data; control prompt contents and workspace permissions accordingly.
|
|
106
106
|
|
|
107
|
+
## Migration from 0.8.x
|
|
108
|
+
|
|
109
|
+
`0.9.0` retains configuration schema `4`, final JSON schema `1`, session tables, run-store layout, provider defaults, and both executable aliases. The new change-envelope commands are provider-free and do not add persisted run state.
|
|
110
|
+
|
|
111
|
+
The repository tool fingerprint changes because `read_files` and `search_many` join the read-only surface. Resolve or deny paused `0.8.x` approvals with the matching `0.8.x` artifact; `0.9.x` intentionally rejects a resume whose harness version or tool contract differs. Completed `0.8.x` runs remain available to redacted operator inspection, and new `0.9.x` sessions can start normally.
|
|
112
|
+
|
|
113
|
+
## Migration from 0.7.x
|
|
114
|
+
|
|
115
|
+
`0.8.0` keeps configuration schema version `4`, final JSON schema `1`, session storage, CLI commands, and both executable aliases. The OpenAI default changes from `gpt-5.4` to `gpt-5.6-luna`; pass an explicit model when retaining the previous behavior is required.
|
|
116
|
+
|
|
117
|
+
Paused `0.7.x` approvals are intentionally not resumable by `0.8.x`: the durable binding includes the harness version, so resume fails closed before a tool side effect. Resolve or deny them with the matching `0.7.x` artifact. Completed runs remain inspectable, and new `0.8.x` sessions can start from an explicitly compacted summary.
|
|
118
|
+
|
|
107
119
|
## Migration from 0.6.x
|
|
108
120
|
|
|
109
121
|
`0.7.0` keeps configuration schema version `4`, final JSON schema `1`, existing run commands, and the `zhivex-harness` binary. It adds the `zhx` alias, session tables, optional route metadata, and a JSONL event schema without rewriting existing run rows.
|
|
@@ -8,7 +8,7 @@ This is a local enforced runner. It is not a hosted sandbox, a virtual machine,
|
|
|
8
8
|
|
|
9
9
|
The harness trusts the operator, host OS, Docker or Podman daemon, configured image, Zhivex packages, and its own state directory. The model and code executed in the container are outside that trust boundary.
|
|
10
10
|
|
|
11
|
-
The OCI policy is enforced
|
|
11
|
+
The OCI policy is enforced for one acquired run session, with each command committed as a separate validated transaction:
|
|
12
12
|
|
|
13
13
|
- `--network none`;
|
|
14
14
|
- a read-only container root filesystem;
|
|
@@ -79,7 +79,13 @@ The acquired environment contains two owner-only copies under `<state-dir>/envir
|
|
|
79
79
|
- `base`: the immutable comparison snapshot;
|
|
80
80
|
- `workspace`: the mutable snapshot used by repository tools and containers.
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
In `0.9.x`, acquisition keeps only a bounded metadata inventory in memory, writes each verified source file to `base` once, and creates `workspace` with filesystem copy-on-write cloning when available. Unsupported filesystems fall back to an independent normal copy. Patch comparison inventories both trees but rereads file content only for paths whose digest or mode changed. This changes host I/O and memory use, not the two-copy trust model: mutations in `workspace` remain observable as a patch against `base` and never mutate `base`.
|
|
83
|
+
|
|
84
|
+
`environment_status` includes cumulative `io` counters for inventory passes/pages, verified content reads/bytes, snapshot files/bytes, clone fallbacks, container starts/reuses, successful workspace publications, and changed-workspace exports. They are diagnostics for profiling and regression tests, not admission evidence or a stable performance guarantee.
|
|
85
|
+
|
|
86
|
+
The first command seeds a size-bounded `/workspace` tmpfs from the durable snapshot and subsequent successful commands reuse that run container while the host snapshot fingerprint remains unchanged. The container stays paused while idle. After every command the harness rejects surviving background processes, clears `/tmp`, and computes a canonical workspace seal. An unchanged seal takes a no-export fast path. A changed seal freezes the container, copies `/workspace` out through the runtime into a new owner-only staging directory, rejects symlinks, hard links, special files, oversized workspaces, excessive entries, and oversized changed files, then atomically replaces the durable snapshot. The host snapshot is never mounted writable into an untrusted container.
|
|
87
|
+
|
|
88
|
+
Failed, cancelled, timed-out, output-limited, invalid, or background-spawning commands do not publish partial workspace mutations: their container and tmpfs volume are destroyed. A later command reseeds from the last durable snapshot. Repository-tool changes made outside the container alter the host-side snapshot fingerprint, which likewise discards the warm container and reseeds before execution. This preserves one durable source of truth instead of silently carrying stale container state.
|
|
83
89
|
|
|
84
90
|
`inspect_environment_patch` compares them deterministically and returns a run-bound patch identifier plus create/update/delete entries, content digests, and before/after permission modes. Content-identical mode changes remain visible, and modes are part of the reviewed `patchId`. It rejects binary changes, more than 50 files, a patch above 4 MiB, or a file above the configured import ceiling.
|
|
85
91
|
|
|
@@ -99,7 +105,7 @@ PID limits are the primary fork-bomb control. Memory and CPU limits constrain re
|
|
|
99
105
|
|
|
100
106
|
Environment artifacts are keyed by a hash of the durable run ID and include an owner-only metadata file bound to that exact run, workspace, environment fingerprint, and image. Reacquisition reuses the same snapshot only when every binding matches.
|
|
101
107
|
|
|
102
|
-
Each runtime container and temporary workspace volume carries `com.zhivex.harness.execution=v1` and a hashed run label.
|
|
108
|
+
Each runtime container and temporary workspace volume carries `com.zhivex.harness.execution=v1` and a hashed run label. The container remains paused between successful commands and session release force-removes all resources for that run before recording status and release time. `runs cleanup --before <cutoff>` removes only released terminal artifact directories older than the cutoff; with OCI configured it also removes labeled containers in `created`, `exited`, `dead`, or `paused` state and unused labeled volumes. Unknown directories, symlinks, active resources, and unlabeled OCI resources are skipped.
|
|
103
109
|
|
|
104
110
|
Crash recovery relies on the same labels and durable artifacts. An operator can rerun cleanup after a process crash. The harness does not issue broad container/volume prune commands and never deletes an unlabeled OCI resource.
|
|
105
111
|
|
|
@@ -115,7 +121,7 @@ Applications constructing the harness can inject a `HarnessOciRuntimeAdapter` fo
|
|
|
115
121
|
|
|
116
122
|
The deterministic tests use an injected runtime to cover acquisition, secret exclusion, snapshot-only mutation, patch binding/import, separate approvals, image-fingerprint resume rejection, release, and safe artifact cleanup. The installed-package smoke imports the public OCI API and proves that a consumer can perform the same snapshot/import flow.
|
|
117
123
|
|
|
118
|
-
`bun run smoke:oci` exercises a real Docker/Podman daemon and preloaded image. It verifies secret exclusion, denied outbound network, denied root-filesystem writes, snapshot mutation, enforced workspace capacity, package checks, host non-mutation before import, approved import, cancellation, release, orphan cleanup, and artifact retention cleanup.
|
|
124
|
+
`bun run smoke:oci` exercises a real Docker/Podman daemon and preloaded image. It verifies secret exclusion, denied outbound network, denied root-filesystem writes, warm-container reuse, host-tool reseeding, background-process rejection, snapshot mutation, enforced workspace capacity, package checks, host non-mutation before import, approved import, cancellation, release, orphan cleanup, and artifact retention cleanup. `bun run benchmark:oci` reports first-command, warm no-op, mutation, snapshot, and runtime-I/O measurements on a configurable synthetic repository. The smoke skips locally when no daemon is available unless `ZHIVEX_HARNESS_OCI_REQUIRED=1`; Linux CI, release validation, and live certification set that variable so absence is a failure.
|
|
119
125
|
|
|
120
126
|
Provider certification is separate and billable. The live workflow runs the required OCI gate before the model-directed Meta, Qwen, and OpenAI matrices. A deterministic OCI pass does not by itself certify a provider, and live provider success does not replace exact installed-artifact or published-registry proof.
|
|
121
127
|
|
package/docs/EXTENSIBILITY.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Extensibility and orchestration
|
|
2
2
|
|
|
3
|
-
Zhivex Harness `0.
|
|
3
|
+
Zhivex Harness `0.9.x` combines governed external tools and bounded multi-agent work with a public provider registry and explicit per-role model routing. Configuration schema remains version `4`; registry selection, runtime model capabilities, routed child models, non-secret provider transport settings, MCP, execution policy, budgets, and scope are bound into the durable harness fingerprint.
|
|
4
4
|
|
|
5
5
|
## Provider registry
|
|
6
6
|
|
|
@@ -8,7 +8,11 @@ Built-in registrations are Meta, Qwen, OpenAI, and Gemini. Each registration own
|
|
|
8
8
|
|
|
9
9
|
Library callers can use `DEFAULT_PROVIDER_REGISTRY`, `BUILTIN_PROVIDER_REGISTRATIONS`, `createProviderRegistry`, or `DEFAULT_PROVIDER_REGISTRY.extend(...)`, then pass the registry to `resolveHarnessConfig`, `createProviderModel`, provider diagnostics, or `createHarness({ providerRegistry })`. Registration IDs, environment-variable names, defaults, diagnostics, and factories are validated before they become selectable.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The coordinated SDK batch pins `@zhivex-ai/agents@1.2.0`, `@zhivex-ai/core@1.7.0`, `@zhivex-ai/meta@0.2.2`, `@zhivex-ai/qwen@0.10.2`, `@zhivex-ai/openai@0.9.6`, and `@zhivex-ai/gemini@0.10.5`. A Core override keeps one runtime contract identity across every adapter.
|
|
12
|
+
|
|
13
|
+
OpenAI is based on the GPT-5.6 family: `gpt-5.6-luna` is the default, with `gpt-5.6-terra` and `gpt-5.6-sol` available through `--model`. Availability remains organization-dependent while the upstream family is in limited preview, and the adapter uses the Responses API by default.
|
|
14
|
+
|
|
15
|
+
Gemini defaults to `gemini-3.6-flash`, uses `GEMINI_API_KEY` or `GOOGLE_GENERATIVE_AI_API_KEY`, and accepts optional `GEMINI_BASE_URL`. It is provisional until proposal/approval/restart, delegation, mixed routing, and OCI execution pass the credentialed harness live matrix; adapter-level evidence alone does not make the harness integration certified.
|
|
12
16
|
|
|
13
17
|
## Capability gate
|
|
14
18
|
|
|
@@ -115,7 +119,7 @@ The resolved route plan is persisted without credentials in CLI resume metadata
|
|
|
115
119
|
## Routing limits
|
|
116
120
|
|
|
117
121
|
- There is no automatic failover inside a run and no provider change while an approval is pending.
|
|
118
|
-
- `--max-cost-usd` with any route is rejected because `0.
|
|
122
|
+
- `--max-cost-usd` with any route is rejected because `0.9.x` has one operator-supplied price pair, not pricing per model/run.
|
|
119
123
|
- Routing does not infer speed, quality, price, or a “best” provider; presets remain deferred until the model catalog contains reliable evidence.
|
|
120
124
|
- The CLI registry is static. Applications may inject a validated registry through the TypeScript API, but configuration files cannot load arbitrary provider modules.
|
|
121
125
|
- Cross-provider console context uses deterministic redacted compaction and omits tool/provider payloads; it is a portable summary, not a byte-identical transcript handoff.
|
|
@@ -54,6 +54,22 @@ A missing credential, unavailable container runtime, upstream failure, incomplet
|
|
|
54
54
|
|
|
55
55
|
## Current public status
|
|
56
56
|
|
|
57
|
-
Meta, Qwen, and OpenAI retain the previously published
|
|
57
|
+
Meta, Qwen, and OpenAI retain the previously published support conclusion for unchanged runtime paths. The published `0.7.0` release added Gemini and mixed-provider routing as provisional surfaces; they require fresh release-candidate evidence before certification.
|
|
58
58
|
|
|
59
59
|
The controlled and official-SDK MCP interoperability gates remain separate transport evidence. They certify only the tested protocol, implementation, and compatibility mode, not every MCP server or future protocol version.
|
|
60
|
+
|
|
61
|
+
## Current local pre-release evidence
|
|
62
|
+
|
|
63
|
+
On 2026-08-20, the uncommitted `0.8.0` source worktree with `@zhivex-ai/core@1.7.0` and `@zhivex-ai/openai@0.9.6` passed the base proposal/approval/restart/exactly-once gate for the GPT-5.6 family used by the Harness:
|
|
64
|
+
|
|
65
|
+
| Provider | Model | Result |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| OpenAI | `gpt-5.6-luna` | Passed |
|
|
68
|
+
| OpenAI | `gpt-5.6-terra` | Passed |
|
|
69
|
+
| OpenAI | `gpt-5.6-sol` | Passed |
|
|
70
|
+
|
|
71
|
+
Every run persisted the `apply_patch` approval, restarted against the same scoped durable store, executed the approved mutation exactly once, and recorded exactly one completed journal entry.
|
|
72
|
+
|
|
73
|
+
The `0.8.0`-bound runs completed at `2026-08-20T20:13:24.151Z` for Luna, `2026-08-20T20:13:25.211Z` for Terra, and `2026-08-20T20:13:27.441Z` for Sol. The Luna run omitted the model override and resolved to `gpt-5.6-luna` through the provider registry default.
|
|
74
|
+
|
|
75
|
+
This is local pre-release evidence, not public release certification: the worktree is not committed, the exact `0.8.0` artifact is not published, and the source-commit/provenance requirement is therefore unsatisfied. It certifies only the shared Harness edit-and-resume path. It does not certify GPT-5.6 Programmatic Tool Calling, Multi-agent, hosted tools, long-context pricing, model-directed OCI execution, or mixed-provider routing.
|
package/docs/RELEASE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Release process
|
|
2
2
|
|
|
3
|
-
`@zhivex-ai/harness@0.
|
|
3
|
+
`@zhivex-ai/harness@0.8.0` is the latest public npm release. `0.9.0` is a source candidate, not a published artifact. Publication is never performed from a development checkout. The confirmation-gated `.github/workflows/release.yml` workflow builds, inspects, transfers, and publishes one exact tarball through npm Trusted Publishing/OIDC. Creating a tag alone does not publish anything.
|
|
4
4
|
|
|
5
5
|
## Deterministic gates
|
|
6
6
|
|
|
@@ -48,9 +48,9 @@ For a local artifact rehearsal after the source gate:
|
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
50
|
mkdir -p release-artifacts
|
|
51
|
-
bun pm pack --filename release-artifacts/zhivex-ai-harness-0.
|
|
52
|
-
bun run artifact:check -- release-artifacts/zhivex-ai-harness-0.
|
|
53
|
-
bun run smoke:artifact -- release-artifacts/zhivex-ai-harness-0.
|
|
51
|
+
bun pm pack --filename release-artifacts/zhivex-ai-harness-0.9.0.tgz --ignore-scripts
|
|
52
|
+
bun run artifact:check -- release-artifacts/zhivex-ai-harness-0.9.0.tgz
|
|
53
|
+
bun run smoke:artifact -- release-artifacts/zhivex-ai-harness-0.9.0.tgz
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
`release-artifacts/`, `.npmrc`, `.env`, source tests, Git metadata, and local run state are excluded from the package.
|
|
@@ -21,6 +21,10 @@ These controls prevent silent workspace drift; they do not isolate the host. Run
|
|
|
21
21
|
|
|
22
22
|
`list_files` and `search_files` return deterministic pages. Each response includes `truncated` and, when another page exists, an opaque `nextCursor`. Supply that cursor unchanged to request the next page. A cursor is bound to the original operation and parameters; it must not be edited or reused for a different path, query, case-sensitivity setting, or page size.
|
|
23
23
|
|
|
24
|
+
In `0.9.x`, pagination reuses a topology-only index. Before each reuse, the harness validates visible directory metadata and the metadata plus content digests of applicable ignore files. A structural or ignore-policy change invalidates the index and makes an older cursor fail as stale. File bytes and content digests are never served from that index: every listed page, read, and search uses the stable anti-race file reader, so an external content-only change is observed even when the topology remains valid.
|
|
25
|
+
|
|
26
|
+
Use `read_files` for up to 20 independent file/range requests with a 2 MiB aggregate source limit; duplicate paths share one stable read. Use `search_many` for up to 10 literal queries and 500 aggregate matches; it reads each candidate file once for the whole query set. The single-file tools remain available for focused reads and cursor-paginated search. Batch tools are read-only and do not enable global tool parallelism, so write ordering and approval behavior are unchanged.
|
|
27
|
+
|
|
24
28
|
Listed files and every search match include a content digest. `read_file` also returns the digest of the complete file, even when only a line range was requested. Digests are the concurrency contract for later edits: reading content and then editing it without carrying the observed digest does not provide stale-workspace protection.
|
|
25
29
|
|
|
26
30
|
Ignore rules affect discovery, not direct authorization. A direct request for a hard-protected path still fails. An ignored ordinary source file can only be addressed when the workspace policy explicitly permits the direct operation.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-08-20T12:00:00.000Z",
|
|
3
|
+
"base": {
|
|
4
|
+
"workspaceDigest": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
|
|
5
|
+
"treeDigest": "sha256:2222222222222222222222222222222222222222222222222222222222222222"
|
|
6
|
+
},
|
|
7
|
+
"patch": {
|
|
8
|
+
"patchId": "example-candidate"
|
|
9
|
+
},
|
|
10
|
+
"fingerprints": {
|
|
11
|
+
"harness": "sha256:3333333333333333333333333333333333333333333333333333333333333333",
|
|
12
|
+
"policy": "sha256:4444444444444444444444444444444444444444444444444444444444444444",
|
|
13
|
+
"environment": "sha256:5555555555555555555555555555555555555555555555555555555555555555"
|
|
14
|
+
},
|
|
15
|
+
"checks": [
|
|
16
|
+
{
|
|
17
|
+
"checkId": "tests",
|
|
18
|
+
"status": "passed",
|
|
19
|
+
"redacted": true,
|
|
20
|
+
"startedAt": "2026-08-20T11:59:00.000Z",
|
|
21
|
+
"completedAt": "2026-08-20T11:59:01.000Z",
|
|
22
|
+
"durationMs": 1000,
|
|
23
|
+
"exitCode": 0
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhivex-ai/harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.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",
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
"coding-agent",
|
|
24
24
|
"agent-runtime",
|
|
25
25
|
"agent-governance",
|
|
26
|
+
"change-control",
|
|
27
|
+
"policy-as-code",
|
|
28
|
+
"software-supply-chain",
|
|
26
29
|
"sandbox",
|
|
27
30
|
"durable-workflows",
|
|
28
31
|
"mcp",
|
|
@@ -63,6 +66,9 @@
|
|
|
63
66
|
"typecheck": "tsc --noEmit",
|
|
64
67
|
"test": "bun test",
|
|
65
68
|
"evaluate": "bun run scripts/evaluate.ts",
|
|
69
|
+
"benchmark:workspace": "bun run scripts/benchmark-workspace.ts",
|
|
70
|
+
"benchmark:workspace:ci": "bun run scripts/benchmark-workspace.ts --files 1000 --page-size 100",
|
|
71
|
+
"benchmark:oci": "bun run scripts/benchmark-oci.ts",
|
|
66
72
|
"smoke:package": "bun run build && bun run scripts/package-smoke.ts",
|
|
67
73
|
"smoke:artifact": "bun run scripts/package-smoke.ts",
|
|
68
74
|
"smoke:mcp": "bun run scripts/mcp-interoperability-smoke.ts",
|
|
@@ -75,22 +81,22 @@
|
|
|
75
81
|
"demo:hostile": "bun run dist/hostile-repository-demo.js",
|
|
76
82
|
"artifact:check": "bun run scripts/check-release-artifact.ts",
|
|
77
83
|
"pack:inspect": "bun run build && bun pm pack --dry-run --ignore-scripts",
|
|
78
|
-
"check": "bun run docs:check && bun run typecheck && bun test && bun run evaluate && bun run smoke:mcp && bun run smoke:mcp:official && bun run smoke:oci && bun run smoke:package",
|
|
84
|
+
"check": "bun run docs:check && bun run typecheck && bun test && bun run evaluate && bun run benchmark:workspace:ci && bun run smoke:mcp && bun run smoke:mcp:official && bun run smoke:oci && bun run smoke:package",
|
|
79
85
|
"release:check": "bun run check && bun audit && bun pm untrusted && bun run pack:inspect && bun run scripts/check-release-readiness.ts",
|
|
80
86
|
"release:status": "bun run scripts/check-registry-release-status.ts",
|
|
81
87
|
"release:verify": "bun run scripts/verify-registry-release.ts"
|
|
82
88
|
},
|
|
83
89
|
"dependencies": {
|
|
84
90
|
"@zhivex-ai/agents": "1.2.0",
|
|
85
|
-
"@zhivex-ai/core": "1.
|
|
86
|
-
"@zhivex-ai/gemini": "0.10.
|
|
87
|
-
"@zhivex-ai/meta": "0.2.
|
|
88
|
-
"@zhivex-ai/openai": "0.9.
|
|
89
|
-
"@zhivex-ai/qwen": "0.10.
|
|
91
|
+
"@zhivex-ai/core": "1.7.0",
|
|
92
|
+
"@zhivex-ai/gemini": "0.10.5",
|
|
93
|
+
"@zhivex-ai/meta": "0.2.2",
|
|
94
|
+
"@zhivex-ai/openai": "0.9.6",
|
|
95
|
+
"@zhivex-ai/qwen": "0.10.2",
|
|
90
96
|
"zod": "4.4.3"
|
|
91
97
|
},
|
|
92
98
|
"overrides": {
|
|
93
|
-
"@zhivex-ai/core": "1.
|
|
99
|
+
"@zhivex-ai/core": "1.7.0"
|
|
94
100
|
},
|
|
95
101
|
"devDependencies": {
|
|
96
102
|
"@modelcontextprotocol/server": "2.0.0",
|