@zhivex-ai/harness 1.4.1 → 1.6.2
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 +23 -0
- package/README.md +1 -1
- package/SUPPORT.md +1 -1
- package/contracts/stable-api-signatures.json +7 -7
- package/dist/acp-cli.js +10 -10
- package/dist/approvals/approval-diff.d.ts +2 -1
- package/dist/approvals/approval-preview.d.ts +1 -1
- package/dist/approvals/auto-approve.d.ts +137 -0
- package/dist/audit/index.js +6 -6
- package/dist/{audit-pack-e4vaq7np.js → audit-pack-fckpqfsb.js} +3 -3
- package/dist/{cli-1cf4dcnj.js → cli-84en174d.js} +14 -8
- package/dist/{cli-entry-3s63zn4w.js → cli-entry-10th5awp.js} +16 -15
- package/dist/{cli-entry-a890x3kq.js → cli-entry-4g2ewcnw.js} +15 -5
- package/dist/{cli-entry-7f0cen32.js → cli-entry-6amx4mcc.js} +209 -68
- package/dist/{cli-entry-rgs6bxmy.js → cli-entry-z1pbjrg4.js} +2 -2
- package/dist/cli.js +2 -2
- package/dist/compat/code-support.js +8 -8
- package/dist/engine/acp.js +11 -11
- package/dist/engine/client.js +10 -10
- package/dist/engine/desktop-state-v1.js +6 -6
- package/dist/engine/index.js +15 -15
- package/dist/engine/mcp-stdio-v1.js +5 -5
- package/dist/engine/service.js +11 -11
- package/dist/hostile-repository-demo.js +235 -84
- package/dist/{index-mv8sb1ns.js → index-1pn0ecs4.js} +55 -13
- package/dist/{index-dtb2c6ds.js → index-2r4f0p4n.js} +2 -2
- package/dist/{index-6599mpmy.js → index-4mn6m3bq.js} +3 -3
- package/dist/{index-xdbkcccf.js → index-6dxrbnxm.js} +2 -2
- package/dist/{index-crta5wzv.js → index-74f9yhfh.js} +4 -4
- package/dist/{index-f6mqa5gk.js → index-amjttjaj.js} +11 -39
- package/dist/{index-wm9xeq1n.js → index-bt2p8x7r.js} +1 -1
- package/dist/{index-sk3cap35.js → index-eps3c3g6.js} +1 -1
- package/dist/{index-zxg4ve4j.js → index-fqqz1yt8.js} +77 -4
- package/dist/{index-02pqtbbg.js → index-paf7z8kn.js} +10 -10
- package/dist/{index-0zs2dz26.js → index-pf73y4gt.js} +18 -9
- package/dist/{index-74kkpyqk.js → index-rgqzdgv6.js} +12 -6
- package/dist/{index-4fx5f3k5.js → index-rz7wmp71.js} +16 -15
- package/dist/{index-d9zkmhz3.js → index-w0m1nckc.js} +127 -28
- package/dist/{index-sstgcsr0.js → index-yx52bt4a.js} +1 -1
- package/dist/{index-j6zxnc8m.js → index-zrz4rs7p.js} +5 -5
- package/dist/index.js +14 -14
- package/dist/integrations/mcp-stdio-tools.d.ts +4 -1
- package/dist/providers/bedrock.d.ts +1 -1
- package/dist/review/reveal-invisible.d.ts +13 -0
- package/dist/runtime/budget-ledger-scope.d.ts +14 -0
- package/dist/service-cli.js +11 -11
- package/dist/{service-client-cli-eqrdc9zq.js → service-client-cli-pp5z4dmf.js} +4 -4
- package/dist/tools/workspace.d.ts +2 -2
- package/dist/verify-historical-migrations.js +240 -86
- package/dist/workspace/edit-contracts.d.ts +2 -2
- package/dist/workspace/path-policy.d.ts +2 -1
- package/dist/workspace/text-integrity.d.ts +19 -0
- package/dist/workspace/workspace.d.ts +21 -3
- package/dist/zhx.js +2 -2
- package/docs/AUTO_APPROVE.md +51 -0
- package/docs/AZURE_OPENAI.md +4 -4
- package/docs/BEDROCK.md +4 -4
- package/docs/CLI.md +13 -0
- package/docs/CODE_RELEASE.md +36 -6
- package/docs/CODE_WEB_TASKS.md +1 -1
- package/docs/CREDENTIALS.md +1 -1
- package/docs/DURABLE_OPERATIONS.md +1 -1
- package/docs/ENGINE_API.md +1 -1
- package/docs/EXTENSIBILITY.md +7 -3
- package/docs/FIRST_USE.md +6 -6
- package/docs/MINIMUM_TASK_AUTHORITY.md +5 -5
- package/docs/PROJECT_MEMORY.md +1 -1
- package/docs/PUBLIC_SECURITY.md +14 -1
- package/docs/REPOSITORY_EDITING.md +1 -1
- package/docs/TOOL_POLICY.md +7 -1
- package/docs/VERTEX.md +2 -2
- package/docs/WEB_LIMITS.md +2 -2
- package/docs/adr/0002-isolated-mcp-stdio.md +2 -2
- package/evaluations/representative-assembly-matrix.json +37 -1
- package/examples/README.md +3 -3
- package/package.json +16 -15
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,29 @@ The project follows Semantic Versioning. During `0.x`, minor releases may change
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 1.6.2 - 2026-10-24
|
|
10
|
+
|
|
11
|
+
- Allow one continuity retry per provider in the release gate. Live certification of `v1.6.0` and `v1.6.1` (twice) failed only the multi-process continuity gate, each time on a different provider. A provider whose continuity run fails now gets one fresh retry of all phases and passes only if the retry passes. Every selected provider stays mandatory, and no other gate retries. The continuity evidence records which provider retried, the first attempt's sanitized cause, and the retry outcome. Runtime and CLI behavior and defaults are unchanged (#250).
|
|
12
|
+
- 1.6.1 was tagged but not published, so 1.6.2 is the first npm release carrying the 1.6.1 compaction fix below.
|
|
13
|
+
|
|
14
|
+
## 1.6.1 - 2026-10-24
|
|
15
|
+
|
|
16
|
+
- Mark compacted recollections that precede later user messages. Compaction keeps user steering and recent assistant replies in separate lists, so a stale reply naming a replaced objective could read as newer than the user message that superseded it. In the `v1.6.0` live certification, meta and qwen repeated their previous answer in the continuity gate. Recent entries followed by a later user message now carry a `[before later user messages] ` prefix. The summary schema, strategy id, and defaults are unchanged (#248).
|
|
17
|
+
|
|
18
|
+
## 1.6.0 - 2026-10-24
|
|
19
|
+
|
|
20
|
+
- Prepare minor Harness 1.6.0 for npm `latest`. The minor is opt-in auto-approve. Code stays version 0.4.0. Its source pin moves to Harness 1.6.0 because installed acceptance rejects a candidate that differs from that pin. Published npm Code 0.4.0 remains pinned to Harness 1.5.0 and is not republished. Private Desktop binds to this engine. The representative mapping for `v1.6.0` uses the same Meta, Qwen, and OpenAI models as `v1.5.0`. This preparation creates no tag and dispatches no workflow.
|
|
21
|
+
- Add opt-in auto-approve. Manual stays the default. `auto-edits` can apply file edits inside the workspace without a prompt. `auto-limits` adds commands whose executable is on the allowlist. Network or egress, secrets, `git push`, package publish, writes outside the workspace, and a reached spend or token limit still wait for a person. A mixed batch stays on the review screen. `--approval-mode auto` and `--yes` remain the older non-interactive switch and are not this feature. See [opt-in auto-approve](docs/AUTO_APPROVE.md).
|
|
22
|
+
- Rework the local web workspace. Light-theme controls use theme tokens, the header is one bar, and the first message creates the session. A confirmed execution failure stays editable. The model library, composer, message bubbles, tool pills, and appearance control follow the Harness chat reference.
|
|
23
|
+
- Name each terminal action. Read, search, and edit lines state the target. Consecutive edits of one file collapse to a net diff and an attempt count. The review names the change, counts each file, keeps indentation when a line wraps, and shows NUL, zero-width characters, bidi overrides, tabs, and trailing spaces. The decision is "Approve this change".
|
|
24
|
+
- Keep NUL and other control bytes out of model-facing edit tool schemas. `propose_edits`, `apply_patch`, and the replacement and verified-edit inputs do not advertise `allowControlBytes`. Model-supplied text is still refused, and the host opt-in stays off unless a host call passes it outside the tool input. The stable declaration snapshot records that optional host argument.
|
|
25
|
+
- Pin private Desktop Electron 44.9.3 and its optional `undici` dependency at 7.30.1. Electron 44.5.1 is inside GHSA-jr5w-w6x2-84p9 (`<44.9.1`), and undici 7.29.1 is inside GHSA-4qv8-2p9j-2685, GHSA-f72v-6w45-q472, and GHSA-xjj6-f33q-929c (`<7.30.1`). Desktop behavior is unchanged.
|
|
26
|
+
- Pin the private web Playwright devDependency at 1.64.1 so `playwright install --with-deps chromium` can run on the Ubuntu 26.04 GitHub runner. Browser journeys still launch headless Chromium the same way.
|
|
27
|
+
- Pin the published 2026-10-24 SDK batch: Core 1.36.0, Agents 1.12.0, OpenAI 0.17.0, Anthropic 0.15.0, Qwen 0.18.0, Gemini 0.14.0, Vertex 1.3.0, Azure OpenAI 0.8.0, Bedrock 2.1.0, and Meta 0.3.0. The web client pins React 0.10.0. The root Core override stays one runtime. `zod` is 4.6.7 and `google-auth-library` is 11.3.1 so the new adapter floors resolve to one copy. Harness and CLI defaults are unchanged: shared `topP`, `seed`, and `stopSequences` are not sent, `stopWhen` is not set, and voice is unused. `@types/bun` is 1.4.3. CodeQL init and analyze stay SHA-pinned at `6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee` (v4.39.0).
|
|
28
|
+
|
|
29
|
+
## 1.5.0 - 2026-10-16
|
|
30
|
+
|
|
31
|
+
- Prepare minor Harness 1.5.0 and Code 0.4.0 for npm `latest`. The minor covers the new experimental audit pack, provisional Bedrock and Azure OpenAI routes, and Code web task control; stable root exports and command contracts are unchanged. It ships with the exact Code engine pin, private Desktop binding and an additive representative mapping for `v1.5.0` using the unchanged Meta, Qwen and OpenAI models. Published `latest` is Harness 1.4.1 and Code 0.3.2. Tags and publication follow only through the protected release workflows.
|
|
9
32
|
- Add provisional Amazon Bedrock and Azure OpenAI routes. Bedrock pins `@zhivex-ai/bedrock@2.0.7` (Converse uses the AWS credential chain and region and reports Tier B; `BEDROCK_RUNTIME=openai` is the Tier A path). Azure OpenAI pins `@zhivex-ai/azure-openai@0.7.8` (https endpoint, API key, optional API version and deployments map). Core is `@zhivex-ai/core@1.34.0`, which those adapters require. An incomplete Bedrock or Azure environment stays out of the durable transport fingerprint. Desktop forwards the selected route's environment credentials through the worker bootstrap. These routes are uncertified: no live calls, no default certification cohort, and no publish or tags.
|
|
10
33
|
- Add an experimental audit pack on `@zhivex-ai/harness/audit`. `zhx export-audit <task-id> --out <directory>` writes one directory per run, or one directory containing every run on a guided task account. The pack reuses the governance report, every approval decision page up to 512 records, the durable redacted activity journal as JSONL, and the usage ledger projection plus transport summary. Approvals, usage, and the governance report come from one captured run snapshot. A change to that run, its journal, or the task account before signing fails with `AUDIT_PACK_STATE_CHANGED` and writes nothing. The 32 MiB limit includes `manifest.json`. `zhx verify-audit --out <directory>` checks the manifest hashes and an HMAC-SHA256 seal without resolving provider, store, or budget configuration. The signing key is `ZHIVEX_AUDIT_SIGNING_KEY` or `--signing-key-file` and is not stored in the pack. Stable root exports, stable declaration signatures, and existing command option contracts are unchanged. This note does not publish a release.
|
|
11
34
|
- Add experimental Code web task definition, bounded exact delivery review, explicit human acceptance, requirement correction, and budgeted continuation through additive host-owned client commands. Keep check verification, human decisions, and provider usage uncertainty distinct. Failed pre-admission continuations retain scoped previous evidence without inventing budget admissions; ordinary chat cannot bypass a governed task's budget.
|
package/README.md
CHANGED
|
@@ -159,6 +159,6 @@ Contracts, stability tiers, and the experimental ACP and MCP entry points are in
|
|
|
159
159
|
|
|
160
160
|
## Releases
|
|
161
161
|
|
|
162
|
-
Version `1.
|
|
162
|
+
Version `1.5.0` is the current public npm release. The paired Code package on npm `latest` is `0.4.0`, pinned to that engine. This checkout prepares Version `1.6.2` for `latest`. Code stays version `0.4.0`, and its source pin is Harness `1.6.2` for installed acceptance. Published Code `0.4.0` stays on Harness `1.5.0`. That Harness publication is pending, so the quick start above follows the published `latest` tag. npm `next` is Harness `1.4.0-rc.8` and Code `0.3.0-rc.8`. Confirm dist-tags on the [Code versions](https://www.npmjs.com/package/@zhivex-ai/code?activeTab=versions) and [Harness versions](https://www.npmjs.com/package/@zhivex-ai/harness?activeTab=versions) pages before you install a prerelease.
|
|
163
163
|
|
|
164
164
|
Release channels, publication, and certification records are in the [release procedure](https://github.com/Zhivex/zhivex-harness/blob/main/docs/RELEASE.md). Releases are verified with npm provenance. Source in this checkout can be newer than the public package. See the [changelog](CHANGELOG.md) and the [repository release status](https://raw.githubusercontent.com/Zhivex/zhivex-harness/main/release-status.json).
|
package/SUPPORT.md
CHANGED
|
@@ -13,7 +13,7 @@ The 1.1 support scope is tracked in the [machine-readable support matrix](./docs
|
|
|
13
13
|
- the provider/model combinations marked certified in the package documentation; and
|
|
14
14
|
- HTTPS or explicitly allowed loopback-HTTP MCP endpoints using the documented bounded JSON-RPC subset.
|
|
15
15
|
|
|
16
|
-
Only the most recent published stable minor receives routine fixes. The exact `v1.3.0` tag passed the protected artifact, six-provider live and 42-case representative release jobs. Harness 1.
|
|
16
|
+
Only the most recent published stable minor receives routine fixes. The exact `v1.3.0` tag passed the protected artifact, six-provider live and 42-case representative release jobs. Harness 1.5.0 and Code 0.4.0 are the published stable packages. Code stays version 0.4.0. Its source pin is Harness 1.6.2 for installed acceptance, and published Code 0.4.0 remains pinned to Harness 1.5.0 until 1.6.2 completes verified publication. Gemini, Anthropic and Vertex remain provisional despite the release-bound live gates; the representative repository matrix covers only Meta, Qwen and OpenAI. Live provider evidence is account-, model-, endpoint-, artifact-, and date-dependent; see [docs/LIVE_CERTIFICATION.md](https://github.com/Zhivex/zhivex-harness/blob/main/docs/LIVE_CERTIFICATION.md).
|
|
17
17
|
|
|
18
18
|
## Installation diagnostics
|
|
19
19
|
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
},
|
|
126
126
|
{
|
|
127
127
|
"name": "Workspace",
|
|
128
|
-
"sha256": "sha256:
|
|
128
|
+
"sha256": "sha256:9b8bc9eb0d44bb64e75995483aa9c68f73816359da93299844b8c8290c3a1480"
|
|
129
129
|
},
|
|
130
130
|
{
|
|
131
131
|
"name": "appendUserMessage",
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
"name": "createHarness",
|
|
168
|
-
"sha256": "sha256:
|
|
168
|
+
"sha256": "sha256:2a9567b8785aced05da16f6606cf6e71bad3229d2df0d0b1cf1f5f96e57852f2"
|
|
169
169
|
},
|
|
170
170
|
{
|
|
171
171
|
"name": "createHarnessMcpTools",
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
},
|
|
174
174
|
{
|
|
175
175
|
"name": "createHarnessOciExecutionEnvironment",
|
|
176
|
-
"sha256": "sha256:
|
|
176
|
+
"sha256": "sha256:432ed8e25be522eb6adf03ca61bc01d1f04e3ccafcb9a9d380b6b55130f5a1c5"
|
|
177
177
|
},
|
|
178
178
|
{
|
|
179
179
|
"name": "createHarnessStateBackup",
|
|
@@ -273,7 +273,7 @@
|
|
|
273
273
|
},
|
|
274
274
|
{
|
|
275
275
|
"name": "runHarness",
|
|
276
|
-
"sha256": "sha256:
|
|
276
|
+
"sha256": "sha256:e2da41119fb7a86ae2385a2edacee3221c44ab68bcc9360d5307f7df44bd4982"
|
|
277
277
|
},
|
|
278
278
|
{
|
|
279
279
|
"name": "serializeStreamEvent",
|
|
@@ -427,7 +427,7 @@
|
|
|
427
427
|
},
|
|
428
428
|
{
|
|
429
429
|
"name": "HarnessExecutionSession",
|
|
430
|
-
"sha256": "sha256:
|
|
430
|
+
"sha256": "sha256:6ef99960a68c92cbcf6f1b0d6f65fde844f0b1ee1514b7d1b4df65d752cc4a37"
|
|
431
431
|
},
|
|
432
432
|
{
|
|
433
433
|
"name": "HarnessMcpConfiguration",
|
|
@@ -487,8 +487,8 @@
|
|
|
487
487
|
},
|
|
488
488
|
{
|
|
489
489
|
"name": "ZhivexHarness",
|
|
490
|
-
"sha256": "sha256:
|
|
490
|
+
"sha256": "sha256:959a37960c89176ada62c3d126bb30b49d0621b721b89a5972fcf58a184480c0"
|
|
491
491
|
}
|
|
492
492
|
],
|
|
493
|
-
"digest": "sha256:
|
|
493
|
+
"digest": "sha256:ad2cd323cee44ab26037a02eb9079eecf713771601de3fde44ad2e3b4df85cbc"
|
|
494
494
|
}
|
package/dist/acp-cli.js
CHANGED
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
} from "./index-3ah1f369.js";
|
|
12
12
|
import {
|
|
13
13
|
createHarnessClientAdapter
|
|
14
|
-
} from "./index-
|
|
15
|
-
import"./index-
|
|
14
|
+
} from "./index-paf7z8kn.js";
|
|
15
|
+
import"./index-4mn6m3bq.js";
|
|
16
16
|
import {
|
|
17
17
|
createHarness
|
|
18
|
-
} from "./index-
|
|
19
|
-
import"./index-
|
|
20
|
-
import"./index-
|
|
21
|
-
import"./index-
|
|
18
|
+
} from "./index-pf73y4gt.js";
|
|
19
|
+
import"./index-amjttjaj.js";
|
|
20
|
+
import"./index-2r4f0p4n.js";
|
|
21
|
+
import"./index-w0m1nckc.js";
|
|
22
22
|
import {
|
|
23
23
|
HARNESS_REQUIRED_CAPABILITIES,
|
|
24
24
|
HARNESS_SUBAGENT_PROFILES,
|
|
@@ -31,17 +31,17 @@ import {
|
|
|
31
31
|
} from "./index-1265j7t2.js";
|
|
32
32
|
import"./index-c39197wq.js";
|
|
33
33
|
import"./index-mzydbzp8.js";
|
|
34
|
-
import"./index-
|
|
34
|
+
import"./index-bt2p8x7r.js";
|
|
35
35
|
import {
|
|
36
36
|
usagePricingSchema
|
|
37
|
-
} from "./index-
|
|
38
|
-
import"./index-
|
|
37
|
+
} from "./index-fqqz1yt8.js";
|
|
38
|
+
import"./index-rz7wmp71.js";
|
|
39
39
|
import {
|
|
40
40
|
FileChangedWhileReadingError,
|
|
41
41
|
FileSizeLimitError,
|
|
42
42
|
UnsafeFileTypeError,
|
|
43
43
|
readRegularFileNoFollow
|
|
44
|
-
} from "./index-
|
|
44
|
+
} from "./index-6dxrbnxm.js";
|
|
45
45
|
import"./index-4gt045j0.js";
|
|
46
46
|
import {
|
|
47
47
|
HarnessConfigError,
|
|
@@ -14,6 +14,7 @@ declare const file: z.ZodObject<{
|
|
|
14
14
|
operation: z.ZodOptional<z.ZodEnum<{
|
|
15
15
|
create: "create";
|
|
16
16
|
delete: "delete";
|
|
17
|
+
restore: "restore";
|
|
17
18
|
update: "update";
|
|
18
19
|
}>>;
|
|
19
20
|
}, z.core.$strict>;
|
|
@@ -37,7 +38,7 @@ export declare function captureApprovalDiffs(state: AgentRunState, run: HarnessC
|
|
|
37
38
|
afterDigest: string | null;
|
|
38
39
|
beforeMode?: number | undefined;
|
|
39
40
|
afterMode?: number | undefined;
|
|
40
|
-
operation?: "create" | "delete" | "update" | undefined;
|
|
41
|
+
operation?: "create" | "delete" | "restore" | "update" | undefined;
|
|
41
42
|
}[];
|
|
42
43
|
}[];
|
|
43
44
|
/** Only expose saved content when exact journal effects certify every file. */
|
|
@@ -10,7 +10,7 @@ export interface ApprovalPreviewFile {
|
|
|
10
10
|
afterDigest: string | null;
|
|
11
11
|
beforeMode?: number;
|
|
12
12
|
afterMode?: number;
|
|
13
|
-
operation?: "create" | "update" | "delete";
|
|
13
|
+
operation?: "create" | "update" | "delete" | "restore";
|
|
14
14
|
}
|
|
15
15
|
export type ApprovalFilePreview = {
|
|
16
16
|
status: "complete";
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/** Opt-in approval policy. Manual is the default. Always-ask reasons are checked before any mode or allowlist. */
|
|
2
|
+
export declare const AUTO_APPROVE_MODES: readonly ["manual", "auto-edits", "auto-limits"];
|
|
3
|
+
export type AutoApproveMode = (typeof AUTO_APPROVE_MODES)[number];
|
|
4
|
+
export interface AutoApprovePolicy {
|
|
5
|
+
mode: AutoApproveMode;
|
|
6
|
+
commandAllowlist: readonly string[];
|
|
7
|
+
rootDir: string;
|
|
8
|
+
overLimit?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface ApprovalPath {
|
|
11
|
+
path: string;
|
|
12
|
+
operation?: "create" | "update" | "delete" | "move" | "restore";
|
|
13
|
+
}
|
|
14
|
+
export interface ApprovalFacts {
|
|
15
|
+
name: string;
|
|
16
|
+
paths: readonly ApprovalPath[];
|
|
17
|
+
commands: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
export type AskReason = "manual" | "not-an-edit" | "not-allowlisted" | "unproven-path" | "network" | "delete-outside" | "write-outside" | "secret" | "git-push" | "package-publish" | "over-limit";
|
|
20
|
+
export type ClassifyResult = {
|
|
21
|
+
decision: "ask";
|
|
22
|
+
reason: AskReason;
|
|
23
|
+
} | {
|
|
24
|
+
decision: "auto";
|
|
25
|
+
reason: "edit-in-root" | "allowlisted-command";
|
|
26
|
+
};
|
|
27
|
+
export interface ApprovalConfigFile {
|
|
28
|
+
mode: AutoApproveMode;
|
|
29
|
+
commandAllowlist: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface AutoApprovalSnapshot {
|
|
32
|
+
path: string;
|
|
33
|
+
before: string | null;
|
|
34
|
+
after: string | null;
|
|
35
|
+
undoable: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface AutoApprovalAuditEntry {
|
|
38
|
+
id: string;
|
|
39
|
+
approvalId: string;
|
|
40
|
+
name: string;
|
|
41
|
+
mode: Exclude<AutoApproveMode, "manual">;
|
|
42
|
+
reason: string;
|
|
43
|
+
timestamp: string;
|
|
44
|
+
snapshots: AutoApprovalSnapshot[];
|
|
45
|
+
}
|
|
46
|
+
export interface PublicAutoApproval {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
mode: Exclude<AutoApproveMode, "manual">;
|
|
50
|
+
reason: string;
|
|
51
|
+
timestamp: string;
|
|
52
|
+
paths: string[];
|
|
53
|
+
undoable: boolean;
|
|
54
|
+
}
|
|
55
|
+
export declare const approvalConfigPath: (rootDir: string) => string;
|
|
56
|
+
export declare const autoApprovalLogPath: (rootDir: string) => string;
|
|
57
|
+
export declare const isAutoApproveMode: (value: string) => value is AutoApproveMode;
|
|
58
|
+
/** Exact executable names only. Wildcards, paths and shell syntax are rejected. */
|
|
59
|
+
export declare const parseAllowlist: (entries: readonly string[]) => string[];
|
|
60
|
+
export declare const parseApprovalConfig: (text: string) => ApprovalConfigFile;
|
|
61
|
+
export declare const resolveAutoApprovePolicy: (input: {
|
|
62
|
+
rootDir: string;
|
|
63
|
+
overLimit?: boolean;
|
|
64
|
+
file?: ApprovalConfigFile | null;
|
|
65
|
+
cliMode?: AutoApproveMode;
|
|
66
|
+
cliAllow?: readonly string[];
|
|
67
|
+
sessionMode?: AutoApproveMode;
|
|
68
|
+
sessionAllow?: readonly string[];
|
|
69
|
+
}) => AutoApprovePolicy;
|
|
70
|
+
export declare const isInsideRoot: (rootDir: string, candidate: string) => boolean;
|
|
71
|
+
export declare const isSecretPath: (candidate: string) => boolean;
|
|
72
|
+
/** Always-ask is decided before mode and before the command allowlist. There is no force flag. */
|
|
73
|
+
export declare const classifyApproval: (facts: ApprovalFacts, policy: AutoApprovePolicy) => ClassifyResult;
|
|
74
|
+
export declare const approvalFacts: (name: string, argumentsText: string) => ApprovalFacts;
|
|
75
|
+
/** A whole pending batch auto-resolves only when every item is auto. One always-ask item keeps the batch for a person. */
|
|
76
|
+
export declare const decideBatch: (items: readonly {
|
|
77
|
+
name?: string;
|
|
78
|
+
arguments?: string;
|
|
79
|
+
}[], policy: AutoApprovePolicy) => {
|
|
80
|
+
auto: true;
|
|
81
|
+
results: {
|
|
82
|
+
decision: "auto";
|
|
83
|
+
reason: "edit-in-root" | "allowlisted-command";
|
|
84
|
+
}[];
|
|
85
|
+
reason?: never;
|
|
86
|
+
} | {
|
|
87
|
+
results?: never;
|
|
88
|
+
auto: false;
|
|
89
|
+
reason: AskReason;
|
|
90
|
+
};
|
|
91
|
+
export declare const snapshotText: (bytes: Buffer | null) => {
|
|
92
|
+
text: null;
|
|
93
|
+
undoable: boolean;
|
|
94
|
+
} | {
|
|
95
|
+
text: string;
|
|
96
|
+
undoable: boolean;
|
|
97
|
+
};
|
|
98
|
+
export declare const buildSnapshots: (argumentsText: string, read: (relativePath: string) => {
|
|
99
|
+
text: string | null;
|
|
100
|
+
undoable: boolean;
|
|
101
|
+
}) => AutoApprovalSnapshot[];
|
|
102
|
+
export declare const planUndo: (entry: AutoApprovalAuditEntry, current: ReadonlyMap<string, string | null>) => {
|
|
103
|
+
ok: false;
|
|
104
|
+
reason: string;
|
|
105
|
+
writes?: never;
|
|
106
|
+
} | {
|
|
107
|
+
reason?: never;
|
|
108
|
+
ok: true;
|
|
109
|
+
writes: {
|
|
110
|
+
path: string;
|
|
111
|
+
contents: string | null;
|
|
112
|
+
}[];
|
|
113
|
+
};
|
|
114
|
+
export declare const publicAutoApproval: (entry: AutoApprovalAuditEntry) => PublicAutoApproval;
|
|
115
|
+
export declare const readAutoApprovals: (rootDir: string) => Promise<AutoApprovalAuditEntry[]>;
|
|
116
|
+
export declare const appendAutoApproval: (rootDir: string, entry: AutoApprovalAuditEntry) => Promise<void>;
|
|
117
|
+
export declare const loadApprovalConfig: (rootDir: string) => Promise<ApprovalConfigFile>;
|
|
118
|
+
export declare const writeApprovalConfig: (rootDir: string, config: ApprovalConfigFile) => Promise<void>;
|
|
119
|
+
export declare const createAutoApprovalEntry: (input: {
|
|
120
|
+
approvalId: string;
|
|
121
|
+
name: string;
|
|
122
|
+
mode: Exclude<AutoApproveMode, "manual">;
|
|
123
|
+
reason: string;
|
|
124
|
+
snapshots: AutoApprovalSnapshot[];
|
|
125
|
+
}) => AutoApprovalAuditEntry;
|
|
126
|
+
export declare const readWorkspaceSnapshot: (rootDir: string, relativePath: string) => Promise<{
|
|
127
|
+
text: string | null;
|
|
128
|
+
undoable: boolean;
|
|
129
|
+
}>;
|
|
130
|
+
export declare const revertAutoApproval: (rootDir: string, id: string) => Promise<{
|
|
131
|
+
ok: false;
|
|
132
|
+
reason: string;
|
|
133
|
+
writes?: never;
|
|
134
|
+
} | {
|
|
135
|
+
ok: true;
|
|
136
|
+
paths: string[];
|
|
137
|
+
}>;
|
package/dist/audit/index.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
exportHarnessGovernanceReport,
|
|
3
3
|
harnessGovernanceReportSchema
|
|
4
|
-
} from "../index-
|
|
5
|
-
import"../index-
|
|
4
|
+
} from "../index-zrz4rs7p.js";
|
|
5
|
+
import"../index-yx52bt4a.js";
|
|
6
6
|
import {
|
|
7
7
|
APPROVAL_HISTORY_KEY,
|
|
8
8
|
approvalDecisionViews,
|
|
9
9
|
harnessPolicyDecisionEventSchema
|
|
10
|
-
} from "../index-
|
|
10
|
+
} from "../index-bt2p8x7r.js";
|
|
11
11
|
import {
|
|
12
12
|
TASK_BUDGET_ACCOUNT_KEY,
|
|
13
13
|
TaskBudget,
|
|
14
14
|
USAGE_LEDGER_KEY,
|
|
15
15
|
UsageLedger,
|
|
16
16
|
inspectUsageLedger
|
|
17
|
-
} from "../index-
|
|
17
|
+
} from "../index-fqqz1yt8.js";
|
|
18
18
|
import {
|
|
19
19
|
HARNESS_VERSION
|
|
20
|
-
} from "../index-
|
|
20
|
+
} from "../index-rz7wmp71.js";
|
|
21
21
|
import {
|
|
22
22
|
readRegularFileNoFollow
|
|
23
|
-
} from "../index-
|
|
23
|
+
} from "../index-6dxrbnxm.js";
|
|
24
24
|
import"../index-bpc596v3.js";
|
|
25
25
|
import"../index-fm84men1.js";
|
|
26
26
|
import"../index-1bx83sw4.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
exportHarnessGovernanceReport,
|
|
3
3
|
harnessGovernanceReportSchema
|
|
4
|
-
} from "./cli-entry-
|
|
4
|
+
} from "./cli-entry-z1pbjrg4.js";
|
|
5
5
|
import {
|
|
6
6
|
APPROVAL_HISTORY_KEY,
|
|
7
7
|
CliUsageError,
|
|
@@ -17,10 +17,10 @@ import {
|
|
|
17
17
|
openHarnessPersistence,
|
|
18
18
|
readRegularFileNoFollow,
|
|
19
19
|
validateStateDirectory
|
|
20
|
-
} from "./cli-entry-
|
|
20
|
+
} from "./cli-entry-6amx4mcc.js";
|
|
21
21
|
import {
|
|
22
22
|
HARNESS_VERSION
|
|
23
|
-
} from "./cli-entry-
|
|
23
|
+
} from "./cli-entry-10th5awp.js";
|
|
24
24
|
import {
|
|
25
25
|
resolveHarnessConfig
|
|
26
26
|
} from "./cli-entry-hdtfef27.js";
|
|
@@ -61,12 +61,14 @@ import {
|
|
|
61
61
|
withTemporaryHarnessProfiles,
|
|
62
62
|
workspaceCheckpointSchema,
|
|
63
63
|
workspaceRestoreOperationSchema
|
|
64
|
-
} from "./cli-entry-
|
|
64
|
+
} from "./cli-entry-4g2ewcnw.js";
|
|
65
65
|
import {
|
|
66
66
|
exportHarnessGovernanceReport,
|
|
67
67
|
renderHarnessGovernanceMarkdown
|
|
68
|
-
} from "./cli-entry-
|
|
68
|
+
} from "./cli-entry-z1pbjrg4.js";
|
|
69
69
|
import {
|
|
70
|
+
BUDGET_LEDGER_NAMESPACE,
|
|
71
|
+
BUDGET_OWNER_NAMESPACE_KEY,
|
|
70
72
|
CLI_CHANGES_COMMANDS,
|
|
71
73
|
CLI_COMMANDS,
|
|
72
74
|
CLI_JSON_SCHEMA_VERSION,
|
|
@@ -87,6 +89,7 @@ import {
|
|
|
87
89
|
Workspace,
|
|
88
90
|
applyCliProfile,
|
|
89
91
|
assertTaskBudgetBackupLinks,
|
|
92
|
+
budgetLedgerNamespace,
|
|
90
93
|
cancelHarnessRun,
|
|
91
94
|
canonicalizeChangeEnvelope,
|
|
92
95
|
changeEnvelopePreconditionsSchema,
|
|
@@ -122,14 +125,14 @@ import {
|
|
|
122
125
|
updateCliProfile,
|
|
123
126
|
validateStateDirectory,
|
|
124
127
|
verifyChangeEnvelope
|
|
125
|
-
} from "./cli-entry-
|
|
128
|
+
} from "./cli-entry-6amx4mcc.js";
|
|
126
129
|
import {
|
|
127
130
|
BUN_ENGINE_RANGE,
|
|
128
131
|
HARNESS_VERSION,
|
|
129
132
|
NODE_ENGINE_RANGE,
|
|
130
133
|
formatCliHelp,
|
|
131
134
|
shortCliHelp
|
|
132
|
-
} from "./cli-entry-
|
|
135
|
+
} from "./cli-entry-10th5awp.js";
|
|
133
136
|
import {
|
|
134
137
|
DEFAULT_PROVIDER_REGISTRY,
|
|
135
138
|
HARNESS_SUBAGENT_PROFILES,
|
|
@@ -3191,7 +3194,8 @@ var coordinatorIds = (runs) => new Set(runs.flatMap(({ state }) => {
|
|
|
3191
3194
|
var validateBudgetLedger = (config, run, identities) => {
|
|
3192
3195
|
const state = validatedRunState(run.state, `Budget ledger ${run.key}`);
|
|
3193
3196
|
const identity = state.metadata?.budgetIdentity;
|
|
3194
|
-
|
|
3197
|
+
const ownerNamespace = config.scope.namespace;
|
|
3198
|
+
if (!ownerNamespace || state.scope?.namespace !== budgetLedgerNamespace(ownerNamespace) || state.metadata?.[BUDGET_OWNER_NAMESPACE_KEY] !== ownerNamespace || state.scope?.tenantId !== config.scope.tenantId || (state.scope?.userId ?? undefined) !== (config.scope.userId ?? undefined) || state.provider !== "zhivex" || state.modelId !== "budget-coordinator" || state.metadata?.budgetCoordinator !== true || typeof identity !== "string" || !identities.has(identity) || !/^budget_[a-f0-9]{64}$/.test(state.runId) || !sdkRunKeyMatches(run.key, state.scope, state.runId)) {
|
|
3195
3199
|
throw new HarnessStateConflictError("Budget ledger is not bound to an exported run and durable scope.");
|
|
3196
3200
|
}
|
|
3197
3201
|
assertTerminalState(state, `Budget ledger ${run.key}`);
|
|
@@ -3325,7 +3329,9 @@ var readPayload = async (config, recordedWorkspace, accessLease) => {
|
|
|
3325
3329
|
const metadata = state.metadata;
|
|
3326
3330
|
if (typeof metadata?.budgetIdentity !== "string" || !identities.has(metadata.budgetIdentity)) {
|
|
3327
3331
|
const scope = state.scope;
|
|
3328
|
-
|
|
3332
|
+
const sameTenant = scope?.tenantId === config.scope.tenantId && (scope?.userId ?? undefined) === (config.scope.userId ?? undefined);
|
|
3333
|
+
const boundNamespace = config.scope.namespace ? budgetLedgerNamespace(config.scope.namespace) : undefined;
|
|
3334
|
+
if (sameTenant && (scope?.namespace === BUDGET_LEDGER_NAMESPACE || scope?.namespace === boundNamespace)) {
|
|
3329
3335
|
throw new HarnessStateConflictError("An unlinked shared budget ledger cannot be safely assigned to this backup scope; retain the original database.");
|
|
3330
3336
|
}
|
|
3331
3337
|
return [];
|
|
@@ -4085,7 +4091,7 @@ var main = async (argv = process.argv.slice(2)) => {
|
|
|
4085
4091
|
parsedOptions = { ...parsedOptions, prompt: await readStdinTask() };
|
|
4086
4092
|
}
|
|
4087
4093
|
if (parsedOptions.serviceFile) {
|
|
4088
|
-
const { runServiceCli } = await import("./service-client-cli-
|
|
4094
|
+
const { runServiceCli } = await import("./service-client-cli-pp5z4dmf.js");
|
|
4089
4095
|
await runServiceCli(parsedOptions, annotateCliStreamError);
|
|
4090
4096
|
return;
|
|
4091
4097
|
}
|
|
@@ -4150,7 +4156,7 @@ var main = async (argv = process.argv.slice(2)) => {
|
|
|
4150
4156
|
return;
|
|
4151
4157
|
case "export-audit":
|
|
4152
4158
|
case "verify-audit": {
|
|
4153
|
-
const { auditPackCli } = await import("./audit-pack-
|
|
4159
|
+
const { auditPackCli } = await import("./audit-pack-fckpqfsb.js");
|
|
4154
4160
|
await auditPackCli(options);
|
|
4155
4161
|
return;
|
|
4156
4162
|
}
|
|
@@ -444,7 +444,7 @@ Use zhx help all for the full reference and exit codes.`;
|
|
|
444
444
|
// package.json
|
|
445
445
|
var package_default = {
|
|
446
446
|
name: "@zhivex-ai/harness",
|
|
447
|
-
version: "1.
|
|
447
|
+
version: "1.6.2",
|
|
448
448
|
description: "Governed, provider-portable runtime for coding agents with durable approvals and isolated repository execution.",
|
|
449
449
|
type: "module",
|
|
450
450
|
license: "MIT",
|
|
@@ -544,6 +544,7 @@ var package_default = {
|
|
|
544
544
|
"LICENSE",
|
|
545
545
|
"docs/CHANGE_ENVELOPES.md",
|
|
546
546
|
"docs/CLI.md",
|
|
547
|
+
"docs/AUTO_APPROVE.md",
|
|
547
548
|
"docs/WEB_LIMITS.md",
|
|
548
549
|
"docs/CODE_RELEASE.md",
|
|
549
550
|
"docs/CODE_WEB_TASKS.md",
|
|
@@ -660,26 +661,26 @@ var package_default = {
|
|
|
660
661
|
"smoke:mcp:installed": "bun run build && bun scripts/mcp-installed-smoke.ts"
|
|
661
662
|
},
|
|
662
663
|
dependencies: {
|
|
663
|
-
"@zhivex-ai/agents": "1.
|
|
664
|
-
"@zhivex-ai/anthropic": "0.
|
|
665
|
-
"@zhivex-ai/azure-openai": "0.
|
|
666
|
-
"@zhivex-ai/bedrock": "2.0
|
|
667
|
-
"@zhivex-ai/core": "1.
|
|
668
|
-
"@zhivex-ai/gemini": "0.
|
|
669
|
-
"@zhivex-ai/meta": "0.
|
|
670
|
-
"@zhivex-ai/openai": "0.
|
|
671
|
-
"@zhivex-ai/qwen": "0.
|
|
672
|
-
"@zhivex-ai/vertex": "1.
|
|
673
|
-
"google-auth-library": "11.1
|
|
674
|
-
zod: "4.6.
|
|
664
|
+
"@zhivex-ai/agents": "1.12.0",
|
|
665
|
+
"@zhivex-ai/anthropic": "0.15.0",
|
|
666
|
+
"@zhivex-ai/azure-openai": "0.8.0",
|
|
667
|
+
"@zhivex-ai/bedrock": "2.1.0",
|
|
668
|
+
"@zhivex-ai/core": "1.36.0",
|
|
669
|
+
"@zhivex-ai/gemini": "0.14.0",
|
|
670
|
+
"@zhivex-ai/meta": "0.3.0",
|
|
671
|
+
"@zhivex-ai/openai": "0.17.0",
|
|
672
|
+
"@zhivex-ai/qwen": "0.18.0",
|
|
673
|
+
"@zhivex-ai/vertex": "1.3.0",
|
|
674
|
+
"google-auth-library": "11.3.1",
|
|
675
|
+
zod: "4.6.7"
|
|
675
676
|
},
|
|
676
677
|
overrides: {
|
|
677
|
-
"@zhivex-ai/core": "1.
|
|
678
|
+
"@zhivex-ai/core": "1.36.0"
|
|
678
679
|
},
|
|
679
680
|
devDependencies: {
|
|
680
681
|
"@agentclientprotocol/sdk": "1.8.0",
|
|
681
682
|
"@modelcontextprotocol/server": "2.3.1",
|
|
682
|
-
"@types/bun": "1.4.
|
|
683
|
+
"@types/bun": "1.4.3",
|
|
683
684
|
"@types/node": "^26.6.5",
|
|
684
685
|
typescript: "7.0.2",
|
|
685
686
|
"typescript-compiler-api": "npm:typescript@6.0.3"
|
|
@@ -59,6 +59,7 @@ import {
|
|
|
59
59
|
inspectTaskMonetaryUsage,
|
|
60
60
|
inspectUsageLedger,
|
|
61
61
|
isHardIgnored,
|
|
62
|
+
isReservedBudgetNamespace,
|
|
62
63
|
measureContext,
|
|
63
64
|
moveFileInputSchema,
|
|
64
65
|
nextTaskAcceptanceLedger,
|
|
@@ -96,10 +97,10 @@ import {
|
|
|
96
97
|
withWorkspaceMutation,
|
|
97
98
|
workBudgetReached,
|
|
98
99
|
workspaceFilePathSchema
|
|
99
|
-
} from "./cli-entry-
|
|
100
|
+
} from "./cli-entry-6amx4mcc.js";
|
|
100
101
|
import {
|
|
101
102
|
HARNESS_VERSION
|
|
102
|
-
} from "./cli-entry-
|
|
103
|
+
} from "./cli-entry-10th5awp.js";
|
|
103
104
|
import {
|
|
104
105
|
DEFAULT_PROVIDER_REGISTRY,
|
|
105
106
|
HARNESS_CONFIG_SCHEMA_VERSION,
|
|
@@ -4978,6 +4979,7 @@ var record = (value) => value !== null && typeof value === "object" && !Array.is
|
|
|
4978
4979
|
var LOCAL_TOOLS = LOCAL_TOOL_NAMES;
|
|
4979
4980
|
var MAX_USER_STEERING = 10;
|
|
4980
4981
|
var CONTEXT_PRIORITY = "Latest user > chronological user steering > historical objective. Assistant never overrides user facts. Questions retain task.";
|
|
4982
|
+
var EARLIER = "[before later user messages] ";
|
|
4981
4983
|
var summarizeHarnessMessages = (messages, maxCharacters = 4000) => {
|
|
4982
4984
|
const redaction = createRedactionPolicy3({ includeEmails: true });
|
|
4983
4985
|
const clean = (text, limit = 512) => redaction.redactText(text).replace(/\bBearer\s+\S+/gi, "Bearer [REDACTED]").replace(/\b([A-Z][A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD)|api[_-]?key|access[_-]?token|password)\s*([=:])\s*(?:"[^"]*"|'[^']*'|\S+)/gi, "$1$2[REDACTED]").replace(/\b(?:sk|ghp|gho|github_pat)-[A-Za-z0-9_-]{8,}\b/g, "[REDACTED]").replace(/\s+/g, " ").trim().slice(0, limit);
|
|
@@ -5003,6 +5005,12 @@ var summarizeHarnessMessages = (messages, maxCharacters = 4000) => {
|
|
|
5003
5005
|
omitted = true;
|
|
5004
5006
|
}
|
|
5005
5007
|
};
|
|
5008
|
+
const markRecentEarlier = () => {
|
|
5009
|
+
const marked = recent.map((value) => value.startsWith(EARLIER) ? value : `${EARLIER}${value}`);
|
|
5010
|
+
recent.length = 0;
|
|
5011
|
+
for (const value of marked)
|
|
5012
|
+
add(recent, value, 4);
|
|
5013
|
+
};
|
|
5006
5014
|
const rememberObservation = (tool2, detail) => {
|
|
5007
5015
|
if (typeof tool2 !== "string" || !LOCAL_TOOLS.has(tool2) || typeof detail !== "string")
|
|
5008
5016
|
return;
|
|
@@ -5120,6 +5128,7 @@ var summarizeHarnessMessages = (messages, maxCharacters = 4000) => {
|
|
|
5120
5128
|
objective = text;
|
|
5121
5129
|
if (historicalObjective)
|
|
5122
5130
|
add(steering, text, MAX_USER_STEERING);
|
|
5131
|
+
markRecentEarlier();
|
|
5123
5132
|
} else
|
|
5124
5133
|
add(recent, `${message.role}: ${text}`, 4);
|
|
5125
5134
|
} else if (part.type === "tool-call") {
|
|
@@ -6394,7 +6403,7 @@ var projectMemoryBinding = (workspace, scope) => {
|
|
|
6394
6403
|
segment(scope.userId);
|
|
6395
6404
|
if (scope.namespace !== undefined)
|
|
6396
6405
|
segment(scope.namespace);
|
|
6397
|
-
if (scope.namespace
|
|
6406
|
+
if (isReservedBudgetNamespace(scope.namespace))
|
|
6398
6407
|
throw new HarnessConfigError("Reserved memory namespace.");
|
|
6399
6408
|
const key = (kind, value) => createHash10("sha256").update(kind).update("\x00").update(value).digest("hex");
|
|
6400
6409
|
const workspaceKey = key("workspace", workspace);
|
|
@@ -6720,7 +6729,8 @@ var resolvers = {
|
|
|
6720
6729
|
const parsed = moveFileInputSchema.parse(input);
|
|
6721
6730
|
return [parsed.source, parsed.destination];
|
|
6722
6731
|
},
|
|
6723
|
-
quarantine_file: (input) => [quarantineFileInputSchema.parse(input).path]
|
|
6732
|
+
quarantine_file: (input) => [quarantineFileInputSchema.parse(input).path],
|
|
6733
|
+
restore_file: (input) => [restoreFileInputSchema.parse(input).destination]
|
|
6724
6734
|
};
|
|
6725
6735
|
var validateBuiltinToolPolicy = (policy, tools) => {
|
|
6726
6736
|
for (const rule of policy.rules)
|
|
@@ -8153,7 +8163,7 @@ var createWorkspaceTools = (workspace, allowedChecks) => ({
|
|
|
8153
8163
|
}),
|
|
8154
8164
|
restore_file: tool4({
|
|
8155
8165
|
name: "restore_file",
|
|
8156
|
-
description: "Restore a quarantined file to
|
|
8166
|
+
description: "Restore a quarantined file to the required destination after the reviewed expectedDigest matches the quarantined bytes. Restore does not fall back to the original path and never overwrites an existing file.",
|
|
8157
8167
|
schema: restoreFileInputSchema,
|
|
8158
8168
|
...mutationApproval,
|
|
8159
8169
|
execute: async (input, context) => serializeJsonValue6(editContractDocument("restore-result", await (harnessExecutionSession(context)?.workspace ?? workspace).restoreQuarantined(input)))
|