@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.
Files changed (76) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +1 -1
  3. package/SUPPORT.md +1 -1
  4. package/contracts/stable-api-signatures.json +7 -7
  5. package/dist/acp-cli.js +10 -10
  6. package/dist/approvals/approval-diff.d.ts +2 -1
  7. package/dist/approvals/approval-preview.d.ts +1 -1
  8. package/dist/approvals/auto-approve.d.ts +137 -0
  9. package/dist/audit/index.js +6 -6
  10. package/dist/{audit-pack-e4vaq7np.js → audit-pack-fckpqfsb.js} +3 -3
  11. package/dist/{cli-1cf4dcnj.js → cli-84en174d.js} +14 -8
  12. package/dist/{cli-entry-3s63zn4w.js → cli-entry-10th5awp.js} +16 -15
  13. package/dist/{cli-entry-a890x3kq.js → cli-entry-4g2ewcnw.js} +15 -5
  14. package/dist/{cli-entry-7f0cen32.js → cli-entry-6amx4mcc.js} +209 -68
  15. package/dist/{cli-entry-rgs6bxmy.js → cli-entry-z1pbjrg4.js} +2 -2
  16. package/dist/cli.js +2 -2
  17. package/dist/compat/code-support.js +8 -8
  18. package/dist/engine/acp.js +11 -11
  19. package/dist/engine/client.js +10 -10
  20. package/dist/engine/desktop-state-v1.js +6 -6
  21. package/dist/engine/index.js +15 -15
  22. package/dist/engine/mcp-stdio-v1.js +5 -5
  23. package/dist/engine/service.js +11 -11
  24. package/dist/hostile-repository-demo.js +235 -84
  25. package/dist/{index-mv8sb1ns.js → index-1pn0ecs4.js} +55 -13
  26. package/dist/{index-dtb2c6ds.js → index-2r4f0p4n.js} +2 -2
  27. package/dist/{index-6599mpmy.js → index-4mn6m3bq.js} +3 -3
  28. package/dist/{index-xdbkcccf.js → index-6dxrbnxm.js} +2 -2
  29. package/dist/{index-crta5wzv.js → index-74f9yhfh.js} +4 -4
  30. package/dist/{index-f6mqa5gk.js → index-amjttjaj.js} +11 -39
  31. package/dist/{index-wm9xeq1n.js → index-bt2p8x7r.js} +1 -1
  32. package/dist/{index-sk3cap35.js → index-eps3c3g6.js} +1 -1
  33. package/dist/{index-zxg4ve4j.js → index-fqqz1yt8.js} +77 -4
  34. package/dist/{index-02pqtbbg.js → index-paf7z8kn.js} +10 -10
  35. package/dist/{index-0zs2dz26.js → index-pf73y4gt.js} +18 -9
  36. package/dist/{index-74kkpyqk.js → index-rgqzdgv6.js} +12 -6
  37. package/dist/{index-4fx5f3k5.js → index-rz7wmp71.js} +16 -15
  38. package/dist/{index-d9zkmhz3.js → index-w0m1nckc.js} +127 -28
  39. package/dist/{index-sstgcsr0.js → index-yx52bt4a.js} +1 -1
  40. package/dist/{index-j6zxnc8m.js → index-zrz4rs7p.js} +5 -5
  41. package/dist/index.js +14 -14
  42. package/dist/integrations/mcp-stdio-tools.d.ts +4 -1
  43. package/dist/providers/bedrock.d.ts +1 -1
  44. package/dist/review/reveal-invisible.d.ts +13 -0
  45. package/dist/runtime/budget-ledger-scope.d.ts +14 -0
  46. package/dist/service-cli.js +11 -11
  47. package/dist/{service-client-cli-eqrdc9zq.js → service-client-cli-pp5z4dmf.js} +4 -4
  48. package/dist/tools/workspace.d.ts +2 -2
  49. package/dist/verify-historical-migrations.js +240 -86
  50. package/dist/workspace/edit-contracts.d.ts +2 -2
  51. package/dist/workspace/path-policy.d.ts +2 -1
  52. package/dist/workspace/text-integrity.d.ts +19 -0
  53. package/dist/workspace/workspace.d.ts +21 -3
  54. package/dist/zhx.js +2 -2
  55. package/docs/AUTO_APPROVE.md +51 -0
  56. package/docs/AZURE_OPENAI.md +4 -4
  57. package/docs/BEDROCK.md +4 -4
  58. package/docs/CLI.md +13 -0
  59. package/docs/CODE_RELEASE.md +36 -6
  60. package/docs/CODE_WEB_TASKS.md +1 -1
  61. package/docs/CREDENTIALS.md +1 -1
  62. package/docs/DURABLE_OPERATIONS.md +1 -1
  63. package/docs/ENGINE_API.md +1 -1
  64. package/docs/EXTENSIBILITY.md +7 -3
  65. package/docs/FIRST_USE.md +6 -6
  66. package/docs/MINIMUM_TASK_AUTHORITY.md +5 -5
  67. package/docs/PROJECT_MEMORY.md +1 -1
  68. package/docs/PUBLIC_SECURITY.md +14 -1
  69. package/docs/REPOSITORY_EDITING.md +1 -1
  70. package/docs/TOOL_POLICY.md +7 -1
  71. package/docs/VERTEX.md +2 -2
  72. package/docs/WEB_LIMITS.md +2 -2
  73. package/docs/adr/0002-isolated-mcp-stdio.md +2 -2
  74. package/evaluations/representative-assembly-matrix.json +37 -1
  75. package/examples/README.md +3 -3
  76. package/package.json +16 -15
@@ -20,7 +20,7 @@ import {
20
20
  taskAcceptanceChecks,
21
21
  validateEditProposal,
22
22
  workspaceFilePathSchema
23
- } from "./index-xdbkcccf.js";
23
+ } from "./index-6dxrbnxm.js";
24
24
  import {
25
25
  HarnessError,
26
26
  HarnessExecutionError,
@@ -403,13 +403,62 @@ import { createHash as createHash2, randomUUID } from "node:crypto";
403
403
  import { link, lstat as lstat3, mkdir as mkdir2, open as open2, readdir, realpath as realpath2, rename, stat, unlink } from "node:fs/promises";
404
404
  import path3 from "node:path";
405
405
 
406
+ // src/workspace/text-integrity.ts
407
+ var controlLabel = (code) => code === 0 ? "NUL byte" : `U+${code.toString(16).padStart(4, "0")}`;
408
+ var firstDisallowedControl = (text) => {
409
+ let line = 1;
410
+ for (let index = 0;index < text.length; index += 1) {
411
+ const code = text.charCodeAt(index);
412
+ if (code === 10) {
413
+ line += 1;
414
+ continue;
415
+ }
416
+ if (code === 9 || code === 13)
417
+ continue;
418
+ if (code < 32 || code === 127 || code >= 128 && code <= 159)
419
+ return { line, label: controlLabel(code) };
420
+ }
421
+ return;
422
+ };
423
+ var firstDisallowedControlBytes = (bytes) => {
424
+ let line = 1;
425
+ for (let index = 0;index < bytes.length; index += 1) {
426
+ const code = bytes[index] ?? 0;
427
+ if (code === 10) {
428
+ line += 1;
429
+ continue;
430
+ }
431
+ if (code === 9 || code === 13)
432
+ continue;
433
+ if (code < 32 || code === 127)
434
+ return { line, label: controlLabel(code) };
435
+ }
436
+ return;
437
+ };
438
+ var refuseControlMessage = (hit) => `Refusing to write a control byte into a text file: ${hit.label} at L${hit.line}. The file was not changed. Remove the control byte.`;
439
+ var binaryAfterEditMessage = (hit) => `file is binary after edit: ${hit.label} at L${hit.line}. The edit was reverted. Read the file again before retrying.`;
440
+ var textGuards = {
441
+ beforeWrite(content, allowControlBytes) {
442
+ if (allowControlBytes)
443
+ return;
444
+ const problem = firstDisallowedControl(content);
445
+ if (problem)
446
+ throw new HarnessWorkspaceError(refuseControlMessage(problem));
447
+ },
448
+ afterWrite(bytes, allowControlBytes) {
449
+ if (allowControlBytes)
450
+ return;
451
+ return firstDisallowedControlBytes(bytes);
452
+ }
453
+ };
454
+
406
455
  // src/workspace/path-policy.ts
407
456
  var HARD_IGNORES = new Set([".git", ".next", ".turbo", ".zhivex-harness", "coverage", "dist", "node_modules"]);
408
457
  var isSensitiveName = (name) => {
409
- const normalized = name.toLocaleLowerCase();
458
+ const normalized = name.toLowerCase();
410
459
  return normalized === ".env" || normalized.startsWith(".env.") && normalized !== ".env.example" || normalized === ".npmrc" || normalized === "id_rsa" || normalized === "id_ed25519" || [".key", ".pem", ".p12", ".pfx"].some((extension) => normalized.endsWith(extension));
411
460
  };
412
- var isHardIgnored = (relativePath) => relativePath.split("/").some((segment) => HARD_IGNORES.has(segment.toLocaleLowerCase()) || isSensitiveName(segment));
461
+ var isHardIgnored = (relativePath) => relativePath.split("/").some((segment) => HARD_IGNORES.has(segment.toLowerCase()) || isSensitiveName(segment));
413
462
 
414
463
  // src/workspace/workspace.ts
415
464
  var IGNORE_FILES = [".gitignore", ".zhivex-harnessignore"];
@@ -689,7 +738,7 @@ class Workspace {
689
738
  throw new HarnessWorkspaceError(`The path escapes the workspace: ${relativePath}`);
690
739
  const relative = wirePath(path3.relative(this.root, candidate));
691
740
  if (relative && isHardIgnored(relative)) {
692
- const blocked = relative.split("/").find((segment) => HARD_IGNORES.has(segment.toLocaleLowerCase()) || isSensitiveName(segment));
741
+ const blocked = relative.split("/").find((segment) => HARD_IGNORES.has(segment.toLowerCase()) || isSensitiveName(segment));
693
742
  throw new HarnessWorkspaceError(`The path is protected by the harness policy: ${blocked}`);
694
743
  }
695
744
  return candidate;
@@ -732,8 +781,11 @@ class Workspace {
732
781
  maxBytes: MAX_FILE_BYTES
733
782
  });
734
783
  const { contents } = file;
735
- if (!allowBinary && contents.includes(0))
736
- throw new HarnessWorkspaceError("The file appears to be binary and cannot be read as text.");
784
+ if (!allowBinary && contents.includes(0)) {
785
+ const hit = firstDisallowedControlBytes(contents);
786
+ const where = hit ? `: ${hit.label} at L${hit.line}` : "";
787
+ throw new HarnessWorkspaceError(`The file appears to be binary and cannot be read as text${where}.`);
788
+ }
737
789
  return {
738
790
  path: wirePath(path3.relative(this.root, safe.path)),
739
791
  absolutePath: safe.path,
@@ -1400,19 +1452,23 @@ class Workspace {
1400
1452
  if (position < 0 || text.indexOf(edit.oldText, position + 1) >= 0) {
1401
1453
  throw new HarnessWorkspaceError("Replacement requires exactly one literal match; include more surrounding context.");
1402
1454
  }
1403
- return [{ path: edit.path, expectedDigest: edit.expectedDigest, content: text.slice(0, position) + edit.newText + text.slice(position + edit.oldText.length) }];
1455
+ return [{
1456
+ path: edit.path,
1457
+ expectedDigest: edit.expectedDigest,
1458
+ content: text.slice(0, position) + edit.newText + text.slice(position + edit.oldText.length)
1459
+ }];
1404
1460
  }
1405
- async applyReplacement(input) {
1461
+ async applyReplacement(input, host = {}) {
1406
1462
  const changes = await this.replacementChanges(input);
1407
- return this.applyPatch({ proposalId: createEditProposal({ changes }).proposalId, changes });
1463
+ return this.applyPatch({ proposalId: createEditProposal({ changes }).proposalId, changes }, host);
1408
1464
  }
1409
- async applyPatch(input) {
1410
- return this.applyPatchWithModes(input, new Map);
1465
+ async applyPatch(input, host = {}) {
1466
+ return this.applyPatchWithModes(input, new Map, undefined, host);
1411
1467
  }
1412
- async applyPatchWithModes(input, modes, assertActive) {
1413
- return withWorkspaceMutation(this.root, () => this.applyPatchWithModesLocked(input, modes, assertActive));
1468
+ async applyPatchWithModes(input, modes, assertActive, host = {}) {
1469
+ return withWorkspaceMutation(this.root, () => this.applyPatchWithModesLocked(input, modes, assertActive, host));
1414
1470
  }
1415
- async applyPatchWithModesLocked(input, modes, assertActive) {
1471
+ async applyPatchWithModesLocked(input, modes, assertActive, host = {}) {
1416
1472
  const proposal = validateEditProposal(input);
1417
1473
  this.checkAuditCapacity(proposal.changes.length);
1418
1474
  const targetPaths = new Set(proposal.changes.map((change) => change.path));
@@ -1457,6 +1513,7 @@ class Workspace {
1457
1513
  throw new HarnessWorkspaceError(`Stale patch mode rejected for ${change.path}: expected ${modeBinding.beforeMode.toString(8)}, found ${before.mode.toString(8)}.`);
1458
1514
  }
1459
1515
  }
1516
+ textGuards.beforeWrite(change.content, host.allowControlBytes === true);
1460
1517
  const temporary = await this.stageFile(safe.path, change.content, modeBinding?.afterMode ?? before?.mode ?? 420);
1461
1518
  prepared.push({
1462
1519
  change,
@@ -1496,6 +1553,13 @@ class Workspace {
1496
1553
  await unlink(item.temporary);
1497
1554
  }
1498
1555
  committed.push(item);
1556
+ const published = await readRegularFileNoFollow(item.target, {
1557
+ label: "The published file",
1558
+ maxBytes: MAX_FILE_BYTES
1559
+ });
1560
+ const corrupt = textGuards.afterWrite(published.contents, host.allowControlBytes === true);
1561
+ if (corrupt)
1562
+ throw new HarnessWorkspaceError(binaryAfterEditMessage(corrupt));
1499
1563
  await assertActive?.();
1500
1564
  }
1501
1565
  } catch (error) {
@@ -1672,30 +1736,65 @@ class Workspace {
1672
1736
  const audit = await this.audit({ operation: "quarantine", path: parsed.path, beforeDigest: source.digest, quarantineId });
1673
1737
  return { quarantineId, path: parsed.path, digest: source.digest, audit };
1674
1738
  }
1675
- async restoreQuarantined(input) {
1676
- return withWorkspaceMutation(this.root, () => this.restoreQuarantinedLocked(input));
1677
- }
1678
- async restoreQuarantinedLocked(input) {
1679
- const parsed = restoreFileInputSchema.parse(input);
1680
- this.checkAuditCapacity();
1739
+ async readRestorableQuarantine(quarantineId) {
1681
1740
  const directory = await this.secureQuarantineDirectory(false);
1682
1741
  let manifest;
1683
1742
  try {
1684
- const manifestFile = await this.readInternalRegularFile(path3.join(directory, `${parsed.quarantineId}.json`), "Quarantine manifest", 64 * 1024);
1743
+ const manifestFile = await this.readInternalRegularFile(path3.join(directory, `${quarantineId}.json`), "Quarantine manifest", 64 * 1024);
1685
1744
  manifest = JSON.parse(manifestFile.contents.toString("utf8"));
1686
1745
  } catch {
1687
- throw new HarnessWorkspaceError(`Quarantine entry was not found: ${parsed.quarantineId}.`);
1746
+ throw new HarnessWorkspaceError(`Quarantine entry was not found: ${quarantineId}.`);
1688
1747
  }
1689
- if (manifest.schemaVersion !== 1 || manifest.quarantineId !== parsed.quarantineId || manifest.status !== "quarantined") {
1690
- throw new HarnessWorkspaceError(`Quarantine entry is not restorable: ${parsed.quarantineId}.`);
1748
+ if (manifest.schemaVersion !== 1 || manifest.quarantineId !== quarantineId || manifest.status !== "quarantined") {
1749
+ throw new HarnessWorkspaceError(`Quarantine entry is not restorable: ${quarantineId}.`);
1691
1750
  }
1692
- const dataPath = path3.join(directory, `${parsed.quarantineId}.data`);
1751
+ const dataPath = path3.join(directory, `${quarantineId}.data`);
1693
1752
  const dataFile = await this.readInternalRegularFile(dataPath, "Quarantine payload", MAX_FILE_BYTES);
1694
1753
  const digest = digestBytes(dataFile.contents);
1695
- if (digest !== manifest.digest || parsed.expectedDigest && parsed.expectedDigest !== digest) {
1754
+ if (digest !== manifest.digest) {
1755
+ throw new HarnessWorkspaceError(`Quarantine digest mismatch: ${quarantineId}.`);
1756
+ }
1757
+ return { manifest, dataPath, dataFile, digest };
1758
+ }
1759
+ async previewRestore(input) {
1760
+ const parsed = restoreFileInputSchema.parse(input);
1761
+ const quarantined = await this.readRestorableQuarantine(parsed.quarantineId);
1762
+ if (parsed.expectedDigest !== quarantined.digest) {
1763
+ throw new HarnessWorkspaceError(`Quarantine digest mismatch: ${parsed.quarantineId}.`);
1764
+ }
1765
+ const destination = await this.safePath(parsed.destination, { allowMissing: true });
1766
+ if (destination.exists)
1767
+ throw new HarnessWorkspaceError(`Restore destination already exists: ${parsed.destination}.`);
1768
+ let after;
1769
+ try {
1770
+ after = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(quarantined.dataFile.contents);
1771
+ } catch {
1772
+ throw new HarnessWorkspaceError("Preview requires valid UTF-8 text.");
1773
+ }
1774
+ return {
1775
+ proposalId: parsed.expectedDigest,
1776
+ files: [{
1777
+ path: parsed.destination,
1778
+ expectedDigest: parsed.expectedDigest,
1779
+ before: null,
1780
+ after,
1781
+ afterDigest: quarantined.digest,
1782
+ operation: "restore"
1783
+ }]
1784
+ };
1785
+ }
1786
+ async restoreQuarantined(input) {
1787
+ return withWorkspaceMutation(this.root, () => this.restoreQuarantinedLocked(input));
1788
+ }
1789
+ async restoreQuarantinedLocked(input) {
1790
+ const parsed = restoreFileInputSchema.parse(input);
1791
+ this.checkAuditCapacity();
1792
+ const quarantined = await this.readRestorableQuarantine(parsed.quarantineId);
1793
+ if (parsed.expectedDigest !== quarantined.digest) {
1696
1794
  throw new HarnessWorkspaceError(`Quarantine digest mismatch: ${parsed.quarantineId}.`);
1697
1795
  }
1698
- const destinationPath = parsed.destination ?? manifest.originalPath;
1796
+ const { manifest, dataPath, dataFile, digest } = quarantined;
1797
+ const destinationPath = parsed.destination;
1699
1798
  const destination = await this.safePath(destinationPath, { allowMissing: true });
1700
1799
  if (destination.exists)
1701
1800
  throw new HarnessWorkspaceError(`Restore destination already exists: ${destinationPath}.`);
@@ -2998,7 +3097,7 @@ var importPatch = async (runId, expectedPatchId, host, base, current, maxFileWri
2998
3097
  const rollbackErrors = [];
2999
3098
  for (const item of [...quarantined].reverse()) {
3000
3099
  try {
3001
- await host.restoreQuarantined({ quarantineId: item.quarantineId, expectedDigest: item.digest });
3100
+ await host.restoreQuarantined({ quarantineId: item.quarantineId, destination: item.path, expectedDigest: item.digest });
3002
3101
  } catch (rollbackError) {
3003
3102
  rollbackErrors.push(rollbackError);
3004
3103
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  fileDigestSchema
3
- } from "./index-xdbkcccf.js";
3
+ } from "./index-6dxrbnxm.js";
4
4
 
5
5
  // src/workspace/change-envelope.ts
6
6
  import { createHash } from "node:crypto";
@@ -1,25 +1,25 @@
1
1
  import {
2
2
  changeEnvelopeSchema,
3
3
  verifyChangeEnvelope
4
- } from "./index-sstgcsr0.js";
4
+ } from "./index-yx52bt4a.js";
5
5
  import {
6
6
  APPROVAL_HISTORY_KEY,
7
7
  approvalDecisionViews,
8
8
  harnessPolicyDecisionEventSchema
9
- } from "./index-wm9xeq1n.js";
9
+ } from "./index-bt2p8x7r.js";
10
10
  import {
11
11
  TASK_ACCEPTANCE_EVIDENCE_KEY,
12
12
  USAGE_LEDGER_KEY,
13
13
  inspectRuntimeManifest,
14
14
  inspectUsageLedger,
15
15
  readTaskAcceptanceLedger
16
- } from "./index-zxg4ve4j.js";
16
+ } from "./index-fqqz1yt8.js";
17
17
  import {
18
18
  HARNESS_VERSION
19
- } from "./index-4fx5f3k5.js";
19
+ } from "./index-rz7wmp71.js";
20
20
  import {
21
21
  taskCheckReceiptSchema
22
- } from "./index-xdbkcccf.js";
22
+ } from "./index-6dxrbnxm.js";
23
23
 
24
24
  // src/persistence/governance-report.ts
25
25
  import { createHash as createHash2 } from "node:crypto";
package/dist/index.js CHANGED
@@ -52,7 +52,7 @@ import {
52
52
  timeToSafeFixDriverResultSchema,
53
53
  timeToSafeFixLatencyStatistics,
54
54
  timeToSafeFixTaskSchema
55
- } from "./index-sk3cap35.js";
55
+ } from "./index-eps3c3g6.js";
56
56
  import {
57
57
  HARNESS_STATE_BACKUP_MAX_BYTES,
58
58
  HARNESS_STATE_BACKUP_SCHEMA_VERSION,
@@ -63,7 +63,7 @@ import {
63
63
  inspectHarnessState,
64
64
  readHarnessStateBackup,
65
65
  stateBackupBundleSchema
66
- } from "./index-74kkpyqk.js";
66
+ } from "./index-rgqzdgv6.js";
67
67
  import {
68
68
  CLI_COMMAND_OPTION_CONTRACTS,
69
69
  CLI_OPTION_DEFINITIONS,
@@ -101,7 +101,7 @@ import {
101
101
  digestChangeEnvelopeArtifact,
102
102
  externalAttestationReferenceSchema,
103
103
  verifyChangeEnvelope
104
- } from "./index-sstgcsr0.js";
104
+ } from "./index-yx52bt4a.js";
105
105
  import {
106
106
  harnessLocalCredentialsSchema,
107
107
  openHarnessActivityStore,
@@ -109,13 +109,13 @@ import {
109
109
  recoverHarnessLocalService,
110
110
  requestHarnessLocalService,
111
111
  startHarnessLocalService
112
- } from "./index-crta5wzv.js";
112
+ } from "./index-74f9yhfh.js";
113
113
  import {
114
114
  createHarnessClientAdapter
115
- } from "./index-02pqtbbg.js";
115
+ } from "./index-paf7z8kn.js";
116
116
  import {
117
117
  openWorkspaceCheckpointStore
118
- } from "./index-6599mpmy.js";
118
+ } from "./index-4mn6m3bq.js";
119
119
  import {
120
120
  DEFAULT_HARNESS_CONTEXT_MANIFEST,
121
121
  DEFAULT_HARNESS_PROJECT_INSTRUCTIONS,
@@ -154,7 +154,7 @@ import {
154
154
  runHarness,
155
155
  runHarnessReviewGroup,
156
156
  selectHarnessModel
157
- } from "./index-0zs2dz26.js";
157
+ } from "./index-pf73y4gt.js";
158
158
  import {
159
159
  HARNESS_OPERATIONS_SCHEMA_VERSION,
160
160
  HARNESS_SQLITE_FILE,
@@ -165,7 +165,7 @@ import {
165
165
  listHarnessRuns,
166
166
  migrateLegacyFileRuns,
167
167
  openHarnessPersistence
168
- } from "./index-f6mqa5gk.js";
168
+ } from "./index-amjttjaj.js";
169
169
  import {
170
170
  HARNESS_MCP_CONFIG_SCHEMA_VERSION,
171
171
  HARNESS_MCP_PERMISSIONS,
@@ -173,7 +173,7 @@ import {
173
173
  createHttpMcpClient,
174
174
  loadHarnessMcpConfiguration,
175
175
  normalizeHarnessMcpConfiguration
176
- } from "./index-dtb2c6ds.js";
176
+ } from "./index-2r4f0p4n.js";
177
177
  import {
178
178
  CliOciRuntimeAdapter,
179
179
  HARNESS_EXECUTION_ARTIFACT_SCHEMA_VERSION,
@@ -185,7 +185,7 @@ import {
185
185
  describeOciCommand,
186
186
  executionFingerprintInput,
187
187
  harnessExecutionSession
188
- } from "./index-d9zkmhz3.js";
188
+ } from "./index-w0m1nckc.js";
189
189
  import {
190
190
  BUILTIN_PROVIDER_REGISTRATIONS,
191
191
  DEFAULT_ALLOWED_CHECKS,
@@ -217,7 +217,7 @@ import {
217
217
  applyHarnessToolPolicy,
218
218
  createHarnessToolPolicy,
219
219
  harnessToolPolicySchema
220
- } from "./index-wm9xeq1n.js";
220
+ } from "./index-bt2p8x7r.js";
221
221
  import {
222
222
  HARNESS_SESSION_INDEX_FILE,
223
223
  HARNESS_SESSION_SCHEMA_VERSION,
@@ -226,12 +226,12 @@ import {
226
226
  openCliSessionStore,
227
227
  openSessionStore,
228
228
  validateStateDirectory
229
- } from "./index-zxg4ve4j.js";
229
+ } from "./index-fqqz1yt8.js";
230
230
  import {
231
231
  BUN_ENGINE_RANGE,
232
232
  HARNESS_VERSION,
233
233
  NODE_ENGINE_RANGE
234
- } from "./index-4fx5f3k5.js";
234
+ } from "./index-rz7wmp71.js";
235
235
  import {
236
236
  EDIT_CONTRACT_SCHEMA_VERSION,
237
237
  EDIT_DIGEST_ALGORITHM,
@@ -254,7 +254,7 @@ import {
254
254
  restoreFileInputSchema,
255
255
  validateEditProposal,
256
256
  workspaceFilePathSchema
257
- } from "./index-xdbkcccf.js";
257
+ } from "./index-6dxrbnxm.js";
258
258
  import {
259
259
  CLI_EVENT_SCHEMA_VERSION,
260
260
  CLI_JSON_SCHEMA_VERSION,
@@ -1,12 +1,15 @@
1
1
  import { type McpClient, type ToolSet } from '@zhivex-ai/core';
2
2
  import type { McpStdioLaunchProposal } from './mcp-stdio-admission.js';
3
3
  import { createJournaledMcpClient } from '../persistence/mcp-execution-journal.js';
4
- /** Host tool bridge. Existing agent execution supplies durable interrupt approvals. */
4
+ /** Host tool bridge. Tool results are untrusted data. Existing agent execution supplies durable interrupt approvals.
5
+ * flagEncodedSecrets is optional. Credential-bearing servers use it to mark encodings and high-entropy tokens; it does not rewrite discovery schemas. */
5
6
  export declare function createIsolatedMcpTools(options: {
6
7
  client: McpClient & {
7
8
  close(): Promise<void>;
8
9
  };
9
10
  proposal: Readonly<McpStdioLaunchProposal>;
10
11
  sensitiveValues?: readonly string[];
12
+ /** When set, tool results flag known encodings of sensitiveValues and other high-entropy encoded strings. */
13
+ flagEncodedSecrets?: boolean;
11
14
  journal?: Pick<Parameters<typeof createJournaledMcpClient>[0], 'store' | 'runId' | 'scope'>;
12
15
  }): Promise<ToolSet>;
@@ -4,7 +4,7 @@ export declare const BEDROCK_TRANSPORT_ENVIRONMENT: readonly ["AWS_REGION", "AWS
4
4
  export declare const BEDROCK_CREDENTIAL_ENVIRONMENT: readonly ["BEDROCK_API_KEY", "AWS_BEARER_TOKEN_BEDROCK"];
5
5
  /**
6
6
  * SDK matrix: Converse is Tier B and `runtime: "openai"` is Tier A.
7
- * Published `@zhivex-ai/bedrock@2.0.7` reports those labels. Converse includes
7
+ * Published `@zhivex-ai/bedrock@2.1.0` reports those labels. Converse includes
8
8
  * reasoning and `toolChoiceNone`. Harness reports the installed label and
9
9
  * does not relabel the model.
10
10
  */
@@ -0,0 +1,13 @@
1
+ export interface RevealedPiece {
2
+ text: string;
3
+ /** The text stands in for a character a terminal or browser would hide. */
4
+ mark: boolean;
5
+ }
6
+ /**
7
+ * Show control, zero-width, and bidi characters, and mark tabs and trailing whitespace.
8
+ * Newlines stay newlines so a diff line remains one row. A second pass leaves the result unchanged.
9
+ */
10
+ export declare const revealInvisiblePieces: (line: string) => RevealedPiece[];
11
+ export declare const revealInvisible: (line: string) => string;
12
+ /** Reveal each line and keep the newline structure of a whole file. */
13
+ export declare const revealInvisibleText: (value: string) => string;
@@ -0,0 +1,14 @@
1
+ import type { AgentRunStore, AgentStoreScope } from "@zhivex-ai/core";
2
+ /** SDK coordinators address ledgers with this namespace. The durable owner appends the source namespace. */
3
+ export declare const BUDGET_LEDGER_NAMESPACE = "__zhivex_budget__";
4
+ export declare const BUDGET_OWNER_NAMESPACE_KEY = "budgetOwnerNamespace";
5
+ export declare const isReservedBudgetNamespace: (namespace: string | undefined) => boolean;
6
+ /** Bind the caller's full namespace into the ledger owner. Collapsing every namespace to the SDK marker lets one tenant read another's ledger by run id. */
7
+ export declare const budgetLedgerNamespace: (namespace: string) => string;
8
+ /**
9
+ * A named source becomes `__zhivex_budget__:<namespace>`.
10
+ * An omitted namespace uses the trailing-colon owner, which `budgetLedgerNamespace` never produces, so it cannot join a named ledger.
11
+ */
12
+ export declare const budgetLedgerScope: (scope: Pick<AgentStoreScope, "tenantId" | "userId" | "namespace">) => AgentStoreScope;
13
+ /** Translate the SDK's collapsed namespace onto the bound owner before the file or SQLite store. */
14
+ export declare const bindBudgetLedgerStore: (primary: AgentRunStore, scope: AgentStoreScope, budget?: AgentRunStore) => AgentRunStore;
@@ -2,22 +2,22 @@
2
2
  import {
3
3
  recoverHarnessLocalService,
4
4
  startHarnessLocalService
5
- } from "./index-crta5wzv.js";
6
- import"./index-02pqtbbg.js";
7
- import"./index-6599mpmy.js";
5
+ } from "./index-74f9yhfh.js";
6
+ import"./index-paf7z8kn.js";
7
+ import"./index-4mn6m3bq.js";
8
8
  import {
9
9
  createHarness
10
- } from "./index-0zs2dz26.js";
11
- import"./index-f6mqa5gk.js";
12
- import"./index-dtb2c6ds.js";
13
- import"./index-d9zkmhz3.js";
10
+ } from "./index-pf73y4gt.js";
11
+ import"./index-amjttjaj.js";
12
+ import"./index-2r4f0p4n.js";
13
+ import"./index-w0m1nckc.js";
14
14
  import"./index-1265j7t2.js";
15
15
  import"./index-c39197wq.js";
16
16
  import"./index-mzydbzp8.js";
17
- import"./index-wm9xeq1n.js";
18
- import"./index-zxg4ve4j.js";
19
- import"./index-4fx5f3k5.js";
20
- import"./index-xdbkcccf.js";
17
+ import"./index-bt2p8x7r.js";
18
+ import"./index-fqqz1yt8.js";
19
+ import"./index-rz7wmp71.js";
20
+ import"./index-6dxrbnxm.js";
21
21
  import"./index-4gt045j0.js";
22
22
  import"./index-bpc596v3.js";
23
23
  import"./index-fm84men1.js";
@@ -9,17 +9,17 @@ import {
9
9
  navigateConsole,
10
10
  printPolicyInspection,
11
11
  sanitizeTerminalText
12
- } from "./cli-entry-a890x3kq.js";
12
+ } from "./cli-entry-4g2ewcnw.js";
13
13
  import {
14
14
  CLI_EVENT_SCHEMA_VERSION,
15
15
  CLI_JSON_SCHEMA_VERSION,
16
16
  changeEnvelopeSchema,
17
17
  harnessPolicyDecisionEventSchema,
18
18
  serializeStreamResult
19
- } from "./cli-entry-7f0cen32.js";
19
+ } from "./cli-entry-6amx4mcc.js";
20
20
  import {
21
21
  HARNESS_VERSION
22
- } from "./cli-entry-3s63zn4w.js";
22
+ } from "./cli-entry-10th5awp.js";
23
23
  import {
24
24
  HARNESS_ERROR_CODES,
25
25
  HARNESS_ERROR_SCHEMA_VERSION,
@@ -195,7 +195,7 @@ var harnessTaskProjectionSchema = z2.strictObject({
195
195
  // src/approvals/approval-diff.ts
196
196
  import { z as z3 } from "zod";
197
197
  var sha = z3.string().regex(/^sha256:[a-f0-9]{64}$/);
198
- var file = z3.object({ path: z3.string().max(1024), expectedDigest: sha.nullable(), before: z3.string().nullable(), after: z3.string().nullable(), afterDigest: sha.nullable(), beforeMode: z3.number().int().optional(), afterMode: z3.number().int().optional(), operation: z3.enum(["create", "update", "delete"]).optional() }).strict();
198
+ var file = z3.object({ path: z3.string().max(1024), expectedDigest: sha.nullable(), before: z3.string().nullable(), after: z3.string().nullable(), afterDigest: sha.nullable(), beforeMode: z3.number().int().optional(), afterMode: z3.number().int().optional(), operation: z3.enum(["create", "update", "delete", "restore"]).optional() }).strict();
199
199
  var archive = z3.object({ approvalId: z3.string().max(256), digest: z3.string().regex(/^[a-f0-9]{64}$/), proposalId: sha, files: z3.array(file).min(1).max(50) }).strict();
200
200
  var archives = z3.array(archive).max(512);
201
201
  var maxBytes = 2 * 1024 * 1024;
@@ -89,8 +89,8 @@ export declare const createWorkspaceTools: (workspace: Workspace, allowedChecks:
89
89
  }, z.core.$strict>, import("@zhivex-ai/core").JsonValue, unknown>;
90
90
  restore_file: import("@zhivex-ai/core").ToolDefinition<z.ZodObject<{
91
91
  quarantineId: z.ZodString;
92
- destination: z.ZodOptional<z.ZodString>;
93
- expectedDigest: z.ZodOptional<z.ZodString>;
92
+ destination: z.ZodString;
93
+ expectedDigest: z.ZodString;
94
94
  }, z.core.$strict>, import("@zhivex-ai/core").JsonValue, unknown>;
95
95
  run_check: import("@zhivex-ai/core").ToolDefinition<z.ZodObject<{
96
96
  check: z.ZodString;