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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +12 -10
  3. package/SECURITY.md +1 -1
  4. package/SUPPORT.md +4 -4
  5. package/contracts/engine-api.json +334 -0
  6. package/contracts/public-api.json +267 -1
  7. package/contracts/stable-api-signatures.json +43 -43
  8. package/dist/acp-cli.js +54 -18
  9. package/dist/approvals/approval-history.d.ts +22 -0
  10. package/dist/approvals/explicit-review.d.ts +24 -0
  11. package/dist/approvals/host-policy-identity.d.ts +3 -0
  12. package/dist/cli/arguments.d.ts +6 -2
  13. package/dist/cli/checkpoints.d.ts +230 -0
  14. package/dist/cli/cli-profiles.d.ts +4 -2
  15. package/dist/cli/governance-report.d.ts +5 -0
  16. package/dist/cli/policy-decisions.d.ts +9 -0
  17. package/dist/cli/policy.d.ts +5 -0
  18. package/dist/cli/presentation.d.ts +3 -1
  19. package/dist/cli/terminal/terminal-ui.d.ts +4 -0
  20. package/dist/{cli-entry-xmf48p6a.js → cli-entry-1gfg3brj.js} +14921 -10692
  21. package/dist/cli-entry-bx3vjw7h.js +656 -0
  22. package/dist/{index-fvca1xea.js → cli-entry-d5788aay.js} +339 -58
  23. package/dist/{cli-qgwvtk0w.js → cli-etsmtst3.js} +918 -2222
  24. package/dist/cli.js +3 -5
  25. package/dist/client/acp-mcp-admission.d.ts +32 -0
  26. package/dist/client/acp-mcp-host.d.ts +19 -0
  27. package/dist/client/acp-mcp-session.d.ts +14 -0
  28. package/dist/client/acp-stdio.d.ts +2 -0
  29. package/dist/client/acp.d.ts +4 -1
  30. package/dist/client/adapter.d.ts +13 -1
  31. package/dist/client/json-contracts.d.ts +107 -4
  32. package/dist/client/local-service.d.ts +2 -0
  33. package/dist/client/protocol.d.ts +127 -1
  34. package/dist/client/service-events.d.ts +4 -0
  35. package/dist/compat/cli-options.d.ts +13 -1
  36. package/dist/compat/code-support.js +23 -87
  37. package/dist/{config-q32jm1e6.js → config-c002f06f.js} +1 -1
  38. package/dist/{config-6gtpxvjv.js → config-j3jga5wh.js} +3 -1
  39. package/dist/context/adaptive-compaction.d.ts +1 -0
  40. package/dist/context/compaction.d.ts +1 -1
  41. package/dist/context/request-measurements.d.ts +17 -0
  42. package/dist/context/request-projection.d.ts +10 -0
  43. package/dist/context/task-memory.d.ts +1 -0
  44. package/dist/engine/acp.d.ts +2 -0
  45. package/dist/engine/acp.js +197 -1
  46. package/dist/engine/client.js +11 -4
  47. package/dist/engine/desktop-providers-v1.d.ts +4 -0
  48. package/dist/engine/desktop-providers-v1.js +18 -0
  49. package/dist/engine/desktop-state-v1.d.ts +10 -0
  50. package/dist/engine/desktop-state-v1.js +168 -0
  51. package/dist/engine/index.d.ts +12 -0
  52. package/dist/engine/index.js +571 -71
  53. package/dist/engine/mcp-stdio-v1.d.ts +11 -0
  54. package/dist/engine/mcp-stdio-v1.js +108 -0
  55. package/dist/engine/models.d.ts +3 -0
  56. package/dist/engine/models.js +894 -0
  57. package/dist/engine/protocol.d.ts +1 -0
  58. package/dist/engine/protocol.js +24 -0
  59. package/dist/engine/service.js +12 -5
  60. package/dist/execution/acceptance-snapshot.d.ts +2 -0
  61. package/dist/execution/execution-environment.d.ts +10 -0
  62. package/dist/execution/mcp-oci-channel.d.ts +11 -0
  63. package/dist/execution/mcp-oci-server.d.ts +38 -0
  64. package/dist/execution/mcp-oci-workspace.d.ts +23 -0
  65. package/dist/execution/mcp-resource-recovery.d.ts +19 -0
  66. package/dist/execution/mcp-workspace-snapshot.d.ts +20 -0
  67. package/dist/hostile-repository-demo.js +3169 -1163
  68. package/dist/{index-f4sb0e2q.js → index-2jrdcj6b.js} +17 -2
  69. package/dist/{index-77h9qr5h.js → index-3ah1f369.js} +40 -10
  70. package/dist/{index-pgqz45fj.js → index-42gp2hy8.js} +197 -1091
  71. package/dist/{index-41fkzt91.js → index-4jw3tvy8.js} +10 -2
  72. package/dist/index-6m08wvab.js +1768 -0
  73. package/dist/index-8705zxpr.js +145 -0
  74. package/dist/{index-d0wrghff.js → index-8vm2m34s.js} +225 -1416
  75. package/dist/index-8zzhggxv.js +477 -0
  76. package/dist/index-a97bezbz.js +1073 -0
  77. package/dist/index-azmwjp95.js +1004 -0
  78. package/dist/{cli-entry-0mmeag20.js → index-gq9xagx2.js} +122 -836
  79. package/dist/index-h0mqx2ed.js +1373 -0
  80. package/dist/index-hnaxfpb5.js +5589 -0
  81. package/dist/{index-2aymdsqc.js → index-qfpz5y2v.js} +24 -0
  82. package/dist/{index-kfgt9yqq.js → index-w2sj0wkw.js} +33 -10
  83. package/dist/index-wg1sd3at.js +80 -0
  84. package/dist/index-xqxeypt5.js +888 -0
  85. package/dist/index-yb239ghk.js +961 -0
  86. package/dist/index-z0qxmkm2.js +3389 -0
  87. package/dist/index.js +85 -72
  88. package/dist/integrations/mcp-host-session.d.ts +26 -0
  89. package/dist/integrations/mcp-stdio-admission.d.ts +54 -0
  90. package/dist/integrations/mcp-stdio-client.d.ts +44 -0
  91. package/dist/integrations/mcp-stdio-framing.d.ts +18 -0
  92. package/dist/integrations/mcp-stdio-launch.d.ts +20 -0
  93. package/dist/integrations/mcp-stdio-session.d.ts +7 -0
  94. package/dist/integrations/mcp-stdio-tools.d.ts +12 -0
  95. package/dist/internal/desktop/catalog.d.ts +2 -0
  96. package/dist/internal/desktop/persistence.d.ts +2 -3
  97. package/dist/internal/desktop/providers.d.ts +1 -0
  98. package/dist/models/catalog.d.ts +2 -0
  99. package/dist/persistence/governance-context.d.ts +126 -0
  100. package/dist/persistence/governance-report.d.ts +299 -0
  101. package/dist/persistence/host-database-backup.d.ts +28 -0
  102. package/dist/persistence/mcp-execution-journal.d.ts +19 -0
  103. package/dist/persistence/mcp-reconciliation.d.ts +33 -0
  104. package/dist/persistence/mcp-resource-journal.d.ts +54 -0
  105. package/dist/persistence/workspace-checkpoints.d.ts +138 -0
  106. package/dist/providers/anthropic-continuation.d.ts +5 -0
  107. package/dist/providers/providers.d.ts +1 -1
  108. package/dist/providers/vertex-auth.d.ts +27 -0
  109. package/dist/runtime/delegation-contracts.d.ts +9 -0
  110. package/dist/runtime/delegation-correction.d.ts +9 -0
  111. package/dist/runtime/delegation-result.d.ts +73 -0
  112. package/dist/runtime/error-diagnostics.d.ts +86 -0
  113. package/dist/runtime/harness.d.ts +11 -1
  114. package/dist/runtime/policy-decisions.d.ts +66 -0
  115. package/dist/runtime/policy-inspection.d.ts +52 -0
  116. package/dist/runtime/provider-diagnostics.d.ts +1 -0
  117. package/dist/runtime/runtime-instructions.d.ts +8 -0
  118. package/dist/runtime/task-acceptance-checks.d.ts +103 -0
  119. package/dist/runtime/task-acceptance-delivery.d.ts +107 -0
  120. package/dist/runtime/task-acceptance-host.d.ts +20 -0
  121. package/dist/runtime/task-acceptance-record.d.ts +107 -0
  122. package/dist/runtime/task-acceptance-validation.d.ts +25 -0
  123. package/dist/runtime/task-acceptance.d.ts +47 -0
  124. package/dist/runtime/time-to-safe-fix.d.ts +83 -0
  125. package/dist/runtime/tool-policy-file.d.ts +23 -0
  126. package/dist/runtime/tool-policy-paths.d.ts +5 -0
  127. package/dist/runtime/tool-policy.d.ts +6 -0
  128. package/dist/service-cli.js +14 -7
  129. package/dist/{service-client-cli-gs78wrxe.js → service-client-cli-3365rfav.js} +307 -248
  130. package/dist/verify-historical-migrations.js +3134 -1129
  131. package/dist/workspace/path-policy.d.ts +4 -0
  132. package/dist/zhx.js +3 -5
  133. package/docs/ACP.md +14 -2
  134. package/docs/ANTHROPIC.md +33 -0
  135. package/docs/CLI.md +132 -0
  136. package/docs/CLIENT_PROTOCOL.md +45 -0
  137. package/docs/CODE_RELEASE.md +35 -18
  138. package/docs/ENGINE_API.md +216 -7
  139. package/docs/EXTENSIBILITY.md +46 -3
  140. package/docs/FIRST_USE.md +6 -6
  141. package/docs/LOCAL_SERVICE.md +13 -0
  142. package/docs/MCP_STDIO.md +20 -0
  143. package/docs/README.md +1 -0
  144. package/docs/STABILITY.md +4 -2
  145. package/docs/SUPPORT_MATRIX.md +1 -1
  146. package/docs/TOOL_POLICY.md +81 -0
  147. package/docs/VERTEX.md +50 -0
  148. package/docs/adr/0002-isolated-mcp-stdio.md +135 -0
  149. package/docs/fixtures/mcp-stdio-contract-v1.json +189 -0
  150. package/docs/support-matrix.json +2 -0
  151. package/evaluations/representative-assembly-matrix.json +46 -1
  152. package/evaluations/task-acceptance-routes.json +7 -0
  153. package/examples/README.md +3 -3
  154. package/package.json +43 -12
  155. package/dist/cli-entry-64pdp3k5.js +0 -17
  156. package/dist/cli-entry-7h9savv5.js +0 -375
  157. package/dist/index-5wjwe91x.js +0 -9434
@@ -123,12 +123,36 @@ var scoped = { projectId: id };
123
123
  var session = { ...scoped, sessionId: id };
124
124
  var run = { ...session, runId: id };
125
125
  var mutation = { idempotencyKey: id };
126
+ var checkpoint = { ...session, checkpointId: z.string().uuid() };
127
+ var restore = { ...session, operationId: z.string().uuid() };
128
+ var fileDigest = z.string().regex(/^sha256:[a-f0-9]{64}$/);
126
129
  var harnessClientCommandSchema = z.discriminatedUnion("method", [
127
130
  z.object({ method: z.literal("project.get"), ...scoped }).strict(),
131
+ z.object({ method: z.literal("policy.get"), ...scoped }).strict(),
128
132
  z.object({ method: z.literal("session.list"), ...scoped, search: z.string().max(256).optional() }).strict(),
129
133
  z.object({ method: z.literal("session.create"), ...scoped, ...mutation, title: z.string().max(256).optional() }).strict(),
130
134
  z.object({ method: z.literal("session.get"), ...session }).strict(),
131
135
  z.object({ method: z.literal("session.rename"), ...session, ...mutation, expectedRevision: revision, title: z.string().max(256) }).strict(),
136
+ z.object({ method: z.literal("checkpoint.list"), ...session }).strict(),
137
+ z.object({ method: z.literal("checkpoint.inspect"), ...checkpoint }).strict(),
138
+ z.object({
139
+ method: z.literal("checkpoint.capture"),
140
+ ...session,
141
+ ...mutation,
142
+ expectedRevision: revision,
143
+ turnId: id,
144
+ paths: z.array(z.string().min(1).max(1024)).min(1).max(20)
145
+ }).strict(),
146
+ z.object({
147
+ method: z.literal("restore.prepare"),
148
+ ...checkpoint,
149
+ ...mutation,
150
+ expectedRevision: revision,
151
+ expected: z.record(z.string().min(1).max(1024), fileDigest).refine((value) => Object.keys(value).length >= 1 && Object.keys(value).length <= 20)
152
+ }).strict(),
153
+ z.object({ method: z.literal("restore.get"), ...restore }).strict(),
154
+ z.object({ method: z.literal("restore.apply"), ...restore, ...mutation, expectedRevision: revision, reviewedProposalId: fileDigest }).strict(),
155
+ z.object({ method: z.literal("restore.recoverFork"), ...restore, ...mutation, expectedRevision: revision, forkSessionId: id }).strict(),
132
156
  z.object({ method: z.literal("run.start"), ...session, ...mutation, expectedRevision: revision, prompt: z.string().min(1).max(64 * 1024) }).strict(),
133
157
  z.object({ method: z.literal("run.get"), ...run, includeReview: z.boolean().optional(), includeDiff: z.boolean().optional(), decisionOffset: z.number().int().min(0).max(512).optional() }).strict(),
134
158
  z.object({
@@ -1,14 +1,17 @@
1
1
  import {
2
- createHarnessClientAdapter
3
- } from "./index-5wjwe91x.js";
2
+ createHarnessClientAdapter,
3
+ harnessPolicyDecisionEventSchema
4
+ } from "./index-hnaxfpb5.js";
4
5
  import {
5
- SqliteDatabase,
6
6
  openCliSessionStore
7
- } from "./index-pgqz45fj.js";
7
+ } from "./index-42gp2hy8.js";
8
+ import {
9
+ SqliteDatabase
10
+ } from "./index-yb239ghk.js";
8
11
  import {
9
12
  harnessClientRequestSchema,
10
13
  streamEventDocument
11
- } from "./index-2aymdsqc.js";
14
+ } from "./index-qfpz5y2v.js";
12
15
  import {
13
16
  __require
14
17
  } from "./index-1bx83sw4.js";
@@ -139,6 +142,9 @@ var openHarnessActivityStore = async (config, options = {}) => {
139
142
  }
140
143
  };
141
144
  return {
145
+ policyDecision(sessionId, runId, event) {
146
+ write(sessionId, runId, redactValue(harnessPolicyDecisionEventSchema.parse(event)));
147
+ },
142
148
  prompt(sessionId, runId, prompt) {
143
149
  const safe = redact(prompt);
144
150
  const truncated = Buffer.byteLength(safe) > 60 * 1024;
@@ -193,10 +199,10 @@ var openHarnessActivityStore = async (config, options = {}) => {
193
199
  if (after > current.state.sequence)
194
200
  throw new Error("ACTIVITY_CURSOR_AHEAD");
195
201
  if (expired)
196
- return { schemaVersion: 1, cursorExpired: true, nextCursor: current.state.sequence, events: [], snapshot: current.state };
197
- const rows = db.query("SELECT sequence,session,run,at,activity FROM client_activity_events WHERE scope=? AND session=? AND sequence>? ORDER BY sequence LIMIT 200").all(scope, sessionId, after);
198
- const events = rows.map((row) => ({ schemaVersion: 1, eventId: createHash("sha256").update(`${scope}:${row.sequence}`).digest("hex"), sequence: row.sequence, sessionId: row.session, runId: row.run, at: row.at, activity: JSON.parse(row.activity) }));
199
- return { schemaVersion: 1, cursorExpired: false, nextCursor: events.at(-1)?.sequence ?? after, events };
202
+ return { schemaVersion: 1, cursorExpired: true, hasMore: false, policyEvidenceIncomplete: true, nextCursor: current.state.sequence, events: [], snapshot: current.state };
203
+ const rows = db.query("SELECT sequence,session,run,at,activity FROM client_activity_events WHERE scope=? AND session=? AND sequence>? ORDER BY sequence LIMIT 201").all(scope, sessionId, after);
204
+ const events = rows.slice(0, 200).map((row) => ({ schemaVersion: 1, eventId: createHash("sha256").update(`${scope}:${row.sequence}`).digest("hex"), sequence: row.sequence, sessionId: row.session, runId: row.run, at: row.at, activity: JSON.parse(row.activity) }));
205
+ return { schemaVersion: 1, cursorExpired: false, hasMore: rows.length > 200, policyEvidenceIncomplete: current.expiredThrough > 0, nextCursor: events.at(-1)?.sequence ?? after, events };
200
206
  },
201
207
  close() {
202
208
  db.close();
@@ -312,7 +318,7 @@ var startHarnessLocalService = async (harness, options) => {
312
318
  }
313
319
  const parsed = harnessClientRequestSchema.safeParse(value);
314
320
  const method = parsed.success ? parsed.data.command.method : undefined;
315
- const mutation = method !== undefined && !["project.get", "session.list", "session.get", "run.get"].includes(method);
321
+ const mutation = method !== undefined && !["project.get", "policy.get", "session.list", "session.get", "run.get", "checkpoint.list", "checkpoint.inspect", "restore.get"].includes(method);
316
322
  if (paused && mutation && method !== "run.cancel")
317
323
  return send(res, 503, fault("SERVICE_PAUSED"));
318
324
  if (mutation)
@@ -359,6 +365,7 @@ var startHarnessLocalService = async (harness, options) => {
359
365
  });
360
366
  adapter = await createHarnessClientAdapter(harness, {
361
367
  ...options.approvalNow ? { now: options.approvalNow } : {},
368
+ onPolicyDecision: (sessionId, runId, event) => activity.policyDecision(sessionId, runId, event),
362
369
  onPrompt: (sessionId, runId, prompt) => activity.prompt(sessionId, runId, prompt),
363
370
  onEvent: (sessionId, runId, event) => activity.append(sessionId, runId, event),
364
371
  onCheckpoint: (sessionId, runId, status) => activity.checkpoint(sessionId, runId, status)
@@ -377,6 +384,22 @@ var startHarnessLocalService = async (harness, options) => {
377
384
  return {
378
385
  socketPath,
379
386
  credentialsPath,
387
+ async dispatchReviewed(request) {
388
+ if (closing || paused)
389
+ throw new Error("SERVICE_ADMISSION_PAUSED");
390
+ if (!adapter?.dispatchReviewed)
391
+ throw new Error("EXPLICIT_REVIEW_UNAVAILABLE");
392
+ activeMutations++;
393
+ const operation = adapter.dispatchReviewed(request);
394
+ const tracked = operation.then(() => {}, () => {});
395
+ pending.add(tracked);
396
+ try {
397
+ return await operation;
398
+ } finally {
399
+ pending.delete(tracked);
400
+ activeMutations--;
401
+ }
402
+ },
380
403
  pauseAdmission() {
381
404
  if (closing)
382
405
  throw new Error("SERVICE_CLOSING");
@@ -0,0 +1,80 @@
1
+ import {
2
+ bundledModelCatalog,
3
+ modelCatalogSchema
4
+ } from "./index-xqxeypt5.js";
5
+
6
+ // src/models/catalog-store.ts
7
+ import { mkdir, readFile, rename, writeFile, unlink } from "node:fs/promises";
8
+ import { homedir } from "node:os";
9
+ import path from "node:path";
10
+ import { createHash, randomUUID } from "node:crypto";
11
+ var MAX_BYTES = 1024 * 1024;
12
+ var TTL = 60 * 60 * 1000;
13
+ async function loadModelCatalog(options = {}) {
14
+ const fallback = { catalog: bundledModelCatalog, source: "bundled", stale: false };
15
+ const source = options.url ?? process.env.ZHIVEX_MODEL_CATALOG_URL;
16
+ if (!source)
17
+ return fallback;
18
+ let url;
19
+ try {
20
+ url = new URL(source);
21
+ if (url.protocol !== "https:" || url.username || url.password || url.hash)
22
+ return { ...fallback, stale: true };
23
+ } catch {
24
+ return { ...fallback, stale: true };
25
+ }
26
+ const now = options.now ?? Date.now();
27
+ const directory = options.cacheDirectory ?? path.join(homedir(), ".zhivex", "model-catalog");
28
+ const file = path.join(directory, `${createHash("sha256").update(url.href).digest("hex")}.json`);
29
+ let cached;
30
+ try {
31
+ const raw = await readFile(file, "utf8");
32
+ if (Buffer.byteLength(raw) > MAX_BYTES + 1024)
33
+ throw new Error("CATALOG_TOO_LARGE");
34
+ const envelope = JSON.parse(raw);
35
+ if (envelope.url !== url.href || !Number.isFinite(envelope.fetchedAt))
36
+ throw new Error("INVALID_CACHE");
37
+ cached = { catalog: modelCatalogSchema.parse(envelope.catalog), source: "cache", stale: true };
38
+ if (!options.refresh && now >= envelope.fetchedAt && now - envelope.fetchedAt < TTL)
39
+ return { ...cached, stale: false };
40
+ } catch {}
41
+ try {
42
+ const response = await (options.fetcher ?? fetch)(url, {
43
+ signal: AbortSignal.timeout(3000),
44
+ redirect: "error",
45
+ headers: { accept: "application/json" }
46
+ });
47
+ if (!response.ok || !response.body)
48
+ throw new Error("CATALOG_FETCH_FAILED");
49
+ const reader = response.body.getReader();
50
+ const chunks = [];
51
+ let size = 0;
52
+ try {
53
+ for (;; ) {
54
+ const { value, done } = await reader.read();
55
+ if (done)
56
+ break;
57
+ size += value.byteLength;
58
+ if (size > MAX_BYTES)
59
+ throw new Error("CATALOG_TOO_LARGE");
60
+ chunks.push(value);
61
+ }
62
+ } finally {
63
+ await reader.cancel().catch(() => {});
64
+ }
65
+ const catalog = modelCatalogSchema.parse(JSON.parse(Buffer.concat(chunks).toString("utf8")));
66
+ const temporary = `${file}.${randomUUID()}.tmp`;
67
+ try {
68
+ await mkdir(directory, { recursive: true, mode: 448 });
69
+ await writeFile(temporary, JSON.stringify({ url: url.href, fetchedAt: now, catalog }), { mode: 384, flag: "wx" });
70
+ await rename(temporary, file);
71
+ } catch {} finally {
72
+ await unlink(temporary).catch(() => {});
73
+ }
74
+ return { catalog, source: "remote", stale: false };
75
+ } catch {
76
+ return cached ?? { ...fallback, stale: true };
77
+ }
78
+ }
79
+
80
+ export { loadModelCatalog };