@agentskit/harness 0.3.0 → 0.4.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/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { resolve, dirname, join, relative, basename, extname, sep } from 'path';
2
2
  import { createHash, randomUUID, createPrivateKey, createPublicKey, sign, verify } from 'crypto';
3
- import { existsSync, mkdirSync, openSync, writeSync, appendFileSync, closeSync, unlinkSync, readFileSync, writeFileSync, mkdtempSync, renameSync, rmSync, readdirSync } from 'fs';
3
+ import { existsSync, mkdirSync, openSync, writeSync, appendFileSync, closeSync, unlinkSync, readFileSync, writeFileSync, readdirSync, mkdtempSync, renameSync, rmSync } from 'fs';
4
4
  import { execFile, spawn } from 'child_process';
5
5
  import { promisify } from 'util';
6
6
  import { cpus, loadavg, freemem, totalmem, tmpdir } from 'os';
7
7
 
8
- // src/constants.ts
8
+ // src/kernel/constants.ts
9
9
  var STATES = [
10
10
  "CLARIFYING",
11
11
  "PLANNED",
@@ -35,7 +35,8 @@ var LEGAL_TRANSITIONS = {
35
35
  var REAL_CATEGORIES = /* @__PURE__ */ new Set(["endpoint", "database", "cli", "mcp", "ui"]);
36
36
  var DECISIONS = /* @__PURE__ */ new Set(["approved", "approve", "yes", "ok", "rejected", "reject", "no"]);
37
37
 
38
- // src/errors.ts
38
+ // src/kernel/errors.ts
39
+ var HARNESS_ERROR_CODES = ["HARNESS_ERROR", "INVALID_CONFIG", "INVALID_INPUT", "INVALID_STATE", "POLICY_BLOCKED", "CLARIFYING", "STALE", "WORKTREE_DIRTY", "ACTIVE_RUN", "NO_RUN", "HUMAN_APPROVAL_REQUIRED", "GIT_REQUIRED"];
39
40
  var HarnessError = class extends Error {
40
41
  code;
41
42
  constructor(message, code = "HARNESS_ERROR") {
@@ -48,7 +49,41 @@ var fail = (message, code = "HARNESS_ERROR") => {
48
49
  throw new HarnessError(message, code);
49
50
  };
50
51
 
51
- // src/profiles.ts
52
+ // src/kernel/error-policy.ts
53
+ var HARNESS_ERROR_CATALOG = {
54
+ HARNESS_ERROR: { disposition: "escalate", retryable: false },
55
+ INVALID_CONFIG: { disposition: "block", retryable: false },
56
+ INVALID_INPUT: { disposition: "block", retryable: false },
57
+ INVALID_STATE: { disposition: "block", retryable: false },
58
+ POLICY_BLOCKED: { disposition: "block", retryable: false },
59
+ CLARIFYING: { disposition: "block", retryable: false },
60
+ STALE: { disposition: "block", retryable: false },
61
+ WORKTREE_DIRTY: { disposition: "block", retryable: false },
62
+ ACTIVE_RUN: { disposition: "retry", retryable: true },
63
+ NO_RUN: { disposition: "block", retryable: false },
64
+ HUMAN_APPROVAL_REQUIRED: { disposition: "block", retryable: false },
65
+ GIT_REQUIRED: { disposition: "block", retryable: false }
66
+ };
67
+ var nonEmpty = (value, label) => {
68
+ if (typeof value !== "string" || !value.trim()) throw new HarnessError(`${label} is required.`, "INVALID_INPUT");
69
+ return value.trim();
70
+ };
71
+ var classifyHarnessError = (error) => {
72
+ const code = error instanceof HarnessError ? error.code : "HARNESS_ERROR";
73
+ const descriptor2 = HARNESS_ERROR_CATALOG[code];
74
+ return { code, ...descriptor2, message: error instanceof Error ? error.message : String(error) };
75
+ };
76
+ var validateHarnessErrorClassification = (value) => {
77
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new HarnessError("Error classification must be an object.", "INVALID_INPUT");
78
+ const candidate = value;
79
+ const code = candidate["code"];
80
+ if (typeof code !== "string" || !HARNESS_ERROR_CODES.includes(code)) throw new HarnessError("Error classification code is invalid.", "INVALID_INPUT");
81
+ const expected = HARNESS_ERROR_CATALOG[code];
82
+ if (candidate["disposition"] !== expected.disposition || candidate["retryable"] !== expected.retryable) throw new HarnessError(`Error classification for ${code} is inconsistent.`, "INVALID_INPUT");
83
+ return { code, disposition: expected.disposition, retryable: expected.retryable, message: nonEmpty(candidate["message"], "Error classification message") };
84
+ };
85
+
86
+ // src/profiles/index.ts
52
87
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
53
88
  var record = (value, label) => {
54
89
  if (!isRecord(value)) fail(`${label} must be an object.`, "INVALID_CONFIG");
@@ -138,7 +173,7 @@ var cleanConfiguredArtifacts = (loaded) => {
138
173
  };
139
174
  var fileContents = (path) => readFileSync(path, "utf8");
140
175
 
141
- // src/types.ts
176
+ // src/kernel/types.ts
142
177
  var SURFACE_NAMES = ["logic", "endpoint", "database", "cli", "mcp", "ui", "docs"];
143
178
  var CHECK_CATEGORIES = ["build", "test", "lint", ...SURFACE_NAMES, "custom"];
144
179
  var RUN_STATES = [
@@ -155,7 +190,7 @@ var RUN_STATES = [
155
190
  "SUPERSEDED"
156
191
  ];
157
192
 
158
- // src/config.ts
193
+ // src/execution/config.ts
159
194
  var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
160
195
  var stringValue = (value, label) => {
161
196
  if (typeof value !== "string") return fail(`${label} is required.`, "INVALID_CONFIG");
@@ -269,7 +304,7 @@ var loadConfig = (configPath = ".codex/verification.json") => {
269
304
  return { absolute, root, stateDir, config, configHash: hashJson(config) };
270
305
  };
271
306
 
272
- // src/state-machine.ts
307
+ // src/kernel/state-machine.ts
273
308
  var transition = (run, to, reason, actor = "harness") => {
274
309
  if (!STATES.includes(to)) fail(`Unknown state ${to}.`, "INVALID_STATE");
275
310
  if (run.state !== to && !LEGAL_TRANSITIONS[run.state].some((state) => state === to)) fail(`Illegal transition ${run.state} -> ${to}.`, "INVALID_STATE");
@@ -284,8 +319,63 @@ var approvedDecision = (decision) => {
284
319
  return ["approved", "approve", "yes", "ok"].includes(decision);
285
320
  };
286
321
  var HARNESS_EVENT_SCHEMA_VERSION = 1;
322
+ var HARNESS_EVENT_ENVELOPE_SCHEMA_VERSION = 2;
287
323
  var EVENT_LOG_GENESIS = "GENESIS";
288
- var HARNESS_EVENT_TYPES = ["run.created", "state.transitioned", "context.attached", "verification.completed", "approval.recorded", "authorization.recorded", "session.started", "session.resumed", "agent.turn.started", "policy.evaluated", "tool.approval.requested", "tool.approval.recorded", "tool.requested", "tool.execution.started", "tool.recovery.recorded", "tool.blocked", "tool.completed", "tool.failed", "session.ended"];
324
+ var HARNESS_EVENT_TYPES = ["run.created", "state.transitioned", "context.attached", "verification.completed", "artifact.recorded", "approval.recorded", "authorization.recorded", "session.started", "session.resumed", "agent.turn.started", "policy.evaluated", "tool.approval.requested", "tool.approval.recorded", "tool.requested", "tool.execution.started", "tool.recovery.recorded", "tool.blocked", "tool.completed", "tool.failed", "session.ended"];
325
+ var envelopeId = (value, label) => {
326
+ if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value)) fail(`${label} is invalid.`, "INVALID_INPUT");
327
+ return value;
328
+ };
329
+ var envelopeText = (value, label) => {
330
+ if (typeof value !== "string") fail(`${label} is required.`, "INVALID_INPUT");
331
+ const result = value.trim();
332
+ if (!result) fail(`${label} is required.`, "INVALID_INPUT");
333
+ return result;
334
+ };
335
+ var envelopeDigest = (value, label) => {
336
+ const result = envelopeText(value, label);
337
+ if (!/^[a-f0-9]{64}$/.test(result)) fail(`${label} must be a lowercase SHA-256 digest.`, "INVALID_INPUT");
338
+ return result;
339
+ };
340
+ var envelopeProvenance = (value) => {
341
+ if (typeof value !== "object" || value === null || Array.isArray(value)) fail("Event provenance must be an object.", "INVALID_INPUT");
342
+ const candidate = value;
343
+ return {
344
+ source: envelopeText(candidate["source"], "Event provenance source"),
345
+ component: envelopeText(candidate["component"], "Event provenance component"),
346
+ version: envelopeText(candidate["version"], "Event provenance version"),
347
+ ...candidate["actor"] === void 0 ? {} : { actor: envelopeText(candidate["actor"], "Event provenance actor") }
348
+ };
349
+ };
350
+ var validateHarnessEventEnvelope = (value) => {
351
+ if (typeof value !== "object" || value === null || Array.isArray(value)) fail("Event envelope must be an object.", "INVALID_INPUT");
352
+ const candidate = value;
353
+ if (candidate["schemaVersion"] !== HARNESS_EVENT_ENVELOPE_SCHEMA_VERSION) fail("Event envelope schemaVersion is invalid.", "INVALID_INPUT");
354
+ const payload = candidate["payload"];
355
+ if (typeof payload !== "object" || payload === null || Array.isArray(payload)) fail("Event envelope payload must be an object.", "INVALID_INPUT");
356
+ const issueRef = candidate["issueRef"] === void 0 ? void 0 : envelopeText(candidate["issueRef"], "Event issueRef");
357
+ const occurredAt = envelopeText(candidate["occurredAt"], "Event occurredAt");
358
+ if (!Number.isFinite(Date.parse(occurredAt))) fail("Event occurredAt must be a valid timestamp.", "INVALID_INPUT");
359
+ return {
360
+ eventId: envelopeId(candidate["eventId"], "Event eventId"),
361
+ eventType: envelopeId(candidate["eventType"], "Event eventType"),
362
+ schemaVersion: HARNESS_EVENT_ENVELOPE_SCHEMA_VERSION,
363
+ occurredAt,
364
+ runId: envelopeText(candidate["runId"], "Event runId"),
365
+ ...issueRef === void 0 ? {} : { issueRef },
366
+ sourceRevision: envelopeText(candidate["sourceRevision"], "Event sourceRevision"),
367
+ correlationId: envelopeId(candidate["correlationId"], "Event correlationId"),
368
+ payload,
369
+ idempotencyKey: envelopeDigest(candidate["idempotencyKey"], "Event idempotencyKey"),
370
+ provenance: envelopeProvenance(candidate["provenance"])
371
+ };
372
+ };
373
+ var createHarnessEventEnvelope = (input) => {
374
+ if (typeof input !== "object" || input === null || Array.isArray(input)) fail("Event envelope input must be an object.", "INVALID_INPUT");
375
+ const identity = { eventType: input.eventType, runId: input.runId, ...input.issueRef === void 0 ? {} : { issueRef: input.issueRef }, sourceRevision: input.sourceRevision, correlationId: input.correlationId, payload: input.payload, provenance: input.provenance };
376
+ const candidate = { ...input, schemaVersion: HARNESS_EVENT_ENVELOPE_SCHEMA_VERSION, idempotencyKey: input.idempotencyKey ?? hashJson(identity) };
377
+ return validateHarnessEventEnvelope(candidate);
378
+ };
289
379
  var SESSION_EVENT_TYPES = /* @__PURE__ */ new Set(["session.started", "session.resumed", "agent.turn.started", "policy.evaluated", "tool.approval.requested", "tool.approval.recorded", "tool.requested", "tool.execution.started", "tool.recovery.recorded", "tool.blocked", "tool.completed", "tool.failed", "session.ended"]);
290
380
  var eventPath = (stateDir, runId) => join(stateDir, "runs", runId, "events.ndjson");
291
381
  var lockPath = (stateDir, runId) => `${eventPath(stateDir, runId)}.lock`;
@@ -306,8 +396,8 @@ var readLock = (stateDir, runId) => {
306
396
  var isEventType = (value) => typeof value === "string" && HARNESS_EVENT_TYPES.includes(value);
307
397
  var digest = (value) => /^[a-f0-9]{64}$/.test(value);
308
398
  var eventBody = (event) => {
309
- const { eventHash: _eventHash, ...body2 } = event;
310
- return body2;
399
+ const { eventHash: _eventHash, ...body3 } = event;
400
+ return body3;
311
401
  };
312
402
  var eventDigest = (event) => sha256(JSON.stringify(eventBody(event)));
313
403
  var parseEvent = (value, expectedSequence) => {
@@ -359,8 +449,8 @@ var FileEventStore = class {
359
449
  try {
360
450
  const events = this.readUnlocked(event.runId);
361
451
  const previous = events.at(-1);
362
- const body2 = { schemaVersion: HARNESS_EVENT_SCHEMA_VERSION, sequence: events.length + 1, at: (/* @__PURE__ */ new Date()).toISOString(), runId: event.runId, sourceRevision: event.sourceRevision, configHash: event.configHash, ...event.correlation ? { correlation: event.correlation } : {}, ...event.sessionId ? { sessionId: event.sessionId } : {}, ...previous?.eventHash ? { previousHash: previous.eventHash } : events.length ? {} : { previousHash: EVENT_LOG_GENESIS }, type: event.type, payload: event.payload };
363
- const record3 = events.length && !previous?.eventHash ? body2 : { ...body2, eventHash: eventDigest(body2) };
452
+ const body3 = { schemaVersion: HARNESS_EVENT_SCHEMA_VERSION, sequence: events.length + 1, at: (/* @__PURE__ */ new Date()).toISOString(), runId: event.runId, sourceRevision: event.sourceRevision, configHash: event.configHash, ...event.correlation ? { correlation: event.correlation } : {}, ...event.sessionId ? { sessionId: event.sessionId } : {}, ...previous?.eventHash ? { previousHash: previous.eventHash } : events.length ? {} : { previousHash: EVENT_LOG_GENESIS }, type: event.type, payload: event.payload };
453
+ const record3 = events.length && !previous?.eventHash ? body3 : { ...body3, eventHash: eventDigest(body3) };
364
454
  appendFileSync(path, `${JSON.stringify(record3)}
365
455
  `, "utf8");
366
456
  return record3;
@@ -414,16 +504,27 @@ var recoverEventLogLock = ({ stateDir, runId, actor, maxAgeMs = 3e5 }) => {
414
504
  return fail("Event log lock owner is still alive.", "HARNESS_ERROR");
415
505
  };
416
506
 
417
- // src/plugins.ts
507
+ // src/kernel/plugins.ts
418
508
  var HARNESS_PLUGIN_API_VERSION = 1;
419
509
  var createPluginSlot = (id2) => {
420
- if (!id2.trim()) fail("Plugin slot id is required.", "INVALID_INPUT");
421
- return { id: id2 };
510
+ if (typeof id2 !== "string" || !id2.trim()) fail("Plugin slot id is required.", "INVALID_INPUT");
511
+ return { id: id2.trim() };
422
512
  };
423
513
  var validId = (value, label) => {
424
- if (!value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
514
+ if (typeof value !== "string") fail(`${label} is required.`, "INVALID_INPUT");
515
+ const result = value.trim();
516
+ if (!result) fail(`${label} is required.`, "INVALID_INPUT");
517
+ return result;
518
+ };
519
+ var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
520
+ var validEventType = (value) => {
521
+ if (typeof value !== "string" || !HARNESS_EVENT_TYPES.includes(value)) fail("Plugin event type is invalid.", "INVALID_INPUT");
425
522
  return value;
426
523
  };
524
+ var validSlot = (value) => {
525
+ if (!isRecord3(value)) fail("Plugin slot must be an object.", "INVALID_INPUT");
526
+ return { id: validId(value["id"], "Plugin slot id") };
527
+ };
427
528
  var createPluginRegistry = () => {
428
529
  const plugins = /* @__PURE__ */ new Map();
429
530
  const contributions = /* @__PURE__ */ new Map();
@@ -470,11 +571,20 @@ var createPluginRegistry = () => {
470
571
  register(plugin) {
471
572
  ensureOpen();
472
573
  if (mounted) fail("Plugins cannot be registered after mount.", "HARNESS_ERROR");
473
- validId(plugin.id, "Plugin id");
474
- validId(plugin.version, "Plugin version");
475
- if (plugin.apiVersion !== HARNESS_PLUGIN_API_VERSION) fail(`Unsupported plugin API version: ${String(plugin.apiVersion)}.`, "INVALID_INPUT");
476
- if (plugins.has(plugin.id)) fail(`Plugin already registered: ${plugin.id}.`, "INVALID_INPUT");
477
- plugins.set(plugin.id, plugin);
574
+ if (!isRecord3(plugin)) fail("Plugin must be an object.", "INVALID_INPUT");
575
+ const candidate = plugin;
576
+ const id2 = validId(candidate.id, "Plugin id");
577
+ validId(candidate.version, "Plugin version");
578
+ if (candidate.apiVersion !== HARNESS_PLUGIN_API_VERSION) fail(`Unsupported plugin API version: ${String(candidate.apiVersion)}.`, "INVALID_INPUT");
579
+ if (typeof candidate.apply !== "function") fail("Plugin apply must be a function.", "INVALID_INPUT");
580
+ let requires;
581
+ if (candidate.requires !== void 0) {
582
+ if (!Array.isArray(candidate.requires)) fail("Plugin requires must be an array.", "INVALID_INPUT");
583
+ requires = candidate.requires.map((dependency, index2) => validId(dependency, `Plugin dependency[${index2}]`));
584
+ if (new Set(requires).size !== requires.length) fail("Plugin dependencies must be unique.", "INVALID_INPUT");
585
+ }
586
+ if (plugins.has(id2)) fail(`Plugin already registered: ${id2}.`, "INVALID_INPUT");
587
+ plugins.set(id2, { ...candidate, id: id2, ...requires === void 0 ? {} : { requires } });
478
588
  },
479
589
  mount() {
480
590
  ensureOpen();
@@ -483,14 +593,17 @@ var createPluginRegistry = () => {
483
593
  for (const plugin of order()) {
484
594
  const context = {
485
595
  apiVersion: HARNESS_PLUGIN_API_VERSION,
486
- register: (slot, id2, value) => registerContribution(plugin.id, slot, validId(id2, "Plugin contribution id"), value),
596
+ register: (slot, id2, value) => registerContribution(plugin.id, validSlot(slot), validId(id2, "Plugin contribution id"), value),
487
597
  effect: (disposer) => {
598
+ if (typeof disposer !== "function") fail("Plugin disposer must be a function.", "INVALID_INPUT");
488
599
  cleanups.push(disposer);
489
600
  },
490
601
  on: (type, listener) => {
491
- const handlers = listeners.get(type) ?? /* @__PURE__ */ new Set();
602
+ const eventType = validEventType(type);
603
+ if (typeof listener !== "function") fail("Plugin event listener must be a function.", "INVALID_INPUT");
604
+ const handlers = listeners.get(eventType) ?? /* @__PURE__ */ new Set();
492
605
  handlers.add(listener);
493
- listeners.set(type, handlers);
606
+ listeners.set(eventType, handlers);
494
607
  const disposer = () => {
495
608
  handlers.delete(listener);
496
609
  };
@@ -513,14 +626,16 @@ var createPluginRegistry = () => {
513
626
  },
514
627
  on(type, listener) {
515
628
  ensureOpen();
516
- const handlers = listeners.get(type) ?? /* @__PURE__ */ new Set();
629
+ const eventType = validEventType(type);
630
+ if (typeof listener !== "function") fail("Plugin event listener must be a function.", "INVALID_INPUT");
631
+ const handlers = listeners.get(eventType) ?? /* @__PURE__ */ new Set();
517
632
  handlers.add(listener);
518
- listeners.set(type, handlers);
633
+ listeners.set(eventType, handlers);
519
634
  return () => {
520
635
  handlers.delete(listener);
521
636
  };
522
637
  },
523
- contributions: (slot) => [...contributions.get(slot.id)?.values() ?? []],
638
+ contributions: (slot) => [...contributions.get(validSlot(slot).id)?.values() ?? []],
524
639
  dispose() {
525
640
  if (disposed) return;
526
641
  let firstError;
@@ -541,7 +656,25 @@ var createPluginRegistry = () => {
541
656
  return registry;
542
657
  };
543
658
 
544
- // src/context.ts
659
+ // src/kernel/adapter-contract.ts
660
+ var ASSURANCE_LEVELS = ["unverified", "contract-tested", "runtime-attested"];
661
+ var nonNegative = (value, label) => {
662
+ if (!Number.isFinite(value) || value < 0) return fail(`${label} must be a non-negative number.`, "INVALID_INPUT");
663
+ return value;
664
+ };
665
+ var validateAdapterMetadata = (value) => {
666
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return fail("Adapter metadata must be an object.", "INVALID_INPUT");
667
+ const candidate = value;
668
+ if (!ASSURANCE_LEVELS.includes(candidate["assurance"])) return fail("Adapter assurance is invalid.", "INVALID_INPUT");
669
+ if (typeof candidate["telemetry"] !== "object" || candidate["telemetry"] === null || Array.isArray(candidate["telemetry"])) return fail("Adapter telemetry must be an object.", "INVALID_INPUT");
670
+ const telemetry = candidate["telemetry"];
671
+ if (telemetry["status"] !== "measured" && telemetry["status"] !== "unknown") return fail("Adapter telemetry status is invalid.", "INVALID_INPUT");
672
+ for (const key of ["durationMs", "inputTokens", "outputTokens", "totalTokens", "cacheHits", "cacheMisses", "memoryReads", "memoryWrites", "memoryRelevantHits", "memoryStaleHits", "contextReferences", "contextCostTokens", "externalMutations"]) if (telemetry[key] !== void 0) nonNegative(telemetry[key], `Adapter telemetry ${key}`);
673
+ return value;
674
+ };
675
+ var unknownTelemetry = () => ({ status: "unknown" });
676
+
677
+ // src/context/index.ts
545
678
  var hashContextSnapshot = ({ providerId, query, references, sourceHash: sourceHash2 }) => hashJson({ providerId, query, references, sourceHash: sourceHash2 });
546
679
  var hashContextSnapshots = (snapshots) => hashJson(snapshots.map(({ providerId, query, references, sourceHash: sourceHash2, snapshotHash }) => ({ providerId, query, references, sourceHash: sourceHash2, snapshotHash })));
547
680
  var record2 = (value, label) => {
@@ -564,17 +697,23 @@ var validateContextSnapshot = (value, index2 = 0) => {
564
697
  uri: requiredString(rawReference["uri"], `context snapshot ${index2}.references[${referenceIndex}].uri`),
565
698
  ...typeof rawReference["title"] === "string" ? { title: rawReference["title"] } : {},
566
699
  ...typeof rawReference["version"] === "string" ? { version: rawReference["version"] } : {},
567
- ...typeof rawReference["contentHash"] === "string" ? { contentHash: rawReference["contentHash"] } : {}
700
+ ...typeof rawReference["contentHash"] === "string" ? { contentHash: rawReference["contentHash"] } : {},
701
+ ...rawReference["relevance"] === void 0 ? {} : typeof rawReference["relevance"] === "number" && rawReference["relevance"] >= 0 && rawReference["relevance"] <= 1 ? { relevance: rawReference["relevance"] } : fail(`context snapshot ${index2}.references[${referenceIndex}].relevance must be between 0 and 1.`, "INVALID_INPUT")
568
702
  };
569
703
  });
570
704
  const scope = rawQuery["scope"] === void 0 ? void 0 : Array.isArray(rawQuery["scope"]) && rawQuery["scope"].every((item) => typeof item === "string") ? rawQuery["scope"] : fail(`context snapshot ${index2}.query.scope must be an array of strings.`, "INVALID_INPUT");
705
+ const assurance = raw["assurance"] === void 0 ? void 0 : ASSURANCE_LEVELS.includes(raw["assurance"]) ? raw["assurance"] : fail(`context snapshot ${index2}.assurance is invalid.`, "INVALID_INPUT");
706
+ const telemetry = raw["telemetry"] === void 0 ? void 0 : record2(raw["telemetry"], `context snapshot ${index2}.telemetry`);
707
+ if (telemetry && telemetry["status"] !== "measured" && telemetry["status"] !== "unknown") fail(`context snapshot ${index2}.telemetry.status is invalid.`, "INVALID_INPUT");
571
708
  const snapshot = {
572
709
  providerId: requiredString(raw["providerId"], `context snapshot ${index2}.providerId`),
573
710
  query: { query: requiredString(rawQuery["query"], `context snapshot ${index2}.query.query`), ...scope ? { scope } : {}, ...typeof rawQuery["sourceRevision"] === "string" ? { sourceRevision: rawQuery["sourceRevision"] } : {} },
574
711
  references,
575
712
  sourceHash: requiredString(raw["sourceHash"], `context snapshot ${index2}.sourceHash`),
576
713
  snapshotHash: requiredString(raw["snapshotHash"], `context snapshot ${index2}.snapshotHash`),
577
- resolvedAt: requiredString(raw["resolvedAt"], `context snapshot ${index2}.resolvedAt`)
714
+ resolvedAt: requiredString(raw["resolvedAt"], `context snapshot ${index2}.resolvedAt`),
715
+ ...assurance === void 0 ? {} : { assurance },
716
+ ...telemetry === void 0 ? {} : { telemetry }
578
717
  };
579
718
  if (snapshot.snapshotHash !== hashContextSnapshot(snapshot)) fail(`context snapshot ${index2}.snapshotHash does not match its contents.`, "INVALID_INPUT");
580
719
  return snapshot;
@@ -586,7 +725,7 @@ var readContextSnapshots = (path) => {
586
725
  var validateContextSnapshots = (snapshots) => snapshots.map((snapshot, index2) => validateContextSnapshot(snapshot, index2));
587
726
  var CONTEXT_PROVIDER_SLOT = createPluginSlot("context.provider");
588
727
 
589
- // src/runs.ts
728
+ // src/execution/runs.ts
590
729
  var now = () => (/* @__PURE__ */ new Date()).toISOString();
591
730
  var newRunId = () => `${Date.now()}-${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
592
731
  var saveRun2 = (stateDir, run) => {
@@ -643,8 +782,8 @@ var parseStructuredEvidence = (stdout) => {
643
782
  }
644
783
  return null;
645
784
  };
646
- var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
647
- var viewportValid = (viewport) => typeof viewport === "string" || isRecord3(viewport) && typeof viewport["width"] === "number" && viewport["width"] > 0 && typeof viewport["height"] === "number" && viewport["height"] > 0;
785
+ var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
786
+ var viewportValid = (viewport) => typeof viewport === "string" || isRecord4(viewport) && typeof viewport["width"] === "number" && viewport["width"] > 0 && typeof viewport["height"] === "number" && viewport["height"] > 0;
648
787
  var validateEvidence = (root, check, evidence, outcomeIds) => {
649
788
  if (!evidence || evidence.status !== "passed") return ["structured evidence did not pass"];
650
789
  if (!Array.isArray(evidence.criteria) || !evidence.criteria.every((id2) => typeof id2 === "string") || outcomeIds.some((id2) => !evidence.criteria.includes(id2))) return [`evidence must map criteria: ${outcomeIds.join(", ")}`];
@@ -655,7 +794,7 @@ var validateEvidence = (root, check, evidence, outcomeIds) => {
655
794
  }
656
795
  const artifacts = Array.isArray(evidence.artifacts) ? evidence.artifacts : [];
657
796
  for (const artifactValue of artifacts) {
658
- if (!isRecord3(artifactValue) || typeof artifactValue["path"] !== "string" || typeof artifactValue["sha256"] !== "string") {
797
+ if (!isRecord4(artifactValue) || typeof artifactValue["path"] !== "string" || typeof artifactValue["sha256"] !== "string") {
659
798
  failures.push("artifact requires string path and sha256");
660
799
  continue;
661
800
  }
@@ -770,7 +909,7 @@ var createMachineMonitor = (sampleIntervalMs = 5e3, options = {}) => {
770
909
  };
771
910
  };
772
911
 
773
- // src/verification.ts
912
+ // src/execution/verification.ts
774
913
  var now2 = () => (/* @__PURE__ */ new Date()).toISOString();
775
914
  var requireRun = (run) => run ?? fail("No verification run exists.", "NO_RUN");
776
915
  var verificationProjection = (run) => ({ checks: run.checks, outcomes: run.outcomes, metrics: run.metrics });
@@ -912,13 +1051,13 @@ var verifyRun = async ({ configPath }) => {
912
1051
  const budgetExceeded = loaded.config.budget?.maxDurationMs !== void 0 && totalDurationMs > loaded.config.budget.maxDurationMs;
913
1052
  const allPassed = loaded.config.checks.every((check) => !check.required || statuses.get(check.id) === "passed") && !budgetExceeded;
914
1053
  current = { ...current, outcomes: current.outcomes.map((outcome) => {
915
- const required15 = outcome.checks.filter((id2) => loaded.config.checks.find((check) => check.id === id2)?.required);
916
- return { ...outcome, status: required15.length === 0 ? "not-applicable" : required15.every((id2) => statuses.get(id2) === "passed") ? "passed" : "failed" };
1054
+ const required16 = outcome.checks.filter((id2) => loaded.config.checks.find((check) => check.id === id2)?.required);
1055
+ return { ...outcome, status: required16.length === 0 ? "not-applicable" : required16.every((id2) => statuses.get(id2) === "passed") ? "passed" : "failed" };
917
1056
  }), metrics: { totalDurationMs, wallDurationMs: Date.now() - verificationStarted, peakConcurrency: observedPeakConcurrency, budgetExceeded, machine: machineMonitor.stop() } };
918
- const digest3 = verificationDigest(current);
919
- current = { ...current, verificationDigest: digest3 };
1057
+ const digest6 = verificationDigest(current);
1058
+ current = { ...current, verificationDigest: digest6 };
920
1059
  saveRun2(loaded.stateDir, current);
921
- new FileEventStore(loaded.stateDir).append({ runId: current.runId, sourceRevision: current.sourceRevision, configHash: current.configHash, type: "verification.completed", payload: { verificationDigest: digest3, checkCount: current.checks.length, outcomeCount: current.outcomes.length, totalDurationMs, budgetExceeded } });
1060
+ new FileEventStore(loaded.stateDir).append({ runId: current.runId, sourceRevision: current.sourceRevision, configHash: current.configHash, type: "verification.completed", payload: { verificationDigest: digest6, checkCount: current.checks.length, outcomeCount: current.outcomes.length, totalDurationMs, budgetExceeded } });
922
1061
  const automatic = allPassed && current.autonomy === "yolo" && !loaded.config.tracking.required && loaded.config.contract.ambiguities.length === 0;
923
1062
  const nextState = allPassed ? automatic ? "COMPLETE" : "AWAITING_HUMAN_APPROVAL" : "BLOCKED";
924
1063
  current = { ...transition(current, nextState, automatic ? "All applicable checks passed; YOLO policy permits automatic completion." : allPassed ? "All configured checks passed; human approval is required." : budgetExceeded ? "Verification budget was exceeded." : "A configured check failed or lacked structured evidence.", "harness") };
@@ -1023,6 +1162,70 @@ var retryRun = async ({ configPath }) => {
1023
1162
  return next;
1024
1163
  };
1025
1164
  var cleanTaskArtifacts = (configPath) => cleanConfiguredArtifacts(loadConfig(configPath));
1165
+
1166
+ // src/kernel/capabilities.ts
1167
+ var CAPABILITY_MANIFEST_SCHEMA_VERSION = 1;
1168
+ var CAPABILITY_KINDS = ["kernel", "execution", "adapter", "composition"];
1169
+ var nonEmpty2 = (value, label) => {
1170
+ if (typeof value !== "string") fail(`${label} is required.`, "INVALID_INPUT");
1171
+ const result = value.trim();
1172
+ if (!result) fail(`${label} is required.`, "INVALID_INPUT");
1173
+ return result;
1174
+ };
1175
+ var digest2 = (value, label) => {
1176
+ const result = nonEmpty2(value, label);
1177
+ if (!/^[a-f0-9]{64}$/.test(result)) fail(`${label} must be a lowercase SHA-256 digest.`, "INVALID_INPUT");
1178
+ return result;
1179
+ };
1180
+ var stringList = (value, label) => {
1181
+ if (!Array.isArray(value)) fail(`${label} must be a non-empty string array.`, "INVALID_INPUT");
1182
+ if (!value.length) fail(`${label} must be a non-empty string array.`, "INVALID_INPUT");
1183
+ const items = value;
1184
+ const result = items.map((item, index2) => nonEmpty2(item, `${label}[${index2}]`));
1185
+ if (new Set(result).size !== result.length) fail(`${label} must not contain duplicates.`, "INVALID_INPUT");
1186
+ return result;
1187
+ };
1188
+ var descriptor = (value, index2) => {
1189
+ if (typeof value !== "object" || value === null || Array.isArray(value)) fail(`capabilities[${index2}] must be an object.`, "INVALID_INPUT");
1190
+ const candidate = value;
1191
+ const kind = candidate["kind"];
1192
+ if (typeof kind !== "string" || !CAPABILITY_KINDS.includes(kind)) fail(`capabilities[${index2}].kind is invalid.`, "INVALID_INPUT");
1193
+ const dependencies = candidate["dependencies"] === void 0 ? void 0 : stringList(candidate["dependencies"], `capabilities[${index2}].dependencies`);
1194
+ return {
1195
+ id: nonEmpty2(candidate["id"], `capabilities[${index2}].id`),
1196
+ version: nonEmpty2(candidate["version"], `capabilities[${index2}].version`),
1197
+ kind,
1198
+ entryPoint: nonEmpty2(candidate["entryPoint"], `capabilities[${index2}].entryPoint`),
1199
+ exports: stringList(candidate["exports"], `capabilities[${index2}].exports`),
1200
+ ...dependencies === void 0 ? {} : { dependencies }
1201
+ };
1202
+ };
1203
+ var manifestBody = (input) => ({
1204
+ type: "agentskit-harness-capability-manifest",
1205
+ schemaVersion: CAPABILITY_MANIFEST_SCHEMA_VERSION,
1206
+ package: nonEmpty2(input.package, "package"),
1207
+ packageVersion: nonEmpty2(input.packageVersion, "packageVersion"),
1208
+ entryPoint: nonEmpty2(input.entryPoint, "entryPoint"),
1209
+ sourceDigest: digest2(input.sourceDigest, "sourceDigest"),
1210
+ capabilities: (Array.isArray(input.capabilities) ? input.capabilities : fail("capabilities must be an array.", "INVALID_INPUT")).map(descriptor)
1211
+ });
1212
+ var createCapabilityManifest = (input) => {
1213
+ const body3 = manifestBody(input);
1214
+ if (!body3.capabilities.length) fail("capabilities must be non-empty.", "INVALID_INPUT");
1215
+ if (new Set(body3.capabilities.map((item) => item.id)).size !== body3.capabilities.length) fail("capability ids must be unique.", "INVALID_INPUT");
1216
+ return { ...body3, digest: hashJson(body3) };
1217
+ };
1218
+ var validateCapabilityManifest = (value) => {
1219
+ if (typeof value !== "object" || value === null || Array.isArray(value)) fail("Capability manifest must be an object.", "INVALID_INPUT");
1220
+ const candidate = value;
1221
+ const capabilities = Array.isArray(candidate["capabilities"]) ? candidate["capabilities"] : fail("capabilities must be an array.", "INVALID_INPUT");
1222
+ const body3 = manifestBody({ package: nonEmpty2(candidate["package"], "package"), packageVersion: nonEmpty2(candidate["packageVersion"], "packageVersion"), entryPoint: nonEmpty2(candidate["entryPoint"], "entryPoint"), sourceDigest: digest2(candidate["sourceDigest"], "sourceDigest"), capabilities });
1223
+ if (new Set(body3.capabilities.map((item) => item.id)).size !== body3.capabilities.length) fail("capability ids must be unique.", "INVALID_INPUT");
1224
+ if (candidate["type"] !== body3.type || candidate["schemaVersion"] !== body3.schemaVersion) fail("Capability manifest type or schemaVersion is invalid.", "INVALID_INPUT");
1225
+ const manifestDigest = digest2(candidate["digest"], "digest");
1226
+ if (manifestDigest !== hashJson(body3)) fail("Capability manifest digest is invalid.", "INVALID_INPUT");
1227
+ return { ...body3, digest: manifestDigest };
1228
+ };
1026
1229
  var index = (root, indexPath) => JSON.parse(readFileSync(resolve(root, indexPath), "utf8"));
1027
1230
  var text = (entry) => [entry.id, entry.type, entry.title, entry.path, entry.description, entry.body, ...Array.isArray(entry.tags) ? entry.tags : []].filter((value) => typeof value === "string").join(" ").toLowerCase();
1028
1231
  var sourceHash = (document) => typeof document.contentHash === "string" && document.contentHash.length > 0 ? document.contentHash : hashJson(document);
@@ -1036,15 +1239,17 @@ var createDocBridgeContextProvider = ({ root, indexPath = ".doc-bridge/index.jso
1036
1239
  id: "doc-bridge",
1037
1240
  version: "1.0.0",
1038
1241
  resolve: async (query) => {
1242
+ const started = Date.now();
1039
1243
  const document = index(root, indexPath);
1040
1244
  const contentHash = sourceHash(document);
1041
1245
  const entries = Array.isArray(document.knowledge) ? document.knowledge.filter((value) => typeof value === "object" && value !== null && !Array.isArray(value)).filter((entry) => matches(entry, query)).sort((left, right) => String(left.id ?? "").localeCompare(String(right.id ?? ""))).slice(0, 8) : [];
1042
- const references = entries.flatMap((entry) => typeof entry.id === "string" && typeof entry.path === "string" ? [{ id: entry.id, uri: `doc-bridge://${entry.path}`, ...typeof entry.title === "string" ? { title: entry.title } : {}, contentHash }] : []);
1043
- return { providerId: "doc-bridge", query, references, sourceHash: contentHash, snapshotHash: hashContextSnapshot({ providerId: "doc-bridge", query, references, sourceHash: contentHash }), resolvedAt: (/* @__PURE__ */ new Date()).toISOString() };
1246
+ const references = entries.flatMap((entry) => typeof entry.id === "string" && typeof entry.path === "string" ? [{ id: entry.id, uri: `doc-bridge://${entry.path}`, ...typeof entry.title === "string" ? { title: entry.title } : {}, contentHash: typeof entry.contentHash === "string" ? entry.contentHash : contentHash, relevance: 1 }] : []);
1247
+ const telemetry = { status: "measured", durationMs: Date.now() - started, contextReferences: references.length, contextCostTokens: Math.max(1, Math.ceil(JSON.stringify(references).length / 4)) };
1248
+ return { providerId: "doc-bridge", query, references, sourceHash: contentHash, snapshotHash: hashContextSnapshot({ providerId: "doc-bridge", query, references, sourceHash: contentHash }), resolvedAt: (/* @__PURE__ */ new Date()).toISOString(), assurance: "contract-tested", telemetry };
1044
1249
  }
1045
1250
  });
1046
1251
 
1047
- // src/discovery.ts
1252
+ // src/kernel/discovery.ts
1048
1253
  var required = (value, label) => {
1049
1254
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
1050
1255
  return value.trim();
@@ -1078,7 +1283,7 @@ var validate = (input) => {
1078
1283
  }
1079
1284
  return { assumptions };
1080
1285
  };
1081
- var digest2 = (result) => hashJson(result);
1286
+ var digest3 = (result) => hashJson(result);
1082
1287
  var assessDiscovery = (input) => {
1083
1288
  const { assumptions } = validate(input);
1084
1289
  const human = input.ambiguities.filter((ambiguity) => ambiguity.material);
@@ -1103,7 +1308,7 @@ var assessDiscovery = (input) => {
1103
1308
  } } : {},
1104
1309
  decisionLog
1105
1310
  };
1106
- return { ...base, digest: digest2(base) };
1311
+ return { ...base, digest: digest3(base) };
1107
1312
  };
1108
1313
  var isDiscoveryCurrent = (result, current) => {
1109
1314
  const reasons = [];
@@ -1113,7 +1318,7 @@ var isDiscoveryCurrent = (result, current) => {
1113
1318
  return { current: reasons.length === 0, reasons };
1114
1319
  };
1115
1320
 
1116
- // src/wip.ts
1321
+ // src/kernel/wip.ts
1117
1322
  var WIP_STATES = ["ready", "implementing", "blocked", "awaiting-decision", "awaiting-acceptance", "done", "cancelled"];
1118
1323
  var terminal = /* @__PURE__ */ new Set(["done", "cancelled"]);
1119
1324
  var required2 = (value, label) => {
@@ -1145,7 +1350,7 @@ var assessWip = ({ entries, candidate, maxInFlight = 3 }) => {
1145
1350
  return { decision: "admit", inFlight, counts, reason: `WIP slot available (${inFlight.length}/${maxInFlight}).` };
1146
1351
  };
1147
1352
 
1148
- // src/experiment.ts
1353
+ // src/kernel/experiment.ts
1149
1354
  var required3 = (value, label) => {
1150
1355
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
1151
1356
  return value.trim();
@@ -1157,11 +1362,11 @@ var comparable = (candidate, baseline) => {
1157
1362
  };
1158
1363
  var selectRuntime = (candidates) => {
1159
1364
  if (!Array.isArray(candidates) || candidates.length < 2) fail("At least two runtime candidates are required.", "INVALID_INPUT");
1160
- const names = /* @__PURE__ */ new Set();
1365
+ const names2 = /* @__PURE__ */ new Set();
1161
1366
  for (const candidate of candidates) {
1162
1367
  const runtime = required3(candidate.runtime, "candidate.runtime");
1163
- if (names.has(runtime)) fail("candidate.runtime values must be unique.", "INVALID_INPUT");
1164
- names.add(runtime);
1368
+ if (names2.has(runtime)) fail("candidate.runtime values must be unique.", "INVALID_INPUT");
1369
+ names2.add(runtime);
1165
1370
  for (const key of ["sourceRevision", "contractHash", "provider", "model", "configurationHash"]) required3(candidate[key], `candidate.${key}`);
1166
1371
  for (const key of ["humanMinutes", "durationMs", "cost"]) if (!Number.isFinite(candidate[key]) || candidate[key] < 0) fail(`candidate.${key} must be a non-negative number.`, "INVALID_INPUT");
1167
1372
  comparable(candidate, candidates[0]);
@@ -1172,7 +1377,92 @@ var selectRuntime = (candidates) => {
1172
1377
  return { decision: "selected", selected, eligible, reason: "Selected by human minutes, duration, cost, then Orca tie-break." };
1173
1378
  };
1174
1379
 
1175
- // src/delivery.ts
1380
+ // src/kernel/workflow.ts
1381
+ var validId2 = (id2) => {
1382
+ if (typeof id2 !== "string" || !id2.trim()) fail("Workflow node id must be non-empty.", "INVALID_INPUT");
1383
+ return id2.trim();
1384
+ };
1385
+ var levels = (nodes) => {
1386
+ const byId = new Map(nodes.map((node) => [validId2(node.id), node]));
1387
+ if (byId.size !== nodes.length) fail("Workflow node ids must be unique.", "INVALID_INPUT");
1388
+ const remaining = new Set(byId.keys());
1389
+ const completed = /* @__PURE__ */ new Set();
1390
+ const result = [];
1391
+ while (remaining.size) {
1392
+ const ready = [...remaining].sort().map((id2) => byId.get(id2)).filter((node) => (node.dependsOn ?? []).every((dependency) => completed.has(dependency)));
1393
+ if (!ready.length) fail("Workflow contains an unknown dependency or cycle.", "INVALID_INPUT");
1394
+ result.push(ready);
1395
+ for (const node of ready) {
1396
+ remaining.delete(node.id);
1397
+ completed.add(node.id);
1398
+ }
1399
+ }
1400
+ return result;
1401
+ };
1402
+ var runWorkflow = async (nodes, options) => {
1403
+ if (!Number.isInteger(options.maxConcurrency) || options.maxConcurrency < 1) fail("maxConcurrency must be a positive integer.", "INVALID_INPUT");
1404
+ const started = Date.now();
1405
+ const results = {};
1406
+ const order = [];
1407
+ let peakConcurrency = 0;
1408
+ for (const level of levels(nodes)) {
1409
+ const remaining = [...level];
1410
+ while (remaining.length) {
1411
+ const batch = [];
1412
+ const keys = /* @__PURE__ */ new Set();
1413
+ const limit = options.currentConcurrency ? options.currentConcurrency() : options.maxConcurrency;
1414
+ if (!Number.isInteger(limit) || limit < 1) fail("currentConcurrency must return a positive integer.", "INVALID_INPUT");
1415
+ for (const node of remaining) {
1416
+ const key = node.mutationKey?.trim();
1417
+ if (batch.length >= limit || key && keys.has(key)) continue;
1418
+ batch.push(node);
1419
+ if (key) keys.add(key);
1420
+ }
1421
+ if (!batch.length) fail("Workflow could not schedule a mutation batch.", "INVALID_INPUT");
1422
+ peakConcurrency = Math.max(peakConcurrency, batch.length);
1423
+ const values = await Promise.all(batch.map((node) => node.run()));
1424
+ batch.forEach((node, index2) => {
1425
+ results[node.id] = values[index2];
1426
+ order.push(node.id);
1427
+ });
1428
+ for (const node of batch) remaining.splice(remaining.indexOf(node), 1);
1429
+ }
1430
+ }
1431
+ return { results, order, peakConcurrency, criticalPathMs: Date.now() - started };
1432
+ };
1433
+
1434
+ // src/delivery/review.ts
1435
+ var runAdversarialReview = async ({ lenses, reviewer, binding: binding2, maxConcurrency = 3 }) => {
1436
+ if (!Array.isArray(lenses) || lenses.length === 0) fail("At least one review lens is required.", "INVALID_INPUT");
1437
+ if (!Number.isInteger(maxConcurrency) || maxConcurrency < 1) fail("maxConcurrency must be a positive integer.", "INVALID_INPUT");
1438
+ const normalized = lenses.map((lens) => {
1439
+ if (typeof lens !== "object" || lens === null || Array.isArray(lens) || typeof lens.id !== "string" || !lens.id.trim()) fail("Review lens id is required.", "INVALID_INPUT");
1440
+ const maxAttempts = lens.maxAttempts ?? 1;
1441
+ if (!Number.isInteger(maxAttempts) || maxAttempts < 1 || maxAttempts > 3) fail("Review lens maxAttempts must be between 1 and 3.", "INVALID_INPUT");
1442
+ return { id: lens.id.trim(), maxAttempts };
1443
+ });
1444
+ if (new Set(normalized.map((lens) => lens.id)).size !== normalized.length) fail("Review lens ids must be unique.", "INVALID_INPUT");
1445
+ const workflow = await runWorkflow(normalized.map((lens) => ({ id: lens.id, run: async () => {
1446
+ let last = { status: "unverified", reason: "Reviewer returned no verdict." };
1447
+ for (let attempt = 1; attempt <= lens.maxAttempts; attempt += 1) {
1448
+ try {
1449
+ const verdict = await reviewer(lens, attempt);
1450
+ if (!verdict || !["pass", "finding", "unverified"].includes(verdict.status)) return { status: "unverified", reason: "Reviewer returned an invalid verdict." };
1451
+ last = verdict;
1452
+ if (verdict.status !== "unverified" || verdict.retryable !== true) return verdict;
1453
+ } catch (error) {
1454
+ last = { status: "unverified", reason: error instanceof Error ? error.message : String(error) };
1455
+ }
1456
+ }
1457
+ return last;
1458
+ } })), { maxConcurrency });
1459
+ const verdicts = Object.fromEntries(Object.entries(workflow.results).sort(([left], [right]) => left.localeCompare(right)));
1460
+ const reasons = Object.entries(verdicts).flatMap(([id2, verdict]) => verdict.status === "pass" ? [] : verdict.status === "finding" && (verdict.evidence?.trim() || verdict.reproduction?.trim()) ? [`${id2} found an issue: ${verdict.reason ?? "evidence recorded"}.`] : [`${id2} is unverified or lacks reproducible evidence.`]);
1461
+ const base = { verdicts, reasons, binding: binding2, peakConcurrency: workflow.peakConcurrency };
1462
+ return { decision: reasons.length ? "blocked" : "approved", ...base, digest: hashJson(base) };
1463
+ };
1464
+
1465
+ // src/delivery/index.ts
1176
1466
  var required4 = (value, label) => {
1177
1467
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
1178
1468
  return value.trim();
@@ -1216,8 +1506,26 @@ var composePullRequest = ({ draft, g2, remote }) => {
1216
1506
  if (remote.candidateRevision !== draft.candidateRevision || !remote.url) return { decision: "blocked", reason: "Confirmed remote PR does not match the candidate revision.", idempotencyKey };
1217
1507
  return { decision: "reuse", reason: "The idempotent remote PR already exists for this candidate revision.", idempotencyKey };
1218
1508
  }
1219
- const body2 = [`## Contract`, `- Issue: ${draft.issueId}`, `- Candidate: ${draft.candidateRevision}`, `- Contract: ${draft.contractHash}`, `- Configuration: ${draft.configHash}`, "", "## G2 evidence", ...draft.evidence.map((item) => `- ${item}`), "", "## Documentation", ...draft.documentation.map((item) => `- ${item}`), "", "## Risk and rollback", `- Risk: ${draft.risk}`, `- Rollback: ${draft.rollback}`, "", "## Later gates", ...draft.pendingCriteria.length ? draft.pendingCriteria.map((item) => `- Pending: ${item}`) : ["- None."]].join("\n");
1220
- return { decision: "create", body: body2, reason: "G2 is current and the remote PR is absent.", idempotencyKey };
1509
+ const body3 = [`## Contract`, `- Issue: ${draft.issueId}`, `- Candidate: ${draft.candidateRevision}`, `- Contract: ${draft.contractHash}`, `- Configuration: ${draft.configHash}`, "", "## G2 evidence", ...draft.evidence.map((item) => `- ${item}`), "", "## Documentation", ...draft.documentation.map((item) => `- ${item}`), "", "## Risk and rollback", `- Risk: ${draft.risk}`, `- Rollback: ${draft.rollback}`, "", "## Later gates", ...draft.pendingCriteria.length ? draft.pendingCriteria.map((item) => `- Pending: ${item}`) : ["- None."]].join("\n");
1510
+ return { decision: "create", body: body3, reason: "G2 is current and the remote PR is absent.", idempotencyKey };
1511
+ };
1512
+ var createPullRequestApproval = ({ body: body3, metadata, approvedBy, candidateRevision, contractHash, configHash }) => {
1513
+ if (approvedBy !== "human") fail("Pull request approval requires a human actor.", "HUMAN_APPROVAL_REQUIRED");
1514
+ const normalizedBody = required4(body3, "PR body");
1515
+ const binding2 = { approvedBy, candidateRevision: required4(candidateRevision, "candidateRevision"), contractHash: required4(contractHash, "contractHash"), configHash: required4(configHash, "configHash"), bodyHash: hashJson(normalizedBody), metadataHash: hashJson(metadata) };
1516
+ return { ...binding2, digest: hashJson(binding2) };
1517
+ };
1518
+ var verifyPullRequestApproval = ({ approval, body: body3, metadata, candidateRevision, contractHash, configHash }) => {
1519
+ const expected = createPullRequestApproval({ body: body3, metadata, approvedBy: "human", candidateRevision, contractHash, configHash });
1520
+ if (approval.digest !== expected.digest || approval.bodyHash !== expected.bodyHash || approval.metadataHash !== expected.metadataHash) fail("Approved pull request content or metadata changed.", "STALE");
1521
+ return approval;
1522
+ };
1523
+ var assessQaTransition = ({ featureValidated, g5, qaPassed, issue }) => {
1524
+ required4(issue, "issue");
1525
+ const base = { issue, featureValidated, g5: g5.digest, qaPassed };
1526
+ if (!featureValidated || g5.gate !== "G5" || g5.decision !== "approved") return { decision: "blocked", target: "verification", invalidatesDownstream: false, reason: "Feature validation and approved G5 acceptance are required before moving the issue to QA.", idempotencyKey: hashJson(base) };
1527
+ if (!qaPassed) return { decision: "return-to-verification", target: "verification", invalidatesDownstream: true, reason: "QA failed; downstream evidence is invalidated and verification must be repeated.", idempotencyKey: hashJson(base) };
1528
+ return { decision: "move-to-qa", target: "qa", invalidatesDownstream: false, reason: "Feature validation and G5 acceptance are current.", idempotencyKey: hashJson(base) };
1221
1529
  };
1222
1530
  var assessIntegration = ({ g2, candidateRevision, evidenceRevision, contractHash, configHash, ci }) => {
1223
1531
  required4(candidateRevision, "candidateRevision");
@@ -1267,7 +1575,7 @@ var assessAcceptance = ({ production, acceptanceRequired, accepted, notApplicabl
1267
1575
  return assessed("G5", "approved", acceptanceRequired ? [] : [`Acceptance is not applicable: ${notApplicableReason}.`], production.binding);
1268
1576
  };
1269
1577
 
1270
- // src/pilot.ts
1578
+ // src/kernel/pilot.ts
1271
1579
  var required5 = (value, label) => {
1272
1580
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
1273
1581
  return value.trim();
@@ -1296,7 +1604,7 @@ var assessPilot = (manifest) => {
1296
1604
  return { ...base, digest: hashJson({ ...manifest, ...base }) };
1297
1605
  };
1298
1606
  var IMPROVEMENT_CYCLE_STEPS = ["adversarial-review", "g2-preflight", "baseline-record", "pilot-execution", "comparison"];
1299
- var nonEmpty = (value, label) => {
1607
+ var nonEmpty3 = (value, label) => {
1300
1608
  if (typeof value !== "string" || !value.trim()) return fail(`${label} must be a non-empty string.`, "INVALID_INPUT");
1301
1609
  return value.trim();
1302
1610
  };
@@ -1315,14 +1623,14 @@ var validateIteration = (iteration, index2) => {
1315
1623
  if (typeof result !== "object" || result === null || Array.isArray(result)) return fail(`iterations[${index2}].steps[${stepIndex}] must be an object.`, "INVALID_INPUT");
1316
1624
  if (result.step !== IMPROVEMENT_CYCLE_STEPS[stepIndex]) return fail(`iterations[${index2}].steps[${stepIndex}] must be ${IMPROVEMENT_CYCLE_STEPS[stepIndex]}.`, "INVALID_INPUT");
1317
1625
  if (!["passed", "failed", "blocked", "pending"].includes(result.status)) return fail(`iterations[${index2}].steps[${stepIndex}].status is invalid.`, "INVALID_INPUT");
1318
- if (result.status !== "passed" && !nonEmpty(result.reason, `iterations[${index2}].steps[${stepIndex}].reason`)) return fail(`iterations[${index2}].steps[${stepIndex}].reason is required when the step does not pass.`, "INVALID_INPUT");
1626
+ if (result.status !== "passed" && !nonEmpty3(result.reason, `iterations[${index2}].steps[${stepIndex}].reason`)) return fail(`iterations[${index2}].steps[${stepIndex}].reason is required when the step does not pass.`, "INVALID_INPUT");
1319
1627
  });
1320
- if (iteration.adjustment !== void 0) nonEmpty(iteration.adjustment, `iterations[${index2}].adjustment`);
1628
+ if (iteration.adjustment !== void 0) nonEmpty3(iteration.adjustment, `iterations[${index2}].adjustment`);
1321
1629
  return { ...iteration, metrics: validateMetrics(iteration.metrics, index2) };
1322
1630
  };
1323
1631
  var assessImprovementCycle = (input) => {
1324
1632
  if (typeof input !== "object" || input === null || Array.isArray(input)) return fail("cycle input must be an object.", "INVALID_INPUT");
1325
- const cycleId = nonEmpty(input.cycleId, "cycleId");
1633
+ const cycleId = nonEmpty3(input.cycleId, "cycleId");
1326
1634
  if (!Number.isInteger(input.maxIterations) || input.maxIterations < 1) return fail("maxIterations must be a positive integer.", "INVALID_INPUT");
1327
1635
  if (!Array.isArray(input.iterations) || input.iterations.length < 1) return fail("iterations must be non-empty.", "INVALID_INPUT");
1328
1636
  if (input.iterations.length > input.maxIterations) return fail("iterations cannot exceed maxIterations.", "INVALID_INPUT");
@@ -1342,11 +1650,129 @@ var assessImprovementCycle = (input) => {
1342
1650
  const reasons = complete ? ["All five cycle steps passed."] : iterations.length >= input.maxIterations ? ["Maximum cycle iterations reached; human adjustment is required."] : latest.adjustment ? ["A failed or blocked step remains; repeat with the recorded adjustment."] : ["A failed or blocked step remains; an explicit adjustment is required before repeating."];
1343
1651
  const decision = complete ? "complete" : iterations.length >= input.maxIterations || !latest.adjustment ? "blocked" : "repeat";
1344
1652
  const result = { type: "agentskit-harness-improvement-cycle", cycleId, decision, ...decision === "repeat" ? { nextIteration: latest.iteration + 1 } : {}, reasons, matrix };
1345
- const digest3 = createHash("sha256").update(JSON.stringify(result)).digest("hex");
1346
- return { ...result, digest: digest3 };
1653
+ const digest6 = createHash("sha256").update(JSON.stringify(result)).digest("hex");
1654
+ return { ...result, digest: digest6 };
1347
1655
  };
1348
1656
 
1349
- // src/eval.ts
1657
+ // src/kernel/eval.ts
1658
+ var EVAL_MANIFEST_SCHEMA_VERSION = 1;
1659
+ var EVAL_LAYERS = ["contract", "deterministic", "integration", "quality", "regression", "resource"];
1660
+ var EVAL_COMPONENTS = ["core", "workflow", "memory", "cache", "doc-bridge", "agent-model", "orca-worktree", "runtime", "code-review", "github-linear", "eval-metrics"];
1661
+ var nonEmpty4 = (value, label) => {
1662
+ const text7 = typeof value === "string" ? value.trim() : "";
1663
+ if (!text7) fail(`${label} is required.`, "INVALID_INPUT");
1664
+ return text7;
1665
+ };
1666
+ var digest4 = (value, label) => {
1667
+ const result = nonEmpty4(value, label);
1668
+ if (!/^[a-f0-9]{64}$/.test(result)) fail(`${label} must be a lowercase SHA-256 digest.`, "INVALID_INPUT");
1669
+ return result;
1670
+ };
1671
+ var score = (value, label) => {
1672
+ const numeric = typeof value === "number" ? value : Number.NaN;
1673
+ if (!Number.isFinite(numeric) || numeric < 0 || numeric > 100) fail(`${label} must be a number between 0 and 100.`, "INVALID_INPUT");
1674
+ return numeric;
1675
+ };
1676
+ var validateCase = (value, index2) => {
1677
+ if (typeof value !== "object" || value === null || Array.isArray(value)) fail(`cases[${index2}] must be an object.`, "INVALID_INPUT");
1678
+ const candidate = value;
1679
+ const layer = nonEmpty4(candidate["layer"], `cases[${index2}].layer`);
1680
+ if (!EVAL_LAYERS.includes(layer)) fail(`cases[${index2}].layer is invalid.`, "INVALID_INPUT");
1681
+ const components = candidate["components"];
1682
+ if (!Array.isArray(components) || !components.length) fail(`cases[${index2}].components must be a non-empty array.`, "INVALID_INPUT");
1683
+ const normalizedComponents = components.map((item, componentIndex) => {
1684
+ const component2 = nonEmpty4(item, `cases[${index2}].components[${componentIndex}]`);
1685
+ if (!EVAL_COMPONENTS.includes(component2)) fail(`cases[${index2}].components[${componentIndex}] is invalid.`, "INVALID_INPUT");
1686
+ return component2;
1687
+ });
1688
+ if (new Set(normalizedComponents).size !== normalizedComponents.length) fail(`cases[${index2}].components must not contain duplicates.`, "INVALID_INPUT");
1689
+ const baselineScore = candidate["baselineScore"] === void 0 ? void 0 : score(candidate["baselineScore"], `cases[${index2}].baselineScore`);
1690
+ return {
1691
+ id: nonEmpty4(candidate["id"], `cases[${index2}].id`),
1692
+ layer,
1693
+ components: normalizedComponents,
1694
+ grader: nonEmpty4(candidate["grader"], `cases[${index2}].grader`),
1695
+ input: nonEmpty4(candidate["input"], `cases[${index2}].input`),
1696
+ ...candidate["critical"] === void 0 ? {} : { critical: candidate["critical"] === true },
1697
+ ...candidate["subjective"] === void 0 ? {} : { subjective: candidate["subjective"] === true },
1698
+ ...baselineScore === void 0 ? {} : { baselineScore }
1699
+ };
1700
+ };
1701
+ var manifestBody2 = (value) => {
1702
+ const casesValue = value["cases"];
1703
+ if (!Array.isArray(casesValue) || !casesValue.length) fail("cases must be a non-empty array.", "INVALID_INPUT");
1704
+ const cases = casesValue.map(validateCase);
1705
+ if (new Set(cases.map((item) => item.id)).size !== cases.length) fail("case ids must be unique.", "INVALID_INPUT");
1706
+ const layers = new Set(cases.map((item) => item.layer));
1707
+ const missingLayers = EVAL_LAYERS.filter((layer) => !layers.has(layer));
1708
+ if (missingLayers.length) fail(`cases must cover layers: ${missingLayers.join(", ")}.`, "INVALID_INPUT");
1709
+ const coveredComponents = new Set(cases.flatMap((item) => item.components));
1710
+ const missingComponents = EVAL_COMPONENTS.filter((component2) => !coveredComponents.has(component2));
1711
+ if (missingComponents.length) fail(`cases must cover components: ${missingComponents.join(", ")}.`, "INVALID_INPUT");
1712
+ const gradersValue = value["graders"];
1713
+ if (!Array.isArray(gradersValue) || !gradersValue.length) fail("graders must be a non-empty array.", "INVALID_INPUT");
1714
+ const graders = gradersValue.map((item, index2) => nonEmpty4(item, `graders[${index2}]`));
1715
+ const thresholdsValue = value["thresholds"];
1716
+ if (typeof thresholdsValue !== "object" || thresholdsValue === null || Array.isArray(thresholdsValue)) fail("thresholds must be an object.", "INVALID_INPUT");
1717
+ const thresholds2 = thresholdsValue;
1718
+ const repetitions = value["repetitions"];
1719
+ if (!Number.isInteger(repetitions) || repetitions < 1) fail("repetitions must be a positive integer.", "INVALID_INPUT");
1720
+ return {
1721
+ type: "agentskit-harness-eval-manifest",
1722
+ schemaVersion: EVAL_MANIFEST_SCHEMA_VERSION,
1723
+ suiteId: nonEmpty4(value["suiteId"], "suiteId"),
1724
+ name: nonEmpty4(value["name"], "name"),
1725
+ cases,
1726
+ graders,
1727
+ thresholds: { subjectiveQuality: score(thresholds2["subjectiveQuality"] ?? 80, "thresholds.subjectiveQuality"), maxRegression: score(thresholds2["maxRegression"] ?? 5, "thresholds.maxRegression") },
1728
+ repetitions,
1729
+ provider: nonEmpty4(value["provider"], "provider"),
1730
+ model: nonEmpty4(value["model"], "model"),
1731
+ promptHash: digest4(value["promptHash"], "promptHash"),
1732
+ toolHash: digest4(value["toolHash"], "toolHash"),
1733
+ evidenceOutputs: Array.isArray(value["evidenceOutputs"]) && value["evidenceOutputs"].length ? value["evidenceOutputs"].map((item, index2) => nonEmpty4(item, `evidenceOutputs[${index2}]`)) : fail("evidenceOutputs must be a non-empty array.", "INVALID_INPUT")
1734
+ };
1735
+ };
1736
+ var createEvalManifest = (input) => {
1737
+ const body3 = manifestBody2(input);
1738
+ return { ...body3, digest: hashJson(body3) };
1739
+ };
1740
+ var validateEvalManifest = (value) => {
1741
+ if (typeof value !== "object" || value === null || Array.isArray(value)) fail("Eval manifest must be an object.", "INVALID_INPUT");
1742
+ const candidate = value;
1743
+ const body3 = manifestBody2(candidate);
1744
+ if (candidate["type"] !== body3.type || candidate["schemaVersion"] !== body3.schemaVersion) fail("Eval manifest type or schemaVersion is invalid.", "INVALID_INPUT");
1745
+ const manifestDigest = digest4(candidate["digest"], "digest");
1746
+ if (manifestDigest !== hashJson(body3)) fail("Eval manifest digest is invalid.", "INVALID_INPUT");
1747
+ return { ...body3, digest: manifestDigest };
1748
+ };
1749
+ var median = (values) => {
1750
+ if (!values.length) return null;
1751
+ const ordered = [...values].sort((left, right) => left - right);
1752
+ const middle = Math.floor(ordered.length / 2);
1753
+ return ordered.length % 2 ? ordered[middle] : (ordered[middle - 1] + ordered[middle]) / 2;
1754
+ };
1755
+ var runEvalBattery = async ({ manifest, evaluate }) => {
1756
+ const validated = validateEvalManifest(manifest);
1757
+ const reports = [];
1758
+ for (const testCase of validated.cases) {
1759
+ const observations = [];
1760
+ for (let repetition = 1; repetition <= validated.repetitions; repetition += 1) observations.push(await evaluate(testCase, repetition));
1761
+ const blockers2 = [];
1762
+ const statuses = observations.map((observation) => observation.status);
1763
+ if (statuses.some((status) => status === "unknown" || status === "stale" || status === "unverified")) blockers2.push("unknown, stale, or unverified evidence");
1764
+ if (statuses.some((status) => status === "failed")) blockers2.push("failed observation");
1765
+ const values = observations.map((observation) => observation.score).filter((value) => typeof value === "number");
1766
+ const minimum = values.length ? Math.min(...values) : null;
1767
+ const baseline = testCase.baselineScore;
1768
+ if (testCase.critical && (minimum === null || minimum < 100)) blockers2.push("critical case requires 100/100");
1769
+ if (testCase.subjective && (median(values) ?? 0) < validated.thresholds.subjectiveQuality) blockers2.push(`subjective score below ${validated.thresholds.subjectiveQuality}/100`);
1770
+ if (baseline !== void 0 && minimum !== null && minimum < baseline - validated.thresholds.maxRegression && !observations.every((observation) => observation.decision)) blockers2.push(`regression exceeds ${validated.thresholds.maxRegression} points without a decision`);
1771
+ reports.push({ id: testCase.id, repetitions: observations.length, min: minimum, median: median(values), max: values.length ? Math.max(...values) : null, statuses, blockers: blockers2 });
1772
+ }
1773
+ const blockers = reports.flatMap((report) => report.blockers.map((reason) => `${report.id}: ${reason}`));
1774
+ return { suiteId: validated.suiteId, repetitions: validated.repetitions, cases: reports, status: blockers.length ? "blocked" : "passed", blockers };
1775
+ };
1350
1776
  var pass = (expected, output) => typeof expected === "string" ? output === expected : expected(output);
1351
1777
  var runAgentEval = async ({ suite, agent, concurrency = 1 }) => {
1352
1778
  if (!suite.name.trim() || !suite.cases.length) fail("Eval suite must have a name and at least one case.", "INVALID_INPUT");
@@ -1369,7 +1795,7 @@ var assessAgentEval = (report, minimumAccuracy) => {
1369
1795
  return report.accuracy >= minimumAccuracy ? { status: "passed", reason: `Accuracy ${report.accuracy.toFixed(4)} meets ${minimumAccuracy.toFixed(4)}.`, report } : { status: "blocked", reason: `Accuracy ${report.accuracy.toFixed(4)} is below ${minimumAccuracy.toFixed(4)}.`, report };
1370
1796
  };
1371
1797
 
1372
- // src/cache.ts
1798
+ // src/kernel/cache.ts
1373
1799
  var validateCacheableOperation = (operation) => {
1374
1800
  if (operation !== "context" && operation !== "read-only") fail("Only context and read-only operations may use the LLM cache.", "POLICY_BLOCKED");
1375
1801
  return operation;
@@ -1384,6 +1810,8 @@ var createLlmCache = () => {
1384
1810
  let misses = 0;
1385
1811
  let invalidations = 0;
1386
1812
  return {
1813
+ assurance: "contract-tested",
1814
+ telemetry: () => ({ status: "measured", cacheHits: hits, cacheMisses: misses }),
1387
1815
  async getOrCompute(key, compute) {
1388
1816
  const cached = values.get(key);
1389
1817
  if (cached !== void 0) {
@@ -1407,13 +1835,13 @@ var createLlmCache = () => {
1407
1835
  };
1408
1836
  };
1409
1837
 
1410
- // src/optimization.ts
1411
- var nonNegative = (value, label) => {
1838
+ // src/kernel/optimization.ts
1839
+ var nonNegative2 = (value, label) => {
1412
1840
  if (!Number.isFinite(value) || value < 0) fail(`${label} must be a non-negative number.`, "INVALID_INPUT");
1413
1841
  return value;
1414
1842
  };
1415
1843
  var nonNegativeInteger = (value, label) => {
1416
- nonNegative(value, label);
1844
+ nonNegative2(value, label);
1417
1845
  if (!Number.isInteger(value)) fail(`${label} must be an integer.`, "INVALID_INPUT");
1418
1846
  return value;
1419
1847
  };
@@ -1427,7 +1855,7 @@ var validateOptimizationObservation = (observation) => {
1427
1855
  required6(observation.configHash, "configHash");
1428
1856
  required6(observation.provider, "provider");
1429
1857
  required6(observation.model, "model");
1430
- nonNegative(observation.durationMs, "durationMs");
1858
+ nonNegative2(observation.durationMs, "durationMs");
1431
1859
  if (observation.accuracy !== void 0 && (!Number.isFinite(observation.accuracy) || observation.accuracy < 0 || observation.accuracy > 1)) fail("accuracy must be between 0 and 1.", "INVALID_INPUT");
1432
1860
  if (observation.tokens) {
1433
1861
  const tokens = observation.tokens;
@@ -1442,8 +1870,8 @@ var validateOptimizationObservation = (observation) => {
1442
1870
  }
1443
1871
  if (observation.parallelism) {
1444
1872
  for (const key of ["tasks", "peakConcurrency"]) nonNegativeInteger(observation.parallelism[key], `parallelism.${key}`);
1445
- nonNegative(observation.parallelism.criticalPathMs, "parallelism.criticalPathMs");
1446
- if (observation.parallelism.queueWaitMs !== void 0) nonNegative(observation.parallelism.queueWaitMs, "parallelism.queueWaitMs");
1873
+ nonNegative2(observation.parallelism.criticalPathMs, "parallelism.criticalPathMs");
1874
+ if (observation.parallelism.queueWaitMs !== void 0) nonNegative2(observation.parallelism.queueWaitMs, "parallelism.queueWaitMs");
1447
1875
  if (observation.parallelism.tasks > 0 && observation.parallelism.peakConcurrency < 1) fail("parallelism.peakConcurrency must be positive when tasks exist.", "INVALID_INPUT");
1448
1876
  }
1449
1877
  return observation;
@@ -1467,7 +1895,7 @@ var compareOptimization = (baseline, candidate) => {
1467
1895
  return result;
1468
1896
  };
1469
1897
 
1470
- // src/memory.ts
1898
+ // src/kernel/memory.ts
1471
1899
  var MEMORY_SCOPES = ["issue", "project", "global"];
1472
1900
  var text2 = (value, label) => {
1473
1901
  if (typeof value !== "string" || !value.trim()) fail(label + " must be a non-empty string.", "INVALID_INPUT");
@@ -1485,23 +1913,38 @@ var validateMemoryRecord = (record3) => {
1485
1913
  };
1486
1914
  var createInMemoryMemoryAdapter = (options = {}) => {
1487
1915
  const records = /* @__PURE__ */ new Map();
1916
+ let reads = 0;
1917
+ let writes = 0;
1918
+ let relevantHits = 0;
1919
+ let staleHits = 0;
1488
1920
  return {
1489
1921
  id: options.id ?? "in-memory",
1490
1922
  version: options.version ?? "1",
1923
+ assurance: "contract-tested",
1924
+ telemetry: () => ({ status: "measured", memoryReads: reads, memoryWrites: writes, memoryRelevantHits: relevantHits, memoryStaleHits: staleHits }),
1491
1925
  async remember(record3) {
1492
1926
  records.set(validateMemoryRecord(record3).id, record3);
1927
+ writes += 1;
1493
1928
  },
1494
1929
  async recall({ query, issueId, project, sourceRevision }) {
1930
+ reads += 1;
1495
1931
  const needle = query.trim().toLowerCase();
1496
- return [...records.values()].filter((record3) => {
1932
+ const hits = [...records.values()].filter((record3) => {
1497
1933
  const scopeMatch = record3.scope === "global" || (record3.scope === "issue" ? Boolean(issueId && record3.source.includes(issueId)) : Boolean(project && record3.source.includes(project)));
1498
1934
  return scopeMatch && (!needle || `${record3.summary} ${record3.source}`.toLowerCase().includes(needle));
1499
1935
  }).map((record3) => ({ record: record3, relevant: true, stale: sourceRevision !== void 0 && record3.sourceRevision !== sourceRevision }));
1936
+ relevantHits += hits.length;
1937
+ staleHits += hits.filter((hit) => hit.stale).length;
1938
+ return hits;
1500
1939
  }
1501
1940
  };
1502
1941
  };
1503
1942
  var createKvMemoryAdapter = (store, options = {}) => {
1504
1943
  const indexKey = "agentskit-harness:memory:index";
1944
+ let reads = 0;
1945
+ let writes = 0;
1946
+ let relevantHits = 0;
1947
+ let staleHits = 0;
1505
1948
  const matches2 = (record3, query, issueId, project) => {
1506
1949
  const scopeMatch = record3.scope === "global" || (record3.scope === "issue" ? Boolean(issueId && record3.source.includes(issueId)) : Boolean(project && record3.source.includes(project)));
1507
1950
  return scopeMatch && (!query || `${record3.summary} ${record3.source}`.toLowerCase().includes(query));
@@ -1509,80 +1952,712 @@ var createKvMemoryAdapter = (store, options = {}) => {
1509
1952
  return {
1510
1953
  id: options.id ?? "agentskit-kv",
1511
1954
  version: options.version ?? "1",
1955
+ assurance: "contract-tested",
1956
+ telemetry: () => ({ status: "measured", memoryReads: reads, memoryWrites: writes, memoryRelevantHits: relevantHits, memoryStaleHits: staleHits }),
1512
1957
  async remember(record3) {
1513
1958
  const valid = validateMemoryRecord(record3);
1514
1959
  const ids = await store.get(indexKey);
1515
1960
  const index2 = Array.isArray(ids) ? ids.filter((id2) => typeof id2 === "string") : [];
1516
1961
  if (!index2.includes(valid.id)) await store.set(indexKey, [...index2, valid.id].sort());
1517
1962
  await store.set(`agentskit-harness:memory:${valid.id}`, valid);
1963
+ writes += 1;
1518
1964
  },
1519
1965
  async recall({ query, issueId, project, sourceRevision }) {
1966
+ reads += 1;
1520
1967
  const ids = await store.get(indexKey);
1521
1968
  const records = Array.isArray(ids) ? await Promise.all(ids.filter((id2) => typeof id2 === "string").map((id2) => store.get(`agentskit-harness:memory:${id2}`))) : [];
1522
- return records.filter((record3) => Boolean(record3 && typeof record3 === "object" && record3.approved === true)).filter((record3) => matches2(record3, query.trim().toLowerCase(), issueId, project)).map((record3) => ({ record: record3, relevant: true, stale: sourceRevision !== void 0 && record3.sourceRevision !== sourceRevision }));
1969
+ const hits = records.filter((record3) => Boolean(record3 && typeof record3 === "object" && record3.approved === true)).filter((record3) => matches2(record3, query.trim().toLowerCase(), issueId, project)).map((record3) => ({ record: record3, relevant: true, stale: sourceRevision !== void 0 && record3.sourceRevision !== sourceRevision }));
1970
+ relevantHits += hits.length;
1971
+ staleHits += hits.filter((hit) => hit.stale).length;
1972
+ return hits;
1523
1973
  }
1524
1974
  };
1525
1975
  };
1526
1976
 
1527
- // src/workflow.ts
1528
- var validId2 = (id2) => {
1529
- if (typeof id2 !== "string" || !id2.trim()) fail("Workflow node id must be non-empty.", "INVALID_INPUT");
1530
- return id2.trim();
1977
+ // src/kernel/phase-executor.ts
1978
+ var PHASE_MODES = ["safe", "yolo", "dry-run"];
1979
+ var PHASE_EFFECTS = ["read", "write", "external"];
1980
+ var PHASE_EFFECT_ACTIONS = ["allow", "preview", "block", "escalate"];
1981
+ var PHASE_DECISIONS = ["pass", "block", "escalate", "retry", "cancel", "resume"];
1982
+ var requiredId = (value, label) => {
1983
+ if (typeof value !== "string") return fail(`${label} must be a non-empty string.`, "INVALID_INPUT");
1984
+ if (!value.trim()) return fail(`${label} must be a non-empty string.`, "INVALID_INPUT");
1985
+ return value.trim();
1531
1986
  };
1532
- var levels = (nodes) => {
1533
- const byId = new Map(nodes.map((node) => [validId2(node.id), node]));
1534
- if (byId.size !== nodes.length) fail("Workflow node ids must be unique.", "INVALID_INPUT");
1987
+ var names = (values, label) => {
1988
+ if (values === void 0) return [];
1989
+ if (!Array.isArray(values)) fail(`${label} must be an array.`, "INVALID_INPUT");
1990
+ const normalized = values.map((value, index2) => requiredId(value, `${label}[${index2}]`));
1991
+ if (new Set(normalized).size !== normalized.length) fail(`${label} must contain unique names.`, "INVALID_INPUT");
1992
+ return normalized;
1993
+ };
1994
+ var boundedPositive = (value, label, fallback) => {
1995
+ const result = value ?? fallback;
1996
+ if (!Number.isInteger(result) || result < 1 || result > 100) fail(`${label} must be a bounded positive integer (1-100).`, "INVALID_INPUT");
1997
+ return result;
1998
+ };
1999
+ var duration = (value, label) => {
2000
+ if (value === void 0) return void 0;
2001
+ if (!Number.isInteger(value) || value < 1) fail(`${label} must be a positive integer.`, "INVALID_INPUT");
2002
+ return value;
2003
+ };
2004
+ var defaultEffects = (mode) => mode === "dry-run" ? { read: "allow", write: "preview", external: "preview" } : mode === "safe" ? { read: "allow", write: "allow", external: "escalate" } : { read: "allow", write: "allow", external: "allow" };
2005
+ var normalize = (profile) => {
2006
+ if (typeof profile !== "object" || profile === null || Array.isArray(profile)) return fail("profile must be an object.", "INVALID_INPUT");
2007
+ const id2 = requiredId(profile.id, "profile.id");
2008
+ if (!PHASE_MODES.includes(profile.mode)) fail("profile.mode is invalid.", "INVALID_INPUT");
2009
+ if (!Array.isArray(profile.phases) || !profile.phases.length) fail("profile.phases must be non-empty.", "INVALID_INPUT");
2010
+ profile.phases.forEach((phase2, index2) => {
2011
+ if (typeof phase2 !== "object" || phase2 === null || Array.isArray(phase2)) fail(`phases[${index2}] must be an object.`, "INVALID_INPUT");
2012
+ });
2013
+ const ids = profile.phases.map((phase2, index2) => requiredId(phase2.id, `phases[${index2}].id`));
2014
+ if (new Set(ids).size !== ids.length) fail("Phase ids must be unique.", "INVALID_INPUT");
2015
+ const known = new Set(ids);
2016
+ const outputOwners = /* @__PURE__ */ new Map();
2017
+ const phases = profile.phases.map((phase2, index2) => {
2018
+ if (typeof phase2 !== "object" || phase2 === null || Array.isArray(phase2)) return fail(`phases[${index2}] must be an object.`, "INVALID_INPUT");
2019
+ if (!PHASE_EFFECTS.includes(phase2.effect)) fail(`phases[${index2}].effect is invalid.`, "INVALID_INPUT");
2020
+ const dependsOn = names(phase2.dependsOn, `phases[${index2}].dependsOn`);
2021
+ if (dependsOn.includes(ids[index2])) fail(`phases[${index2}] cannot depend on itself.`, "INVALID_INPUT");
2022
+ if (dependsOn.some((dependency) => !known.has(dependency))) fail(`phases[${index2}] has an unknown dependency.`, "INVALID_INPUT");
2023
+ const inputs = names(phase2.inputs, `phases[${index2}].inputs`);
2024
+ const outputs = names(phase2.outputs, `phases[${index2}].outputs`);
2025
+ for (const output of outputs) {
2026
+ const owner = outputOwners.get(output);
2027
+ if (owner) fail(`Output ${output} is declared by both ${owner} and ${ids[index2]}.`, "INVALID_INPUT");
2028
+ outputOwners.set(output, ids[index2]);
2029
+ }
2030
+ const gates = names(phase2.gates, `phases[${index2}].gates`);
2031
+ const maxAttempts = boundedPositive(phase2.retries?.maxAttempts, `phases[${index2}].retries.maxAttempts`, 1);
2032
+ return { id: ids[index2], effect: phase2.effect, inputs, outputs, dependsOn, gates, ...maxAttempts > 1 ? { retries: { maxAttempts } } : {}, ...duration(phase2.budgetMs, `phases[${index2}].budgetMs`) ? { budgetMs: phase2.budgetMs } : {} };
2033
+ });
2034
+ const defaults = defaultEffects(profile.mode);
2035
+ const effectPolicy = { ...defaults, ...profile.effectPolicy ?? {} };
2036
+ for (const effect of PHASE_EFFECTS) if (!PHASE_EFFECT_ACTIONS.includes(effectPolicy[effect])) fail(`effectPolicy.${effect} is invalid.`, "INVALID_INPUT");
2037
+ const maxConcurrency = boundedPositive(profile.maxConcurrency, "profile.maxConcurrency", 1);
2038
+ const budgetMs = duration(profile.budgetMs, "profile.budgetMs");
2039
+ calculateLevels(phases);
2040
+ return { id: id2, mode: profile.mode, phases, effectPolicy, maxConcurrency, ...budgetMs ? { budgetMs } : {} };
2041
+ };
2042
+ var calculateLevels = (phases) => {
2043
+ const byId = new Map(phases.map((phase2) => [phase2.id, phase2]));
1535
2044
  const remaining = new Set(byId.keys());
1536
2045
  const completed = /* @__PURE__ */ new Set();
1537
- const result = [];
2046
+ const levels2 = [];
1538
2047
  while (remaining.size) {
1539
- const ready = [...remaining].sort().map((id2) => byId.get(id2)).filter((node) => (node.dependsOn ?? []).every((dependency) => completed.has(dependency)));
1540
- if (!ready.length) fail("Workflow contains an unknown dependency or cycle.", "INVALID_INPUT");
1541
- result.push(ready);
1542
- for (const node of ready) {
1543
- remaining.delete(node.id);
1544
- completed.add(node.id);
1545
- }
2048
+ const ready = [...remaining].sort().filter((id2) => (byId.get(id2)?.dependsOn ?? []).every((dependency) => completed.has(dependency)));
2049
+ if (!ready.length) fail("Phase profile contains an unknown dependency or cycle.", "INVALID_INPUT");
2050
+ levels2.push(ready);
2051
+ ready.forEach((id2) => {
2052
+ remaining.delete(id2);
2053
+ completed.add(id2);
2054
+ });
1546
2055
  }
2056
+ return levels2;
2057
+ };
2058
+ var createPhaseProfile = (profile) => normalize(profile);
2059
+ var planPhaseProfile = (profile) => {
2060
+ const normalized = normalize(profile);
2061
+ return { profileId: normalized.id, mode: normalized.mode, levels: calculateLevels(normalized.phases), phases: normalized.phases, effectPolicy: normalized.effectPolicy, maxConcurrency: normalized.maxConcurrency, ...normalized.budgetMs ? { budgetMs: normalized.budgetMs } : {} };
2062
+ };
2063
+ var resultDecision = (value) => {
2064
+ if (typeof value !== "object" || value === null || Array.isArray(value)) fail("Phase handler must return a decision object.", "INVALID_INPUT");
2065
+ const result = value;
2066
+ if (!PHASE_DECISIONS.includes(result.decision)) fail("Phase handler returned an invalid decision.", "INVALID_INPUT");
2067
+ if (result.outputs !== void 0 && (typeof result.outputs !== "object" || result.outputs === null || Array.isArray(result.outputs))) fail("Phase outputs must be an object.", "INVALID_INPUT");
1547
2068
  return result;
1548
2069
  };
1549
- var runWorkflow = async (nodes, options) => {
1550
- if (!Number.isInteger(options.maxConcurrency) || options.maxConcurrency < 1) fail("maxConcurrency must be a positive integer.", "INVALID_INPUT");
1551
- const started = Date.now();
1552
- const results = {};
1553
- const order = [];
1554
- let peakConcurrency = 0;
1555
- for (const level of levels(nodes)) {
1556
- const remaining = [...level];
1557
- while (remaining.length) {
1558
- const batch = [];
1559
- const keys = /* @__PURE__ */ new Set();
1560
- const limit = options.currentConcurrency ? options.currentConcurrency() : options.maxConcurrency;
1561
- if (!Number.isInteger(limit) || limit < 1) fail("currentConcurrency must return a positive integer.", "INVALID_INPUT");
1562
- for (const node of remaining) {
1563
- const key = node.mutationKey?.trim();
1564
- if (batch.length >= limit || key && keys.has(key)) continue;
1565
- batch.push(node);
1566
- if (key) keys.add(key);
2070
+ var gateDecision = (value) => typeof value === "boolean" ? { decision: value ? "pass" : "block" } : value;
2071
+ var packet = (phaseIds, ambiguities) => ambiguities.length ? { id: "phase-preflight", phaseIds: [...phaseIds].sort(), ambiguities } : void 0;
2072
+ var timeout = async (operation, budgetMs) => {
2073
+ if (budgetMs === void 0) return operation;
2074
+ let timer;
2075
+ const limit = new Promise((_, reject) => {
2076
+ timer = setTimeout(() => reject(new Error(`phase budget exceeded after ${budgetMs}ms`)), budgetMs);
2077
+ });
2078
+ try {
2079
+ return await Promise.race([operation, limit]);
2080
+ } finally {
2081
+ if (timer) clearTimeout(timer);
2082
+ }
2083
+ };
2084
+ var executePhaseProfile = async (profile, options = {}) => {
2085
+ const plan = planPhaseProfile(profile);
2086
+ const started = (options.now ?? Date.now)();
2087
+ const inputValues = { ...options.inputs ?? {} };
2088
+ const outputValues = { ...options.resume?.outputs ?? {} };
2089
+ const completed = options.resume?.completed ?? {};
2090
+ const phasesById = new Map(plan.phases.map((phase2) => [phase2.id, phase2]));
2091
+ const mutating = plan.phases.filter((phase2) => phase2.effect !== "read");
2092
+ const preflightAmbiguities = [];
2093
+ const preflightAmbiguityPhaseIds = /* @__PURE__ */ new Set();
2094
+ const preflightBlocked = [];
2095
+ const preflightEscalated = [];
2096
+ for (const phase2 of mutating) {
2097
+ const action = plan.effectPolicy[phase2.effect];
2098
+ if (action === "block") {
2099
+ preflightBlocked.push({ id: phase2.id, effect: phase2.effect, decision: "block", attempts: 0, skipped: true, reason: `Effect ${phase2.effect} is blocked by profile policy.` });
2100
+ continue;
2101
+ }
2102
+ if (action === "escalate") {
2103
+ preflightEscalated.push({ id: phase2.id, effect: phase2.effect, decision: "escalate", attempts: 0, skipped: true, reason: `Effect ${phase2.effect} requires escalation in ${plan.mode} mode.` });
2104
+ continue;
2105
+ }
2106
+ if (!options.preflight && action === "allow") {
2107
+ preflightBlocked.push({ id: phase2.id, effect: phase2.effect, decision: "block", attempts: 0, skipped: true, reason: `Preflight is required before ${phase2.effect} effects.` });
2108
+ continue;
2109
+ }
2110
+ if (!options.preflight) continue;
2111
+ const context = { phase: phase2, attempt: 0, mode: plan.mode, inputs: inputValues, outputs: outputValues, dryRun: action === "preview" };
2112
+ const check = await options.preflight(context);
2113
+ if (check.ambiguities?.length) {
2114
+ preflightAmbiguityPhaseIds.add(phase2.id);
2115
+ preflightAmbiguities.push(...check.ambiguities);
2116
+ }
2117
+ if (check.decision === "block") preflightBlocked.push({ id: phase2.id, effect: phase2.effect, decision: "block", attempts: 0, skipped: true, ...check.reason ? { reason: check.reason } : {} });
2118
+ if (check.decision === "escalate") preflightEscalated.push({ id: phase2.id, effect: phase2.effect, decision: "escalate", attempts: 0, skipped: true, ...check.reason ? { reason: check.reason } : {} });
2119
+ }
2120
+ const decisionPacket = packet([...preflightAmbiguityPhaseIds, ...preflightEscalated.map((phase2) => phase2.id)], preflightAmbiguities);
2121
+ if (decisionPacket || preflightEscalated.length) return { status: "escalated", plan, phases: [...preflightBlocked, ...preflightEscalated], order: [], outputs: outputValues, resumed: false, ...decisionPacket ? { decisionPacket } : {}, durationMs: (options.now ?? Date.now)() - started };
2122
+ if (preflightBlocked.length) return { status: "blocked", plan, phases: preflightBlocked, order: [], outputs: outputValues, resumed: false, durationMs: (options.now ?? Date.now)() - started };
2123
+ const executions = [];
2124
+ let resumed = false;
2125
+ let dryRun = false;
2126
+ const statusOf = (phase2, decision, attempts, skipped, reason, outputs) => ({ id: phase2.id, effect: phase2.effect, decision, attempts, skipped, ...reason ? { reason } : {}, ...outputs ? { outputs } : {} });
2127
+ const runPhase = async (phase2, levelOutputs) => {
2128
+ const prior = completed[phase2.id];
2129
+ if (prior && (prior.decision === "pass" || prior.decision === "resume")) {
2130
+ resumed = true;
2131
+ const restored = prior.outputs ?? {};
2132
+ return { execution: statusOf(phase2, "resume", 0, true, "Resumed from a completed phase.", restored), outputs: restored };
2133
+ }
2134
+ const action = plan.effectPolicy[phase2.effect];
2135
+ if (action === "block") return { execution: statusOf(phase2, "block", 0, true, `Effect ${phase2.effect} is blocked by profile policy.`), outputs: {} };
2136
+ if (action === "escalate") return { execution: statusOf(phase2, "escalate", 0, true, `Effect ${phase2.effect} requires escalation in ${plan.mode} mode.`), outputs: {} };
2137
+ if (action === "preview") {
2138
+ dryRun = true;
2139
+ return { execution: statusOf(phase2, "pass", 0, true, "Effect previewed; handler was not invoked."), outputs: {} };
2140
+ }
2141
+ const values = { ...inputValues, ...levelOutputs };
2142
+ const inputs = {};
2143
+ for (const name of phase2.inputs ?? []) {
2144
+ if (!(name in values)) return { execution: statusOf(phase2, "block", 0, true, `Missing phase input: ${name}.`), outputs: {} };
2145
+ inputs[name] = values[name];
2146
+ }
2147
+ const handler = options.handlers?.[phase2.id];
2148
+ if (!handler) return { execution: statusOf(phase2, "block", 0, true, `No handler registered for phase ${phase2.id}.`), outputs: {} };
2149
+ const gateContext = (attempt) => ({ phase: phase2, attempt, mode: plan.mode, inputs, outputs: levelOutputs, dryRun: false });
2150
+ for (const gateId of phase2.gates ?? []) {
2151
+ const evaluator = options.gates?.[gateId];
2152
+ if (!evaluator) return { execution: statusOf(phase2, "block", 0, true, `No evaluator registered for gate ${gateId}.`), outputs: {} };
2153
+ const gate = gateDecision(await evaluator(gateContext(0)));
2154
+ if (gate.decision !== "pass") return { execution: statusOf(phase2, gate.decision, 0, true, gate.reason ?? `Gate ${gateId} did not pass.`), outputs: {} };
2155
+ }
2156
+ const maxAttempts = phase2.retries?.maxAttempts ?? 1;
2157
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
2158
+ let result;
2159
+ try {
2160
+ result = resultDecision(await timeout(Promise.resolve(handler(gateContext(attempt))), phase2.budgetMs));
2161
+ } catch (error) {
2162
+ return { execution: statusOf(phase2, "block", attempt, false, error instanceof Error ? error.message : String(error)), outputs: {} };
1567
2163
  }
1568
- if (!batch.length) fail("Workflow could not schedule a mutation batch.", "INVALID_INPUT");
1569
- peakConcurrency = Math.max(peakConcurrency, batch.length);
1570
- const values = await Promise.all(batch.map((node) => node.run()));
1571
- batch.forEach((node, index2) => {
1572
- results[node.id] = values[index2];
1573
- order.push(node.id);
1574
- });
1575
- for (const node of batch) remaining.splice(remaining.indexOf(node), 1);
2164
+ if (result.decision === "retry") {
2165
+ if (attempt < maxAttempts) continue;
2166
+ return { execution: statusOf(phase2, "block", attempt, false, result.reason ?? "Phase retry budget exhausted."), outputs: {} };
2167
+ }
2168
+ if (result.decision === "pass" || result.decision === "resume") {
2169
+ const produced = { ...result.outputs ?? {} };
2170
+ const declared = new Set(phase2.outputs ?? []);
2171
+ if ([...Object.keys(produced)].some((name) => !declared.has(name))) return { execution: statusOf(phase2, "block", attempt, false, "Phase returned an undeclared output."), outputs: {} };
2172
+ if ([...phase2.outputs ?? []].some((name) => !(name in produced))) return { execution: statusOf(phase2, "block", attempt, false, "Phase did not produce every declared output."), outputs: {} };
2173
+ return { execution: statusOf(phase2, result.decision, attempt, false, result.reason, produced), outputs: produced };
2174
+ }
2175
+ return { execution: statusOf(phase2, result.decision, attempt, false, result.reason), outputs: {} };
1576
2176
  }
2177
+ return { execution: statusOf(phase2, "block", maxAttempts, false, "Phase did not resolve."), outputs: {} };
2178
+ };
2179
+ for (const level of plan.levels) {
2180
+ if (plan.budgetMs !== void 0 && (options.now ?? Date.now)() - started > plan.budgetMs) {
2181
+ const phase2 = phasesById.get(level[0]);
2182
+ executions.push(statusOf(phase2, "block", 0, true, `Profile budget exceeded after ${plan.budgetMs}ms.`));
2183
+ break;
2184
+ }
2185
+ const levelSnapshot = { ...outputValues };
2186
+ const workflow = await runWorkflow(level.map((id2) => ({ id: id2, run: () => runPhase(phasesById.get(id2), levelSnapshot) })), { maxConcurrency: plan.maxConcurrency });
2187
+ let stop = false;
2188
+ for (const id2 of level) {
2189
+ const step = workflow.results[id2];
2190
+ executions.push(step.execution);
2191
+ if (step.execution.decision === "pass" || step.execution.decision === "resume") Object.assign(outputValues, step.outputs);
2192
+ else stop = true;
2193
+ }
2194
+ if (plan.budgetMs !== void 0 && (options.now ?? Date.now)() - started > plan.budgetMs && executions.length) {
2195
+ const last = executions.length - 1;
2196
+ executions[last] = { ...executions[last], decision: "block", reason: `Profile budget exceeded after ${plan.budgetMs}ms.` };
2197
+ stop = true;
2198
+ }
2199
+ if (stop) break;
1577
2200
  }
1578
- return { results, order, peakConcurrency, criticalPathMs: Date.now() - started };
2201
+ const failed = executions.find((execution) => execution.decision === "block" || execution.decision === "escalate" || execution.decision === "cancel");
2202
+ const status = failed?.decision === "cancel" ? "cancelled" : failed?.decision === "escalate" ? "escalated" : failed ? "blocked" : dryRun ? "dry-run" : "passed";
2203
+ return { status, plan, phases: executions, order: executions.map((execution) => execution.id), outputs: outputValues, resumed, durationMs: (options.now ?? Date.now)() - started };
2204
+ };
2205
+ var ARTIFACT_SCHEMA_VERSION = 1;
2206
+ var ARTIFACT_TYPES = ["plan", "finding", "decision", "repair", "blocker", "approval", "phase"];
2207
+ var text3 = (value, label) => {
2208
+ if (typeof value !== "string" || !value.trim()) return fail(`${label} is required.`, "INVALID_INPUT");
2209
+ return value.trim();
2210
+ };
2211
+ var digest5 = (value, label) => {
2212
+ const result = text3(value, label);
2213
+ if (!/^[a-f0-9]{64}$/.test(result)) fail(`${label} must be a lowercase SHA-256 digest.`, "INVALID_INPUT");
2214
+ return result;
2215
+ };
2216
+ var artifactId = (value) => {
2217
+ const result = text3(value, "Artifact artifactId");
2218
+ if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(result)) fail("Artifact artifactId is invalid.", "INVALID_INPUT");
2219
+ return result;
2220
+ };
2221
+ var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2222
+ var artifactBody = (artifact) => ({
2223
+ type: artifact.type,
2224
+ schemaVersion: artifact.schemaVersion,
2225
+ artifactId: artifact.artifactId,
2226
+ artifactType: artifact.artifactType,
2227
+ artifactVersion: artifact.artifactVersion,
2228
+ runId: artifact.runId,
2229
+ issueRef: artifact.issueRef,
2230
+ sourceRevision: artifact.sourceRevision,
2231
+ contractHash: artifact.contractHash,
2232
+ configHash: artifact.configHash,
2233
+ contextHash: artifact.contextHash,
2234
+ phase: artifact.phase,
2235
+ payload: artifact.payload,
2236
+ payloadHash: artifact.payloadHash
2237
+ });
2238
+ var expectedArtifactHash = (artifact) => hashJson(artifactBody(artifact));
2239
+ var validateArtifactEnvelope = (value) => {
2240
+ if (!isRecord5(value)) return fail("Artifact envelope must be an object.", "INVALID_INPUT");
2241
+ if (value["type"] !== "agentskit-harness-artifact" || value["schemaVersion"] !== ARTIFACT_SCHEMA_VERSION) fail("Artifact envelope type or schemaVersion is invalid.", "INVALID_INPUT");
2242
+ if (!ARTIFACT_TYPES.includes(value["artifactType"])) fail("Artifact artifactType is invalid.", "INVALID_INPUT");
2243
+ if (!Number.isInteger(value["artifactVersion"]) || value["artifactVersion"] < 1) fail("Artifact artifactVersion must be a positive integer.", "INVALID_INPUT");
2244
+ const createdAt = text3(value["createdAt"], "Artifact createdAt");
2245
+ if (!Number.isFinite(Date.parse(createdAt))) fail("Artifact createdAt must be a valid timestamp.", "INVALID_INPUT");
2246
+ const payloadHash = digest5(value["payloadHash"], "Artifact payloadHash");
2247
+ if (hashJson(value["payload"]) !== payloadHash) fail("Artifact payloadHash does not match payload.", "INVALID_INPUT");
2248
+ const artifact = {
2249
+ type: "agentskit-harness-artifact",
2250
+ schemaVersion: ARTIFACT_SCHEMA_VERSION,
2251
+ artifactId: artifactId(value["artifactId"]),
2252
+ artifactType: value["artifactType"],
2253
+ artifactVersion: value["artifactVersion"],
2254
+ runId: text3(value["runId"], "Artifact runId"),
2255
+ issueRef: text3(value["issueRef"], "Artifact issueRef"),
2256
+ sourceRevision: text3(value["sourceRevision"], "Artifact sourceRevision"),
2257
+ contractHash: digest5(value["contractHash"], "Artifact contractHash"),
2258
+ configHash: digest5(value["configHash"], "Artifact configHash"),
2259
+ contextHash: digest5(value["contextHash"], "Artifact contextHash"),
2260
+ phase: text3(value["phase"], "Artifact phase"),
2261
+ createdAt,
2262
+ payload: value["payload"],
2263
+ payloadHash
2264
+ };
2265
+ if (digest5(value["artifactHash"], "Artifact artifactHash") !== expectedArtifactHash(artifact)) fail("Artifact artifactHash does not match envelope.", "INVALID_INPUT");
2266
+ return { ...artifact, artifactHash: value["artifactHash"] };
2267
+ };
2268
+ var createArtifactEnvelope = (input) => {
2269
+ if (!ARTIFACT_TYPES.includes(input.artifactType)) fail("Artifact artifactType is invalid.", "INVALID_INPUT");
2270
+ const payloadHash = input.payloadHash ?? hashJson(input.payload);
2271
+ if (payloadHash !== hashJson(input.payload)) fail("Artifact payloadHash does not match payload.", "INVALID_INPUT");
2272
+ const identity = {
2273
+ type: "agentskit-harness-artifact",
2274
+ schemaVersion: ARTIFACT_SCHEMA_VERSION,
2275
+ artifactType: input.artifactType,
2276
+ artifactVersion: input.artifactVersion,
2277
+ runId: input.runId,
2278
+ issueRef: input.issueRef,
2279
+ sourceRevision: input.sourceRevision,
2280
+ contractHash: input.contractHash,
2281
+ configHash: input.configHash,
2282
+ contextHash: input.contextHash,
2283
+ phase: input.phase,
2284
+ payload: input.payload,
2285
+ payloadHash
2286
+ };
2287
+ const id2 = input.artifactId ?? hashJson(identity);
2288
+ const artifact = {
2289
+ ...identity,
2290
+ artifactId: id2,
2291
+ createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
2292
+ };
2293
+ const artifactHash = input.artifactHash ?? expectedArtifactHash(artifact);
2294
+ return validateArtifactEnvelope({ ...artifact, artifactHash });
2295
+ };
2296
+ var renderArtifactMarkdown = (artifact) => [
2297
+ `# ${artifact.artifactType} artifact ${artifact.artifactId}`,
2298
+ "",
2299
+ `- Schema: ${artifact.schemaVersion}`,
2300
+ `- Version: ${artifact.artifactVersion}`,
2301
+ `- Run: ${artifact.runId}`,
2302
+ `- Issue: ${artifact.issueRef}`,
2303
+ `- Phase: ${artifact.phase}`,
2304
+ `- Source revision: ${artifact.sourceRevision}`,
2305
+ `- Contract hash: ${artifact.contractHash}`,
2306
+ `- Configuration hash: ${artifact.configHash}`,
2307
+ `- Context hash: ${artifact.contextHash}`,
2308
+ `- Artifact hash: ${artifact.artifactHash}`,
2309
+ "",
2310
+ "## Payload",
2311
+ "",
2312
+ "```json",
2313
+ JSON.stringify(artifact.payload, null, 2),
2314
+ "```",
2315
+ ""
2316
+ ].join("\n");
2317
+ var artifactFilePath = (stateDir, runId, id2) => join(stateDir, "runs", runId, "artifacts", `${id2}.json`);
2318
+ var artifactMarkdownPath = (stateDir, runId, id2) => join(stateDir, "runs", runId, "artifacts", `${id2}.md`);
2319
+ var FileArtifactStore = class {
2320
+ constructor(stateDir) {
2321
+ this.stateDir = stateDir;
2322
+ }
2323
+ stateDir;
2324
+ write(input) {
2325
+ const artifact = validateArtifactEnvelope(input);
2326
+ const path = artifactFilePath(this.stateDir, artifact.runId, artifact.artifactId);
2327
+ mkdirSync(join(this.stateDir, "runs", artifact.runId, "artifacts"), { recursive: true });
2328
+ if (existsSync(path)) {
2329
+ const existing = validateArtifactEnvelope(JSON.parse(readFileSync(path, "utf8")));
2330
+ if (existing.artifactHash !== artifact.artifactHash) fail(`Artifact ${artifact.artifactId} already exists with different content.`, "HARNESS_ERROR");
2331
+ return existing;
2332
+ }
2333
+ writeFileSync(path, `${JSON.stringify(artifact, null, 2)}
2334
+ `, "utf8");
2335
+ writeFileSync(artifactMarkdownPath(this.stateDir, artifact.runId, artifact.artifactId), renderArtifactMarkdown(artifact), "utf8");
2336
+ new FileEventStore(this.stateDir).append({
2337
+ runId: artifact.runId,
2338
+ sourceRevision: artifact.sourceRevision,
2339
+ configHash: artifact.configHash,
2340
+ type: "artifact.recorded",
2341
+ payload: { artifactId: artifact.artifactId, artifactType: artifact.artifactType, artifactVersion: artifact.artifactVersion, artifactHash: artifact.artifactHash, phase: artifact.phase, representation: "json+markdown" }
2342
+ });
2343
+ return artifact;
2344
+ }
2345
+ read(runId, id2) {
2346
+ return validateArtifactEnvelope(JSON.parse(readFileSync(artifactFilePath(this.stateDir, runId, artifactId(id2)), "utf8")));
2347
+ }
2348
+ list(runId) {
2349
+ const directory = join(this.stateDir, "runs", runId, "artifacts");
2350
+ if (!existsSync(directory)) return [];
2351
+ return readdirSync(directory).filter((name) => name.endsWith(".json")).sort().map((name) => validateArtifactEnvelope(JSON.parse(readFileSync(join(directory, name), "utf8"))));
2352
+ }
2353
+ };
2354
+ var artifactIsFresh = (artifact, binding2) => artifact.runId === binding2.runId && artifact.issueRef === binding2.issueRef && artifact.sourceRevision === binding2.sourceRevision && artifact.contractHash === binding2.contractHash && artifact.configHash === binding2.configHash && artifact.contextHash === binding2.contextHash && (binding2.phase === void 0 || artifact.phase === binding2.phase);
2355
+ var resumeStateFromArtifacts = (artifacts) => {
2356
+ const completed = {};
2357
+ const outputs = {};
2358
+ for (const artifact of artifacts.filter((item) => item.artifactType === "phase").sort((left, right) => left.phase.localeCompare(right.phase) || left.artifactVersion - right.artifactVersion)) {
2359
+ if (!isRecord5(artifact.payload) || artifact.payload["decision"] !== "pass") continue;
2360
+ const phaseOutputs = isRecord5(artifact.payload["outputs"]) ? artifact.payload["outputs"] : {};
2361
+ completed[artifact.phase] = { decision: "pass", outputs: phaseOutputs };
2362
+ Object.assign(outputs, phaseOutputs);
2363
+ }
2364
+ return { completed, outputs };
2365
+ };
2366
+ var createPhaseArtifact = (base, execution) => createArtifactEnvelope({ ...base, artifactType: "phase", phase: execution.id, payload: { decision: execution.decision, outputs: execution.outputs ?? {} } });
2367
+ var readArtifactFile = (path) => validateArtifactEnvelope(JSON.parse(readFileSync(path, "utf8")));
2368
+ var artifactDigest = (artifact) => sha256(JSON.stringify(artifact));
2369
+
2370
+ // src/kernel/quality.ts
2371
+ var QUALITY_DIMENSIONS = ["correctness", "completeness", "speed", "cost", "resource", "reliability"];
2372
+ var finite = (value, label, max) => {
2373
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || max !== void 0 && value > max) return fail(`${label} is invalid.`, "INVALID_INPUT");
2374
+ return value;
2375
+ };
2376
+ var integer = (value, label) => {
2377
+ const result = finite(value, label);
2378
+ if (!Number.isInteger(result)) return fail(`${label} must be an integer.`, "INVALID_INPUT");
2379
+ return result;
2380
+ };
2381
+ var phase = (value) => {
2382
+ if (typeof value !== "string" || !value.trim()) return fail("phaseId is required.", "INVALID_INPUT");
2383
+ return value.trim();
2384
+ };
2385
+ var validatePhaseTelemetry = (value) => {
2386
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return fail("Phase telemetry must be an object.", "INVALID_INPUT");
2387
+ const raw = value;
2388
+ const outcome = raw["outcome"];
2389
+ if (!["pass", "block", "escalate", "cancel", "unknown"].includes(outcome)) return fail("Phase telemetry outcome is invalid.", "INVALID_INPUT");
2390
+ const tokens = raw["tokens"] === void 0 ? void 0 : raw["tokens"];
2391
+ if (tokens) {
2392
+ for (const key of ["inputTokens", "outputTokens", "cacheReadTokens", "cacheWriteTokens", "costUsd"]) if (tokens[key] !== void 0) finite(tokens[key], `tokens.${key}`);
2393
+ }
2394
+ const machine = raw["machine"] === void 0 ? void 0 : raw["machine"];
2395
+ if (machine) {
2396
+ for (const key of ["cpuPercent", "memoryUsedPercent", "peakConcurrency", "queueWaitMs", "contentionMs", "saturationPercent"]) if (machine[key] !== void 0) finite(machine[key], `machine.${key}`, ["cpuPercent", "memoryUsedPercent", "saturationPercent"].includes(key) ? 100 : void 0);
2397
+ }
2398
+ return {
2399
+ phaseId: phase(raw["phaseId"]),
2400
+ ...raw["durationMs"] === void 0 ? {} : { durationMs: finite(raw["durationMs"], "durationMs") },
2401
+ ...raw["attempts"] === void 0 ? {} : { attempts: integer(raw["attempts"], "attempts") },
2402
+ outcome,
2403
+ ...raw["failureClass"] === void 0 ? {} : { failureClass: phase(raw["failureClass"]) },
2404
+ ...raw["evidenceCoverage"] === void 0 ? {} : { evidenceCoverage: finite(raw["evidenceCoverage"], "evidenceCoverage", 1) },
2405
+ ...tokens ? { tokens } : {},
2406
+ ...machine ? { machine } : {}
2407
+ };
2408
+ };
2409
+ var average = (values) => values.length ? Number((values.reduce((sum, value) => sum + value, 0) / values.length).toFixed(2)) : null;
2410
+ var score2 = (value, source, baseline = null) => ({ score: value === null ? null : Math.max(0, Math.min(100, Number(value.toFixed(2)))), status: value === null ? "unknown" : "measured", baselineDelta: value === null || baseline === null ? null : Number((value - baseline).toFixed(2)), source });
2411
+ var evaluateWatchdog = ({ phases, budget }) => {
2412
+ const blockers = [];
2413
+ const duration5 = phases.every((phase2) => phase2.durationMs !== void 0) ? phases.reduce((sum, phase2) => sum + (phase2.durationMs ?? 0), 0) : void 0;
2414
+ const totalTokens = phases.every((phase2) => phase2.tokens?.inputTokens !== void 0 && phase2.tokens.outputTokens !== void 0) ? phases.reduce((sum, phase2) => sum + (phase2.tokens?.inputTokens ?? 0) + (phase2.tokens?.outputTokens ?? 0), 0) : void 0;
2415
+ if (budget.maxDurationMs !== void 0 && duration5 !== void 0 && duration5 > budget.maxDurationMs) blockers.push({ class: "budget", reason: `Duration budget exceeded: ${duration5}ms > ${budget.maxDurationMs}ms.` });
2416
+ if (budget.maxTotalTokens !== void 0 && totalTokens !== void 0 && totalTokens > budget.maxTotalTokens) blockers.push({ class: "budget", reason: `Token budget exceeded: ${totalTokens} > ${budget.maxTotalTokens}.` });
2417
+ for (const phase2 of phases) {
2418
+ if (budget.maxMemoryUsedPercent !== void 0 && phase2.machine?.memoryUsedPercent !== void 0 && phase2.machine.memoryUsedPercent > budget.maxMemoryUsedPercent) blockers.push({ class: "resource", phaseId: phase2.phaseId, reason: `Memory saturation exceeded: ${phase2.machine.memoryUsedPercent}% > ${budget.maxMemoryUsedPercent}%.` });
2419
+ if (budget.maxSaturationPercent !== void 0 && phase2.machine?.saturationPercent !== void 0 && phase2.machine.saturationPercent > budget.maxSaturationPercent) blockers.push({ class: "contention", phaseId: phase2.phaseId, reason: `Saturation exceeded: ${phase2.machine.saturationPercent}% > ${budget.maxSaturationPercent}%.` });
2420
+ }
2421
+ return { status: blockers.length ? "blocked" : "ok", blockers };
2422
+ };
2423
+ var createQualityMatrix = ({ phases, baseline, budget = {} }) => {
2424
+ const current = phases.map(validatePhaseTelemetry);
2425
+ const prior = baseline?.map(validatePhaseTelemetry) ?? [];
2426
+ const currentDurations = current.flatMap((phase2) => phase2.durationMs === void 0 ? [] : [phase2.durationMs]);
2427
+ const priorDurations = prior.flatMap((phase2) => phase2.durationMs === void 0 ? [] : [phase2.durationMs]);
2428
+ const currentTokens = current.flatMap((phase2) => phase2.tokens?.inputTokens !== void 0 && phase2.tokens.outputTokens !== void 0 ? [phase2.tokens.inputTokens + phase2.tokens.outputTokens] : []);
2429
+ const priorTokens = prior.flatMap((phase2) => phase2.tokens?.inputTokens !== void 0 && phase2.tokens.outputTokens !== void 0 ? [phase2.tokens.inputTokens + phase2.tokens.outputTokens] : []);
2430
+ const correctness = score2(average(current.map((phase2) => phase2.evidenceCoverage === void 0 ? 0 : phase2.evidenceCoverage * 100)), "mean evidence coverage");
2431
+ const completeness = score2(current.length ? current.filter((phase2) => phase2.outcome === "pass").length / current.length * 100 : null, "passed phases / total phases");
2432
+ const speed = score2(currentDurations.length && priorDurations.length ? average(priorDurations) / Math.max(1, average(currentDurations)) * 100 : null, "baseline duration / current duration", 100);
2433
+ const cost = score2(currentTokens.length && priorTokens.length ? average(priorTokens) / Math.max(1, average(currentTokens)) * 100 : null, "baseline tokens / current tokens", 100);
2434
+ const resourceValues = current.flatMap((phase2) => phase2.machine?.cpuPercent !== void 0 && phase2.machine.memoryUsedPercent !== void 0 ? [100 - Math.max(phase2.machine.cpuPercent, phase2.machine.memoryUsedPercent)] : []);
2435
+ const resource = score2(average(resourceValues), "100 - max(cpu%, memory%)");
2436
+ const reliability = score2(current.length ? current.filter((phase2) => phase2.outcome === "pass").length / current.length * 100 : null, "passed phases / total phases");
2437
+ const dimensions = { correctness, completeness, speed, cost, resource, reliability };
2438
+ const measured = Object.values(dimensions).filter((item) => item.score !== null).map((item) => item.score);
2439
+ const overall = score2(average(measured), "mean of measured dimensions");
2440
+ const unknownMetricCount = Object.values(dimensions).filter((item) => item.status === "unknown").length + current.filter((phase2) => phase2.durationMs === void 0 || phase2.tokens === void 0 || phase2.machine === void 0).length;
2441
+ const blockers = evaluateWatchdog({ phases: current, budget }).blockers;
2442
+ const body3 = { type: "agentskit-harness-quality-matrix", schemaVersion: 1, dimensions, overall, phaseCount: current.length, unknownMetricCount, blockers };
2443
+ return { ...body3, digest: hashJson(body3) };
2444
+ };
2445
+
2446
+ // src/kernel/compatibility.ts
2447
+ var COMPATIBILITY_SCHEMA_VERSION = 1;
2448
+ var COMPATIBILITY_COMPONENTS = ["core", "memory", "eval", "doc-bridge", "code-review", "adapter-boundary", "runtime"];
2449
+ var text4 = (value, label) => {
2450
+ const result = typeof value === "string" ? value.trim() : "";
2451
+ if (!result) fail(`${label} is required.`, "INVALID_INPUT");
2452
+ return result;
2453
+ };
2454
+ var sha = (value, label) => {
2455
+ const result = text4(value, label);
2456
+ if (!/^[a-f0-9]{40,64}$/.test(result)) fail(`${label} must be a pinned git revision.`, "INVALID_INPUT");
2457
+ return result;
2458
+ };
2459
+ var component = (value, index2) => {
2460
+ if (typeof value !== "object" || value === null || Array.isArray(value)) fail(`components[${index2}] must be an object.`, "INVALID_INPUT");
2461
+ const candidate = value;
2462
+ const id2 = text4(candidate["id"], `components[${index2}].id`);
2463
+ if (!COMPATIBILITY_COMPONENTS.includes(id2)) fail(`components[${index2}].id is invalid.`, "INVALID_INPUT");
2464
+ if (candidate["adapterBoundary"] !== "real-adapter") fail(`components[${index2}] must use the real-adapter boundary.`, "INVALID_INPUT");
2465
+ return {
2466
+ id: id2,
2467
+ package: text4(candidate["package"], `components[${index2}].package`),
2468
+ version: text4(candidate["version"], `components[${index2}].version`),
2469
+ revision: sha(candidate["revision"], `components[${index2}].revision`),
2470
+ repository: text4(candidate["repository"], `components[${index2}].repository`),
2471
+ adapterBoundary: "real-adapter",
2472
+ testCommand: text4(candidate["testCommand"], `components[${index2}].testCommand`),
2473
+ evalCommand: text4(candidate["evalCommand"], `components[${index2}].evalCommand`),
2474
+ previousVersion: text4(candidate["previousVersion"], `components[${index2}].previousVersion`),
2475
+ noHarnessBaseline: text4(candidate["noHarnessBaseline"], `components[${index2}].noHarnessBaseline`),
2476
+ migrationEvidence: text4(candidate["migrationEvidence"], `components[${index2}].migrationEvidence`),
2477
+ rollbackEvidence: text4(candidate["rollbackEvidence"], `components[${index2}].rollbackEvidence`)
2478
+ };
2479
+ };
2480
+ var body = (value) => {
2481
+ const componentsValue = value["components"];
2482
+ if (!Array.isArray(componentsValue) || !componentsValue.length) fail("components must be a non-empty array.", "INVALID_INPUT");
2483
+ const components = componentsValue.map(component);
2484
+ if (new Set(components.map((item) => item.id)).size !== components.length) fail("component ids must be unique.", "INVALID_INPUT");
2485
+ const missing = COMPATIBILITY_COMPONENTS.filter((id2) => !components.some((item) => item.id === id2));
2486
+ if (missing.length) fail(`components must cover: ${missing.join(", ")}.`, "INVALID_INPUT");
2487
+ const outputs = value["evidenceOutputs"];
2488
+ if (!Array.isArray(outputs) || !outputs.length) fail("evidenceOutputs must be a non-empty array.", "INVALID_INPUT");
2489
+ return {
2490
+ type: "agentskit-harness-compatibility-manifest",
2491
+ schemaVersion: COMPATIBILITY_SCHEMA_VERSION,
2492
+ harnessVersion: text4(value["harnessVersion"], "harnessVersion"),
2493
+ sourceRevision: sha(value["sourceRevision"], "sourceRevision"),
2494
+ components,
2495
+ evidenceOutputs: outputs.map((item, index2) => text4(item, `evidenceOutputs[${index2}]`))
2496
+ };
2497
+ };
2498
+ var createCompatibilityManifest = (input) => {
2499
+ const value = body(input);
2500
+ return { ...value, digest: hashJson(value) };
2501
+ };
2502
+ var validateCompatibilityManifest = (value) => {
2503
+ if (typeof value !== "object" || value === null || Array.isArray(value)) fail("Compatibility manifest must be an object.", "INVALID_INPUT");
2504
+ const candidate = value;
2505
+ const valueBody = body(candidate);
2506
+ if (candidate["type"] !== valueBody.type || candidate["schemaVersion"] !== valueBody.schemaVersion) fail("Compatibility manifest type or schemaVersion is invalid.", "INVALID_INPUT");
2507
+ const digest6 = text4(candidate["digest"], "digest");
2508
+ if (digest6 !== hashJson(valueBody)) fail("Compatibility manifest digest is invalid.", "INVALID_INPUT");
2509
+ return { ...valueBody, digest: digest6 };
2510
+ };
2511
+ var assessCompatibility = ({ manifest, observations }) => {
2512
+ const validated = validateCompatibilityManifest(manifest);
2513
+ const expected = new Set(validated.components.map((item) => item.id));
2514
+ const seen = /* @__PURE__ */ new Set();
2515
+ const blockers = [];
2516
+ observations.forEach((observation) => {
2517
+ if (!expected.has(observation.componentId) || seen.has(observation.componentId)) blockers.push(`${observation.componentId}: unexpected or duplicate observation`);
2518
+ seen.add(observation.componentId);
2519
+ if (observation.status !== "passed") blockers.push(`${observation.componentId}: ${observation.status} compatibility evidence`);
2520
+ if (!observation.evidence) blockers.push(`${observation.componentId}: missing evidence`);
2521
+ });
2522
+ validated.components.forEach((item) => {
2523
+ if (!seen.has(item.id)) blockers.push(`${item.id}: missing observation`);
2524
+ const observation = observations.find((candidate) => candidate.componentId === item.id);
2525
+ if (observation && observation.previousVersion !== item.previousVersion) blockers.push(`${item.id}: previous version binding mismatch`);
2526
+ if (observation && observation.noHarnessBaseline !== item.noHarnessBaseline) blockers.push(`${item.id}: no-Harness baseline binding mismatch`);
2527
+ });
2528
+ return { status: blockers.length ? "blocked" : "passed", componentCount: validated.components.length, observations, blockers };
2529
+ };
2530
+
2531
+ // src/kernel/resilience.ts
2532
+ var positiveInteger = (value, label) => {
2533
+ if (!Number.isInteger(value) || value < 1) fail(`${label} must be a positive integer.`, "INVALID_INPUT");
2534
+ return value;
2535
+ };
2536
+ var nonNegativeInteger2 = (value, label) => {
2537
+ if (!Number.isInteger(value) || value < 0) fail(`${label} must be a non-negative integer.`, "INVALID_INPUT");
2538
+ return value;
2539
+ };
2540
+ var classifyFailure = (error) => {
2541
+ const value = error;
2542
+ const code = typeof value?.code === "string" ? value.code.toUpperCase() : "";
2543
+ const message = typeof value?.message === "string" ? value.message : String(error);
2544
+ const text7 = `${code} ${message}`.toLowerCase();
2545
+ if (/quota|rate.?limit|too many requests|429/.test(text7)) return { class: "quota", retryable: true, reason: message };
2546
+ if (/timeout|timed out|deadline/.test(text7)) return { class: "timeout", retryable: true, reason: message };
2547
+ if (/policy|forbidden|permission|approval/.test(text7)) return { class: "policy", retryable: false, reason: message };
2548
+ if (/invalid|schema|argument|config|validation/.test(text7)) return { class: "validation", retryable: false, reason: message };
2549
+ if (/network|connection|econn|503|502|external/.test(text7)) return { class: "external", retryable: true, reason: message };
2550
+ return { class: "unknown", retryable: false, reason: message };
2551
+ };
2552
+ var recoveryDelayMs = (attempt, policy) => {
2553
+ positiveInteger(attempt, "attempt");
2554
+ nonNegativeInteger2(policy.baseDelayMs, "baseDelayMs");
2555
+ nonNegativeInteger2(policy.maxDelayMs, "maxDelayMs");
2556
+ if (policy.maxDelayMs < policy.baseDelayMs) fail("maxDelayMs must be greater than or equal to baseDelayMs.", "INVALID_INPUT");
2557
+ return Math.min(policy.maxDelayMs, policy.baseDelayMs * 2 ** Math.max(0, attempt - 1));
2558
+ };
2559
+ var wait = (delayMs, sleep) => delayMs > 0 ? sleep(delayMs) : Promise.resolve();
2560
+ var runWithRecovery = async (operation, options) => {
2561
+ const maxAttempts = positiveInteger(options.maxAttempts, "maxAttempts");
2562
+ const baseDelayMs = nonNegativeInteger2(options.baseDelayMs, "baseDelayMs");
2563
+ const maxDelayMs = nonNegativeInteger2(options.maxDelayMs, "maxDelayMs");
2564
+ if (maxDelayMs < baseDelayMs) fail("maxDelayMs must be greater than or equal to baseDelayMs.", "INVALID_INPUT");
2565
+ if (options.timeoutMs !== void 0) positiveInteger(options.timeoutMs, "timeoutMs");
2566
+ const sleep = options.sleep ?? ((delayMs) => new Promise((resolve6) => setTimeout(resolve6, delayMs)));
2567
+ const observations = [];
2568
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
2569
+ const controller = new AbortController();
2570
+ let timer;
2571
+ try {
2572
+ const operationPromise = operation(controller.signal, attempt);
2573
+ const value = options.timeoutMs === void 0 ? await operationPromise : await Promise.race([
2574
+ operationPromise,
2575
+ new Promise((_, reject) => {
2576
+ timer = setTimeout(() => {
2577
+ controller.abort();
2578
+ reject(new Error("operation timed out"));
2579
+ }, options.timeoutMs);
2580
+ })
2581
+ ]);
2582
+ return { status: "completed", attempts: attempt, observations, value };
2583
+ } catch (error) {
2584
+ const failure = classifyFailure(error);
2585
+ const delayMs = failure.retryable && attempt < maxAttempts ? recoveryDelayMs(attempt, { baseDelayMs, maxDelayMs }) : 0;
2586
+ const observation = { attempt, failure, delayMs };
2587
+ observations.push(observation);
2588
+ options.onObservation?.(observation);
2589
+ if (!failure.retryable || attempt >= maxAttempts) return { status: "failed", attempts: attempt, observations, failure };
2590
+ await wait(delayMs, sleep);
2591
+ } finally {
2592
+ if (timer) clearTimeout(timer);
2593
+ }
2594
+ }
2595
+ return fail("Recovery loop exhausted unexpectedly.", "HARNESS_ERROR");
2596
+ };
2597
+
2598
+ // src/adapters/agent.ts
2599
+ var required7 = (value, label) => {
2600
+ if (typeof value !== "string" || !value.trim()) return fail(`${label} is required.`, "INVALID_INPUT");
2601
+ return value.trim();
2602
+ };
2603
+ var duration2 = (value) => Number.isFinite(value) && value >= 0 ? value : fail("Agent durationMs must be non-negative.", "INVALID_INPUT");
2604
+ var usage = (value) => {
2605
+ if (value === void 0) return { status: "unknown" };
2606
+ if (value.status !== "measured" && value.status !== "unknown") return fail("Agent usage status is invalid.", "INVALID_INPUT");
2607
+ for (const key of ["inputTokens", "outputTokens", "totalTokens"]) if (value[key] !== void 0 && (!Number.isFinite(value[key]) || value[key] < 0)) return fail(`Agent usage ${key} must be non-negative.`, "INVALID_INPUT");
2608
+ return value;
2609
+ };
2610
+ var createCodingAgentAdapter = ({ id: id2, version, assurance = "contract-tested", timeoutMs = 12e4, execute }) => {
2611
+ const adapterId = required7(id2, "agent.id");
2612
+ const adapterVersion = required7(version, "agent.version");
2613
+ if (!Number.isInteger(timeoutMs) || timeoutMs < 1) return fail("agent.timeoutMs must be a positive integer.", "INVALID_INPUT");
2614
+ return {
2615
+ id: adapterId,
2616
+ version: adapterVersion,
2617
+ assurance,
2618
+ execute: async (request) => {
2619
+ const issueRef = required7(request.issueRef, "agent.issueRef");
2620
+ const prompt = required7(request.prompt, "agent.prompt");
2621
+ const sourceRevision = required7(request.sourceRevision, "agent.sourceRevision");
2622
+ const controller = new AbortController();
2623
+ const signal = request.signal;
2624
+ if (signal?.aborted) return { status: "cancelled", output: {}, diff: "", usage: { status: "unknown" }, durationMs: 0, failure: { class: "policy", retryable: false, reason: "Agent execution was cancelled before start." }, metadata: { assurance, telemetry: { status: "measured", durationMs: 0 } } };
2625
+ const onAbort = () => controller.abort();
2626
+ signal?.addEventListener("abort", onAbort, { once: true });
2627
+ const started = Date.now();
2628
+ let timer;
2629
+ let timedOut = false;
2630
+ try {
2631
+ const operation = Promise.resolve(execute({ issueRef, prompt, sourceRevision, ...request.contextHash ? { contextHash: request.contextHash } : {}, signal: controller.signal }));
2632
+ const timeout2 = new Promise((_, reject) => {
2633
+ timer = setTimeout(() => {
2634
+ timedOut = true;
2635
+ controller.abort();
2636
+ reject(new Error("agent execution timed out"));
2637
+ }, timeoutMs);
2638
+ });
2639
+ const result = await Promise.race([operation, timeout2]);
2640
+ if (!result || typeof result !== "object" || Array.isArray(result) || typeof result.output !== "object" || result.output === null || Array.isArray(result.output) || typeof result.diff !== "string") return fail("Agent result must contain structured output and diff.", "INVALID_INPUT");
2641
+ const measuredUsage = usage(result.usage);
2642
+ const durationMs = duration2(Date.now() - started);
2643
+ return { status: "completed", output: result.output, diff: result.diff, usage: measuredUsage, durationMs, metadata: { assurance, telemetry: { status: measuredUsage.status, durationMs, ...measuredUsage.inputTokens === void 0 ? {} : { inputTokens: measuredUsage.inputTokens }, ...measuredUsage.outputTokens === void 0 ? {} : { outputTokens: measuredUsage.outputTokens }, ...measuredUsage.totalTokens === void 0 ? {} : { totalTokens: measuredUsage.totalTokens } } } };
2644
+ } catch (error) {
2645
+ const failure = timedOut ? { class: "timeout", retryable: true, reason: "Agent execution timed out." } : classifyFailure(error);
2646
+ const status = timedOut ? "timeout" : controller.signal.aborted ? "cancelled" : "failed";
2647
+ return { status, output: {}, diff: "", usage: { status: "unknown" }, durationMs: duration2(Date.now() - started), failure, metadata: { assurance, telemetry: { status: "unknown", durationMs: duration2(Date.now() - started) } } };
2648
+ } finally {
2649
+ if (timer) clearTimeout(timer);
2650
+ signal?.removeEventListener("abort", onAbort);
2651
+ }
2652
+ }
2653
+ };
1579
2654
  };
1580
2655
  var BENCHMARK_SCHEMA_VERSION = 1;
1581
2656
  var percentage = (part, total) => total ? Number((part / total).toFixed(4)) : null;
1582
2657
  var improvementRate = (baseline, current) => baseline === void 0 || current === void 0 || baseline === 0 ? null : Number(((baseline - current) / baseline).toFixed(4));
1583
2658
  var improvementDirection = (rate2) => rate2 === null ? "unavailable" : rate2 > 0 ? "improved" : rate2 < 0 ? "regressed" : "unchanged";
1584
2659
  var count = (items, predicate) => items.filter(predicate).length;
1585
- var median = (values) => {
2660
+ var median2 = (values) => {
1586
2661
  if (!values.length) return null;
1587
2662
  const sorted = [...values].sort((left, right) => left - right);
1588
2663
  const middle = Math.floor(sorted.length / 2);
@@ -1628,8 +2703,8 @@ var summarize = (runs) => {
1628
2703
  firstAttemptApprovalRate: percentage(count(firstAttempts, (run) => run.humanApproved), firstAttempts.length),
1629
2704
  retryRate: percentage(count(runs, (run) => run.supersedes !== void 0), runs.length),
1630
2705
  staleRate: percentage(stateCounts.STALE, runs.length),
1631
- averageDurationMs: durations.length ? Math.round(durations.reduce((total, duration3) => total + duration3, 0) / durations.length) : null,
1632
- medianDurationMs: median(durations)
2706
+ averageDurationMs: durations.length ? Math.round(durations.reduce((total, duration5) => total + duration5, 0) / durations.length) : null,
2707
+ medianDurationMs: median2(durations)
1633
2708
  };
1634
2709
  };
1635
2710
  var readRuns = (stateDir) => {
@@ -1656,7 +2731,7 @@ var sha2562 = (value, label) => {
1656
2731
  if (!/^[a-f0-9]{64}$/.test(result)) return fail(`${label} must be a lowercase SHA-256 digest.`, "INVALID_CONFIG");
1657
2732
  return result;
1658
2733
  };
1659
- var stringList = (value, label) => {
2734
+ var stringList2 = (value, label) => {
1660
2735
  if (!Array.isArray(value)) return fail(`${label} must be a non-empty string array.`, "INVALID_CONFIG");
1661
2736
  const items = value;
1662
2737
  if (!items.length || !items.every((item) => typeof item === "string" && Boolean(item.trim()))) return fail(`${label} must be a non-empty string array.`, "INVALID_CONFIG");
@@ -1669,7 +2744,7 @@ var nonNegativeNumber = (value, label) => {
1669
2744
  const result = value;
1670
2745
  return result;
1671
2746
  };
1672
- var nonNegativeInteger2 = (value, label) => {
2747
+ var nonNegativeInteger3 = (value, label) => {
1673
2748
  const result = nonNegativeNumber(value, label);
1674
2749
  if (result !== void 0 && !Number.isInteger(result)) return fail(`${label} must be an integer.`, "INVALID_CONFIG");
1675
2750
  return result;
@@ -1687,7 +2762,7 @@ var validateBenchmarkManifest = (value) => {
1687
2762
  const tasks = rawTasks.map((item, index2) => {
1688
2763
  if (typeof item !== "object" || item === null || Array.isArray(item)) fail(`benchmark.tasks[${index2}] must be an object.`, "INVALID_CONFIG");
1689
2764
  const task = item;
1690
- return { id: nonEmptyString(task["id"], `benchmark.tasks[${index2}].id`), title: nonEmptyString(task["title"], `benchmark.tasks[${index2}].title`), acceptanceCriteria: stringList(task["acceptanceCriteria"], `benchmark.tasks[${index2}].acceptanceCriteria`) };
2765
+ return { id: nonEmptyString(task["id"], `benchmark.tasks[${index2}].id`), title: nonEmptyString(task["title"], `benchmark.tasks[${index2}].title`), acceptanceCriteria: stringList2(task["acceptanceCriteria"], `benchmark.tasks[${index2}].acceptanceCriteria`) };
1691
2766
  });
1692
2767
  if (new Set(tasks.map((task) => task.id)).size !== tasks.length) fail("benchmark task ids must be unique.", "INVALID_CONFIG");
1693
2768
  const taskIds = new Set(tasks.map((task) => task.id));
@@ -1700,10 +2775,10 @@ var validateBenchmarkManifest = (value) => {
1700
2775
  const taskId = nonEmptyString(observation["taskId"], `benchmark.observations[${index2}].taskId`);
1701
2776
  if (!taskIds.has(taskId)) fail(`benchmark observation references unknown task: ${taskId}.`, "INVALID_CONFIG");
1702
2777
  const task = tasks.find((candidate) => candidate.id === taskId) ?? fail(`benchmark observation references unknown task: ${taskId}.`, "INVALID_CONFIG");
1703
- const attempts = nonNegativeInteger2(observation["attempts"], `benchmark.observations[${index2}].attempts`);
2778
+ const attempts = nonNegativeInteger3(observation["attempts"], `benchmark.observations[${index2}].attempts`);
1704
2779
  const durationMs = nonNegativeNumber(observation["durationMs"], `benchmark.observations[${index2}].durationMs`);
1705
2780
  const reviewMinutes2 = nonNegativeNumber(observation["reviewMinutes"], `benchmark.observations[${index2}].reviewMinutes`);
1706
- const escapedIncomplete = nonNegativeInteger2(observation["escapedIncomplete"], `benchmark.observations[${index2}].escapedIncomplete`);
2781
+ const escapedIncomplete = nonNegativeInteger3(observation["escapedIncomplete"], `benchmark.observations[${index2}].escapedIncomplete`);
1707
2782
  const evidenceDigest = sha2562(observation["evidenceDigest"], `benchmark.observations[${index2}].evidenceDigest`);
1708
2783
  const rawEvidence = observation["evidence"] === void 0 ? void 0 : Array.isArray(observation["evidence"]) ? observation["evidence"] : fail(`benchmark.observations[${index2}].evidence must be an array.`, "INVALID_CONFIG");
1709
2784
  const evidence = rawEvidence?.map((item2, evidenceIndex) => {
@@ -1783,19 +2858,19 @@ var benchmarkRuns = (stateDir, manifest) => {
1783
2858
  const reportComparisons = manifest ? comparisons(runs, manifest) : [];
1784
2859
  return { type: "agentskit-harness-benchmark", schemaVersion: BENCHMARK_SCHEMA_VERSION, stateDir, generatedAt: (/* @__PURE__ */ new Date()).toISOString(), runs, summary: summarize(runs), comparisons: reportComparisons, ...manifest ? { manifest: { suiteId: manifest.suiteId, taskCount: manifest.tasks.length, baselineCount: manifest.observations.length, comparableTaskCount: reportComparisons.filter((comparison) => comparison.comparable).length } } : {} };
1785
2860
  };
1786
- var required7 = (value, label) => {
2861
+ var required8 = (value, label) => {
1787
2862
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
1788
2863
  return value.trim();
1789
2864
  };
1790
- var duration = (value) => {
2865
+ var duration3 = (value) => {
1791
2866
  if (!Number.isFinite(value) || value < 0) fail("Tool durationMs must be a non-negative number.", "INVALID_INPUT");
1792
2867
  return value;
1793
2868
  };
1794
2869
  var createSessionRecorder = ({ stateDir, run, adapter, policy, runtime, sessionId = randomUUID(), resume = false }) => {
1795
2870
  if (run.state !== "IMPLEMENTING") fail(`Agent sessions can only start during IMPLEMENTING, not ${run.state}.`, "INVALID_STATE");
1796
- const id2 = required7(sessionId, "sessionId");
1797
- const adapterId = required7(adapter.id, "adapter.id");
1798
- const adapterVersion = required7(adapter.version, "adapter.version");
2871
+ const id2 = required8(sessionId, "sessionId");
2872
+ const adapterId = required8(adapter.id, "adapter.id");
2873
+ const adapterVersion = required8(adapter.version, "adapter.version");
1799
2874
  if (!policy || typeof policy.evaluate !== "function") fail("policy.evaluate is required.", "INVALID_INPUT");
1800
2875
  if (!runtime || typeof runtime.execute !== "function") fail("runtime.execute is required.", "INVALID_INPUT");
1801
2876
  if (!Array.isArray(adapter.capabilities) || adapter.capabilities.some((capability) => typeof capability !== "string" || !capability.trim())) fail("adapter.capabilities must contain non-empty strings.", "INVALID_INPUT");
@@ -1846,18 +2921,18 @@ var createSessionRecorder = ({ stateDir, run, adapter, policy, runtime, sessionI
1846
2921
  };
1847
2922
  const complete = (input) => {
1848
2923
  open();
1849
- const actionId = required7(input.actionId, "actionId");
2924
+ const actionId = required8(input.actionId, "actionId");
1850
2925
  if (!pending.has(actionId)) fail(`Tool action is not pending: ${actionId}.`, "INVALID_STATE");
1851
- const event = append("tool.completed", { actionId, resultHash: required7(input.resultHash, "resultHash"), durationMs: duration(input.durationMs), ...input.runtimeEvidence ? { runtimeEvidence: input.runtimeEvidence } : {} });
2926
+ const event = append("tool.completed", { actionId, resultHash: required8(input.resultHash, "resultHash"), durationMs: duration3(input.durationMs), ...input.runtimeEvidence ? { runtimeEvidence: input.runtimeEvidence } : {} });
1852
2927
  pending.delete(actionId);
1853
2928
  return event;
1854
2929
  };
1855
2930
  const failAction = (input) => {
1856
2931
  open();
1857
- const actionId = required7(input.actionId, "actionId");
2932
+ const actionId = required8(input.actionId, "actionId");
1858
2933
  if (!pending.has(actionId)) fail(`Tool action is not pending: ${actionId}.`, "INVALID_STATE");
1859
2934
  if (typeof input.retryable !== "boolean") fail("retryable must be boolean.", "INVALID_INPUT");
1860
- const event = append("tool.failed", { actionId, errorCode: required7(input.errorCode, "errorCode"), retryable: input.retryable, durationMs: duration(input.durationMs), ...input.runtimeEvidence ? { runtimeEvidence: input.runtimeEvidence } : {} });
2935
+ const event = append("tool.failed", { actionId, errorCode: required8(input.errorCode, "errorCode"), retryable: input.retryable, durationMs: duration3(input.durationMs), ...input.runtimeEvidence ? { runtimeEvidence: input.runtimeEvidence } : {} });
1861
2936
  pending.delete(actionId);
1862
2937
  return event;
1863
2938
  };
@@ -1865,24 +2940,24 @@ var createSessionRecorder = ({ stateDir, run, adapter, policy, runtime, sessionI
1865
2940
  sessionId: id2,
1866
2941
  startTurn: (inputHash, turnId = randomUUID()) => {
1867
2942
  open();
1868
- const turn = required7(turnId, "turnId");
2943
+ const turn = required8(turnId, "turnId");
1869
2944
  if (turns.has(turn)) fail(`Turn already exists: ${turn}.`, "INVALID_STATE");
1870
- const event = append("agent.turn.started", { turnId: turn, inputHash: required7(inputHash, "inputHash") });
2945
+ const event = append("agent.turn.started", { turnId: turn, inputHash: required8(inputHash, "inputHash") });
1871
2946
  turns.add(turn);
1872
2947
  return event;
1873
2948
  },
1874
2949
  requestTool: (input) => {
1875
2950
  open();
1876
- const turnId = required7(input.turnId, "turnId");
2951
+ const turnId = required8(input.turnId, "turnId");
1877
2952
  if (!turns.has(turnId)) fail(`Turn does not exist: ${turnId}.`, "INVALID_STATE");
1878
- const actionId = required7(input.actionId ?? randomUUID(), "actionId");
2953
+ const actionId = required8(input.actionId ?? randomUUID(), "actionId");
1879
2954
  if (actions.has(actionId)) fail(`Tool action already exists: ${actionId}.`, "INVALID_STATE");
1880
- const toolId = required7(input.toolId, "toolId");
1881
- const argumentsHash = required7(input.argumentsHash, "argumentsHash");
2955
+ const toolId = required8(input.toolId, "toolId");
2956
+ const argumentsHash = required8(input.argumentsHash, "argumentsHash");
1882
2957
  const decision = policy.evaluate({ actionId, turnId, toolId, argumentsHash });
1883
2958
  if (!decision || decision.decision !== "allow" && decision.decision !== "block" && decision.decision !== "approve") fail("Policy decision is invalid.", "HARNESS_ERROR");
1884
- const policyId = required7(decision.policyId, "policyId");
1885
- const reason = required7(decision.reason, "policy reason");
2959
+ const policyId = required8(decision.policyId, "policyId");
2960
+ const reason = required8(decision.reason, "policy reason");
1886
2961
  append("policy.evaluated", { actionId, turnId, toolId, decision: decision.decision, policyId, reason });
1887
2962
  actions.add(actionId);
1888
2963
  if (decision.decision === "block") {
@@ -1900,7 +2975,7 @@ var createSessionRecorder = ({ stateDir, run, adapter, policy, runtime, sessionI
1900
2975
  },
1901
2976
  approveTool: (input) => {
1902
2977
  open();
1903
- const actionId = required7(input.actionId, "actionId");
2978
+ const actionId = required8(input.actionId, "actionId");
1904
2979
  const approval = approvals.get(actionId) ?? fail(`Tool action is not awaiting human approval: ${actionId}.`, "INVALID_STATE");
1905
2980
  if (input.actor !== void 0 && input.actor !== "human") fail("Tool approval requires a human actor.", "HUMAN_APPROVAL_REQUIRED");
1906
2981
  const decision = input.decision;
@@ -1914,7 +2989,7 @@ var createSessionRecorder = ({ stateDir, run, adapter, policy, runtime, sessionI
1914
2989
  },
1915
2990
  recoverTool: (input) => {
1916
2991
  open();
1917
- const actionId = required7(input.actionId, "actionId");
2992
+ const actionId = required8(input.actionId, "actionId");
1918
2993
  const action = pending.get(actionId) ?? fail(`Tool action is not pending: ${actionId}.`, "INVALID_STATE");
1919
2994
  if (!action.executionStarted) fail(`Tool action does not require recovery: ${actionId}.`, "INVALID_STATE");
1920
2995
  if (input.actor !== void 0 && input.actor !== "human") fail("Tool recovery requires a human actor.", "HUMAN_APPROVAL_REQUIRED");
@@ -1932,7 +3007,7 @@ var createSessionRecorder = ({ stateDir, run, adapter, policy, runtime, sessionI
1932
3007
  failTool: failAction,
1933
3008
  executeTool: async (input) => {
1934
3009
  open();
1935
- const actionId = required7(input.actionId, "actionId");
3010
+ const actionId = required8(input.actionId, "actionId");
1936
3011
  const action = pending.get(actionId) ?? fail(`Tool action is not pending: ${actionId}.`, "INVALID_STATE");
1937
3012
  if (action.executionStarted) fail(`Tool action requires human recovery decision: ${actionId}.`, "HUMAN_APPROVAL_REQUIRED");
1938
3013
  if (executing.has(actionId)) fail(`Tool action is already executing: ${actionId}.`, "INVALID_STATE");
@@ -1975,8 +3050,8 @@ var createSessionRecorder = ({ stateDir, run, adapter, policy, runtime, sessionI
1975
3050
  return recorder;
1976
3051
  };
1977
3052
 
1978
- // src/policy.ts
1979
- var required8 = (value, label) => {
3053
+ // src/kernel/policy.ts
3054
+ var required9 = (value, label) => {
1980
3055
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
1981
3056
  return value.trim();
1982
3057
  };
@@ -1984,30 +3059,30 @@ var createPolicyGate = ({ rules }) => {
1984
3059
  if (!Array.isArray(rules)) fail("Policy rules must be an array.", "INVALID_INPUT");
1985
3060
  const normalized = rules.map((rule, index2) => {
1986
3061
  if (typeof rule !== "object" || rule === null || Array.isArray(rule)) fail(`rules[${index2}] must be an object.`, "INVALID_INPUT");
1987
- const id2 = required8(rule.id, `rules[${index2}].id`);
3062
+ const id2 = required9(rule.id, `rules[${index2}].id`);
1988
3063
  if (rule.effect !== "allow" && rule.effect !== "block" && rule.effect !== "approve") fail(`rules[${index2}].effect is invalid.`, "INVALID_INPUT");
1989
3064
  if (!Array.isArray(rule.toolIds) || !rule.toolIds.length || rule.toolIds.some((toolId) => typeof toolId !== "string" || !toolId.trim())) fail(`rules[${index2}].toolIds must contain non-empty strings.`, "INVALID_INPUT");
1990
- return { id: id2, effect: rule.effect, toolIds: rule.toolIds.map((toolId) => required8(toolId, `rules[${index2}].toolIds`)), reason: required8(rule.reason, `rules[${index2}].reason`) };
3065
+ return { id: id2, effect: rule.effect, toolIds: rule.toolIds.map((toolId) => required9(toolId, `rules[${index2}].toolIds`)), reason: required9(rule.reason, `rules[${index2}].reason`) };
1991
3066
  });
1992
3067
  if (new Set(normalized.map((rule) => rule.id)).size !== normalized.length) fail("Policy rules must have unique ids.", "INVALID_INPUT");
1993
3068
  return {
1994
3069
  evaluate: (request) => {
1995
3070
  if (typeof request !== "object" || request === null || Array.isArray(request)) fail("Policy request must be an object.", "INVALID_INPUT");
1996
- required8(request.actionId, "request.actionId");
1997
- required8(request.turnId, "request.turnId");
1998
- const toolId = required8(request.toolId, "request.toolId");
1999
- required8(request.argumentsHash, "request.argumentsHash");
3071
+ required9(request.actionId, "request.actionId");
3072
+ required9(request.turnId, "request.turnId");
3073
+ const toolId = required9(request.toolId, "request.toolId");
3074
+ required9(request.argumentsHash, "request.argumentsHash");
2000
3075
  const rule = normalized.find((candidate) => candidate.toolIds.includes(toolId));
2001
3076
  return rule ? { decision: rule.effect, policyId: rule.id, reason: rule.reason } : { decision: "block", policyId: "default-deny", reason: `No policy rule allows tool: ${toolId}.` };
2002
3077
  }
2003
3078
  };
2004
3079
  };
2005
3080
  var createConfiguredToolRuntime = ({ runtime, process: process2, docker }) => runtime.kind === "docker" ? createDockerToolRuntime(docker) : createProcessToolRuntime(process2);
2006
- var required9 = (value, label) => {
3081
+ var required10 = (value, label) => {
2007
3082
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
2008
3083
  return value.trim();
2009
3084
  };
2010
- var duration2 = (value) => {
3085
+ var duration4 = (value) => {
2011
3086
  if (!Number.isFinite(value) || value < 0) fail("Tool durationMs must be a non-negative number.", "INVALID_INPUT");
2012
3087
  return value;
2013
3088
  };
@@ -2017,7 +3092,7 @@ var positiveNumber = (value, label) => {
2017
3092
  return normalized;
2018
3093
  };
2019
3094
  var absolutePath = (value, label) => {
2020
- const normalized = required9(value, label);
3095
+ const normalized = required10(value, label);
2021
3096
  if (!normalized.startsWith("/") || normalized.includes(",")) fail(`${label} must be an absolute path without commas.`, "INVALID_INPUT");
2022
3097
  return normalized;
2023
3098
  };
@@ -2035,35 +3110,38 @@ var createToolRuntime = ({ tools, timeoutMs = 3e4 }) => {
2035
3110
  if (!Number.isInteger(timeoutMs) || timeoutMs < 1) fail("Runtime timeoutMs must be a positive integer.", "INVALID_INPUT");
2036
3111
  const normalized = tools.map((tool, index2) => {
2037
3112
  if (typeof tool !== "object" || tool === null || Array.isArray(tool)) fail(`tools[${index2}] must be an object.`, "INVALID_INPUT");
2038
- const toolId = required9(tool.toolId, `tools[${index2}].toolId`);
3113
+ const toolId = required10(tool.toolId, `tools[${index2}].toolId`);
2039
3114
  if (typeof tool.execute !== "function") fail(`tools[${index2}].execute is required.`, "INVALID_INPUT");
2040
3115
  return { toolId, execute: tool.execute };
2041
3116
  });
2042
3117
  if (new Set(normalized.map((tool) => tool.toolId)).size !== normalized.length) fail("Runtime tools must have unique ids.", "INVALID_INPUT");
2043
3118
  return {
3119
+ assurance: "contract-tested",
3120
+ isolation: "none",
3121
+ telemetry: () => ({ status: "unknown" }),
2044
3122
  execute: async (request) => {
2045
3123
  const started = Date.now();
2046
- const actionId = required9(request.actionId, "request.actionId");
2047
- const turnId = required9(request.turnId, "request.turnId");
2048
- const toolId = required9(request.toolId, "request.toolId");
2049
- const argumentsHash = required9(request.argumentsHash, "request.argumentsHash");
3124
+ const actionId = required10(request.actionId, "request.actionId");
3125
+ const turnId = required10(request.turnId, "request.turnId");
3126
+ const toolId = required10(request.toolId, "request.toolId");
3127
+ const argumentsHash = required10(request.argumentsHash, "request.argumentsHash");
2050
3128
  const tool = normalized.find((candidate) => candidate.toolId === toolId);
2051
- if (!tool) return { status: "failed", errorCode: "TOOL_NOT_FOUND", retryable: false, durationMs: duration2(Date.now() - started) };
3129
+ if (!tool) return { status: "failed", errorCode: "TOOL_NOT_FOUND", retryable: false, durationMs: duration4(Date.now() - started) };
2052
3130
  const controller = new AbortController();
2053
3131
  let timedOut = false;
2054
3132
  let timer;
2055
3133
  try {
2056
- const timeout = new Promise((_, reject) => {
3134
+ const timeout2 = new Promise((_, reject) => {
2057
3135
  timer = setTimeout(() => {
2058
3136
  timedOut = true;
2059
3137
  controller.abort();
2060
3138
  reject(new Error("Tool execution timed out."));
2061
3139
  }, timeoutMs);
2062
3140
  });
2063
- const result = await Promise.race([Promise.resolve(tool.execute({ actionId, turnId, toolId, argumentsHash, arguments: request.arguments, signal: controller.signal })), timeout]);
2064
- return { status: "completed", resultHash: hashJson(result === void 0 ? null : result), durationMs: duration2(Date.now() - started) };
3141
+ const result = await Promise.race([Promise.resolve(tool.execute({ actionId, turnId, toolId, argumentsHash, arguments: request.arguments, signal: controller.signal })), timeout2]);
3142
+ return { status: "completed", resultHash: hashJson(result === void 0 ? null : result), durationMs: duration4(Date.now() - started) };
2065
3143
  } catch {
2066
- return { status: "failed", errorCode: timedOut ? "TIMEOUT" : "RUNTIME_ERROR", retryable: true, durationMs: duration2(Date.now() - started) };
3144
+ return { status: "failed", errorCode: timedOut ? "TIMEOUT" : "RUNTIME_ERROR", retryable: true, durationMs: duration4(Date.now() - started) };
2067
3145
  } finally {
2068
3146
  if (timer) clearTimeout(timer);
2069
3147
  }
@@ -2076,20 +3154,23 @@ var createProcessToolRuntime = ({ tools, timeoutMs = 3e4, maxOutputBytes = 10485
2076
3154
  if (!Number.isInteger(maxOutputBytes) || maxOutputBytes < 1) fail("Process runtime maxOutputBytes must be a positive integer.", "INVALID_INPUT");
2077
3155
  const normalized = tools.map((tool, index2) => {
2078
3156
  if (typeof tool !== "object" || tool === null || Array.isArray(tool)) fail(`tools[${index2}] must be an object.`, "INVALID_INPUT");
2079
- const toolId = required9(tool.toolId, `tools[${index2}].toolId`);
2080
- const command = required9(tool.command, `tools[${index2}].command`);
3157
+ const toolId = required10(tool.toolId, `tools[${index2}].toolId`);
3158
+ const command = required10(tool.command, `tools[${index2}].command`);
2081
3159
  if (tool.args !== void 0 && (!Array.isArray(tool.args) || tool.args.some((arg) => typeof arg !== "string"))) fail(`tools[${index2}].args must contain strings.`, "INVALID_INPUT");
2082
3160
  if (tool.env !== void 0 && (typeof tool.env !== "object" || tool.env === null || Array.isArray(tool.env) || Object.values(tool.env).some((value) => typeof value !== "string"))) fail(`tools[${index2}].env must contain string values.`, "INVALID_INPUT");
2083
3161
  return { toolId, command, args: tool.args ? [...tool.args] : [], ...tool.cwd ? { cwd: tool.cwd } : {}, env: tool.env ? { ...tool.env } : { PATH: process.env["PATH"] ?? "" } };
2084
3162
  });
2085
3163
  if (new Set(normalized.map((tool) => tool.toolId)).size !== normalized.length) fail("Process runtime tools must have unique ids.", "INVALID_INPUT");
2086
3164
  return {
3165
+ assurance: "contract-tested",
3166
+ isolation: "none",
3167
+ telemetry: () => ({ status: "unknown" }),
2087
3168
  execute: async (request) => {
2088
3169
  const started = Date.now();
2089
- const actionId = required9(request.actionId, "request.actionId");
2090
- const turnId = required9(request.turnId, "request.turnId");
2091
- const toolId = required9(request.toolId, "request.toolId");
2092
- const argumentsHash = required9(request.argumentsHash, "request.argumentsHash");
3170
+ const actionId = required10(request.actionId, "request.actionId");
3171
+ const turnId = required10(request.turnId, "request.turnId");
3172
+ const toolId = required10(request.toolId, "request.toolId");
3173
+ const argumentsHash = required10(request.argumentsHash, "request.argumentsHash");
2093
3174
  const tool = normalized.find((candidate) => candidate.toolId === toolId);
2094
3175
  if (!tool) return { status: "failed", errorCode: "TOOL_NOT_FOUND", retryable: false, durationMs: Date.now() - started };
2095
3176
  let input;
@@ -2159,17 +3240,17 @@ var createDockerToolRuntime = ({
2159
3240
  pull = "never"
2160
3241
  }) => {
2161
3242
  if (!Array.isArray(tools)) fail("Docker runtime tools must be an array.", "INVALID_INPUT");
2162
- const command = required9(dockerCommand, "dockerCommand");
2163
- const memory = required9(memoryLimit, "memoryLimit");
3243
+ const command = required10(dockerCommand, "dockerCommand");
3244
+ const memory = required10(memoryLimit, "memoryLimit");
2164
3245
  const cpu = positiveNumber(cpus, "cpus");
2165
3246
  if (!Number.isInteger(pidsLimit) || pidsLimit < 1) fail("pidsLimit must be a positive integer.", "INVALID_INPUT");
2166
- const normalizedUser = required9(user, "user");
3247
+ const normalizedUser = required10(user, "user");
2167
3248
  if (normalizedUser.includes(" ")) fail("user must not contain spaces.", "INVALID_INPUT");
2168
3249
  if (pull !== "never" && pull !== "missing" && pull !== "always") fail("pull must be never, missing, or always.", "INVALID_INPUT");
2169
3250
  const normalized = tools.map((tool, index2) => {
2170
3251
  if (typeof tool !== "object" || tool === null || Array.isArray(tool)) fail(`tools[${index2}] must be an object.`, "INVALID_INPUT");
2171
- const toolId = required9(tool.toolId, `tools[${index2}].toolId`);
2172
- const image = required9(tool.image, `tools[${index2}].image`);
3252
+ const toolId = required10(tool.toolId, `tools[${index2}].toolId`);
3253
+ const image = required10(tool.image, `tools[${index2}].image`);
2173
3254
  if (!Array.isArray(tool.command) || tool.command.length === 0 || tool.command.some((part) => typeof part !== "string" || !part.trim())) fail(`tools[${index2}].command must be a non-empty string array.`, "INVALID_INPUT");
2174
3255
  if (tool.args !== void 0 && (!Array.isArray(tool.args) || tool.args.some((arg) => typeof arg !== "string"))) fail(`tools[${index2}].args must contain strings.`, "INVALID_INPUT");
2175
3256
  const env = dockerEnvironment(tool.env, `tools[${index2}].env`);
@@ -2221,6 +3302,9 @@ var createDockerToolRuntime = ({
2221
3302
  if (new Set(normalized.map((tool) => tool.toolId)).size !== normalized.length) fail("Docker runtime tools must have unique ids.", "INVALID_INPUT");
2222
3303
  const processRuntime = createProcessToolRuntime({ tools: normalized, timeoutMs, maxOutputBytes });
2223
3304
  return {
3305
+ assurance: "runtime-attested",
3306
+ isolation: "sandboxed",
3307
+ telemetry: () => ({ status: "unknown" }),
2224
3308
  execute: async (request) => {
2225
3309
  const tool = normalized.find((candidate) => candidate.toolId === request.toolId);
2226
3310
  if (!tool) return processRuntime.execute(request);
@@ -2231,7 +3315,7 @@ var createDockerToolRuntime = ({
2231
3315
  imageDigest = inspected.stdout.trim();
2232
3316
  if (!/^sha256:[a-f0-9]{64}$/.test(imageDigest)) throw new Error("Docker image inspection did not return a digest.");
2233
3317
  } catch {
2234
- return { status: "failed", errorCode: "IMAGE_UNAVAILABLE", retryable: true, durationMs: duration2(Date.now() - started), runtimeEvidence: tool.evidence };
3318
+ return { status: "failed", errorCode: "IMAGE_UNAVAILABLE", retryable: true, durationMs: duration4(Date.now() - started), runtimeEvidence: tool.evidence };
2235
3319
  }
2236
3320
  const runtimeEvidence = { ...tool.evidence, imageDigest, profileHash: hashJson({ ...tool.evidence, imageDigest }) };
2237
3321
  const result = await processRuntime.execute(request);
@@ -2239,7 +3323,7 @@ var createDockerToolRuntime = ({
2239
3323
  }
2240
3324
  };
2241
3325
  };
2242
- var required10 = (value, label) => {
3326
+ var required11 = (value, label) => {
2243
3327
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
2244
3328
  return value.trim();
2245
3329
  };
@@ -2249,20 +3333,20 @@ var parse = (value, label) => {
2249
3333
  try {
2250
3334
  const raw = JSON.parse(value);
2251
3335
  const identity = {
2252
- tracker: required10(raw["tracker"], `${label}.tracker`),
2253
- repository: required10(raw["repository"], `${label}.repository`),
2254
- issue: required10(raw["issue"], `${label}.issue`),
2255
- worktree: required10(raw["worktree"], `${label}.worktree`),
2256
- branch: required10(raw["branch"], `${label}.branch`)
3336
+ tracker: required11(raw["tracker"], `${label}.tracker`),
3337
+ repository: required11(raw["repository"], `${label}.repository`),
3338
+ issue: required11(raw["issue"], `${label}.issue`),
3339
+ worktree: required11(raw["worktree"], `${label}.worktree`),
3340
+ branch: required11(raw["branch"], `${label}.branch`)
2257
3341
  };
2258
- return { ...identity, key: required10(raw["key"], `${label}.key`), leaseId: required10(raw["leaseId"], `${label}.leaseId`), owner: required10(raw["owner"], `${label}.owner`), claimedAt: required10(raw["claimedAt"], `${label}.claimedAt`) };
3342
+ return { ...identity, key: required11(raw["key"], `${label}.key`), leaseId: required11(raw["leaseId"], `${label}.leaseId`), owner: required11(raw["owner"], `${label}.owner`), claimedAt: required11(raw["claimedAt"], `${label}.claimedAt`) };
2259
3343
  } catch (error) {
2260
3344
  if (error instanceof SyntaxError) fail(`${label} contains invalid JSON.`, "HARNESS_ERROR");
2261
3345
  throw error;
2262
3346
  }
2263
3347
  };
2264
3348
  var createDispatchLedger = (stateDir) => {
2265
- const root = required10(stateDir, "stateDir");
3349
+ const root = required11(stateDir, "stateDir");
2266
3350
  const claimsDir = join(root, "coordination", "claims");
2267
3351
  const ledgerPath = join(root, "coordination", "dispatch-ledger.ndjson");
2268
3352
  mkdirSync(claimsDir, { recursive: true });
@@ -2290,13 +3374,13 @@ var createDispatchLedger = (stateDir) => {
2290
3374
  return {
2291
3375
  claim: (input) => {
2292
3376
  const identity = {
2293
- tracker: required10(input.tracker, "tracker"),
2294
- repository: required10(input.repository, "repository"),
2295
- issue: required10(input.issue, "issue"),
2296
- worktree: required10(input.worktree, "worktree"),
2297
- branch: required10(input.branch, "branch")
3377
+ tracker: required11(input.tracker, "tracker"),
3378
+ repository: required11(input.repository, "repository"),
3379
+ issue: required11(input.issue, "issue"),
3380
+ worktree: required11(input.worktree, "worktree"),
3381
+ branch: required11(input.branch, "branch")
2298
3382
  };
2299
- const owner = required10(input.owner, "owner");
3383
+ const owner = required11(input.owner, "owner");
2300
3384
  const key = safeKey(identity);
2301
3385
  const path = claimPath(key);
2302
3386
  if (existsSync(path)) return { decision: "already-claimed", lease: parse(readFileSync(path, "utf8"), "claim") };
@@ -2317,27 +3401,27 @@ var createDispatchLedger = (stateDir) => {
2317
3401
  return { decision: "claimed", lease };
2318
3402
  },
2319
3403
  recordDispatch: ({ lease, idempotencyKey, commandDigest }) => {
2320
- const id2 = required10(idempotencyKey, "idempotencyKey");
2321
- const digest3 = required10(commandDigest, "commandDigest");
3404
+ const id2 = required11(idempotencyKey, "idempotencyKey");
3405
+ const digest6 = required11(commandDigest, "commandDigest");
2322
3406
  const existing = records().find((record4) => record4.action === "dispatch" && record4.idempotencyKey === id2);
2323
3407
  if (existing) return { decision: "duplicate", record: existing };
2324
- const record3 = { ...lease, action: "dispatch", at: now3(), idempotencyKey: id2, commandDigest: digest3 };
3408
+ const record3 = { ...lease, action: "dispatch", at: now3(), idempotencyKey: id2, commandDigest: digest6 };
2325
3409
  append(record3);
2326
3410
  return { decision: "recorded", record: record3 };
2327
3411
  },
2328
3412
  release: (lease, reason = "lease released") => {
2329
- const path = claimPath(required10(lease.key, "lease.key"));
3413
+ const path = claimPath(required11(lease.key, "lease.key"));
2330
3414
  if (!existsSync(path)) fail("Dispatch lease is not active.", "INVALID_STATE");
2331
3415
  const current = parse(readFileSync(path, "utf8"), "claim");
2332
3416
  if (current.leaseId !== lease.leaseId) fail("Dispatch lease owner does not match.", "INVALID_STATE");
2333
3417
  unlinkSync(path);
2334
- const record3 = { ...current, action: "release", at: now3(), reason: required10(reason, "reason") };
3418
+ const record3 = { ...current, action: "release", at: now3(), reason: required11(reason, "reason") };
2335
3419
  append(record3);
2336
3420
  return record3;
2337
3421
  },
2338
3422
  recover: (key, input) => {
2339
3423
  if (input.actor !== "human") fail("Dispatch lease recovery requires a human actor.", "HUMAN_APPROVAL_REQUIRED");
2340
- const normalizedKey = required10(key, "key");
3424
+ const normalizedKey = required11(key, "key");
2341
3425
  const maxAgeMs = input.maxAgeMs ?? 3e5;
2342
3426
  if (!Number.isInteger(maxAgeMs) || maxAgeMs < 0) fail("maxAgeMs must be a non-negative integer.", "INVALID_INPUT");
2343
3427
  const path = claimPath(normalizedKey);
@@ -2345,7 +3429,7 @@ var createDispatchLedger = (stateDir) => {
2345
3429
  const current = parse(readFileSync(path, "utf8"), "claim");
2346
3430
  if (Date.now() - Date.parse(current.claimedAt) < maxAgeMs) fail("Dispatch lease is not old enough to recover.", "HARNESS_ERROR");
2347
3431
  unlinkSync(path);
2348
- const record3 = { ...current, action: "recover", at: now3(), reason: required10(input.reason, "reason") };
3432
+ const record3 = { ...current, action: "recover", at: now3(), reason: required11(input.reason, "reason") };
2349
3433
  append(record3);
2350
3434
  return record3;
2351
3435
  },
@@ -2353,73 +3437,6 @@ var createDispatchLedger = (stateDir) => {
2353
3437
  records
2354
3438
  };
2355
3439
  };
2356
-
2357
- // src/resilience.ts
2358
- var positiveInteger = (value, label) => {
2359
- if (!Number.isInteger(value) || value < 1) fail(`${label} must be a positive integer.`, "INVALID_INPUT");
2360
- return value;
2361
- };
2362
- var nonNegativeInteger3 = (value, label) => {
2363
- if (!Number.isInteger(value) || value < 0) fail(`${label} must be a non-negative integer.`, "INVALID_INPUT");
2364
- return value;
2365
- };
2366
- var classifyFailure = (error) => {
2367
- const value = error;
2368
- const code = typeof value?.code === "string" ? value.code.toUpperCase() : "";
2369
- const message = typeof value?.message === "string" ? value.message : String(error);
2370
- const text5 = `${code} ${message}`.toLowerCase();
2371
- if (/quota|rate.?limit|too many requests|429/.test(text5)) return { class: "quota", retryable: true, reason: message };
2372
- if (/timeout|timed out|deadline/.test(text5)) return { class: "timeout", retryable: true, reason: message };
2373
- if (/policy|forbidden|permission|approval/.test(text5)) return { class: "policy", retryable: false, reason: message };
2374
- if (/invalid|schema|argument|config|validation/.test(text5)) return { class: "validation", retryable: false, reason: message };
2375
- if (/network|connection|econn|503|502|external/.test(text5)) return { class: "external", retryable: true, reason: message };
2376
- return { class: "unknown", retryable: false, reason: message };
2377
- };
2378
- var recoveryDelayMs = (attempt, policy) => {
2379
- positiveInteger(attempt, "attempt");
2380
- nonNegativeInteger3(policy.baseDelayMs, "baseDelayMs");
2381
- nonNegativeInteger3(policy.maxDelayMs, "maxDelayMs");
2382
- if (policy.maxDelayMs < policy.baseDelayMs) fail("maxDelayMs must be greater than or equal to baseDelayMs.", "INVALID_INPUT");
2383
- return Math.min(policy.maxDelayMs, policy.baseDelayMs * 2 ** Math.max(0, attempt - 1));
2384
- };
2385
- var wait = (delayMs, sleep) => delayMs > 0 ? sleep(delayMs) : Promise.resolve();
2386
- var runWithRecovery = async (operation, options) => {
2387
- const maxAttempts = positiveInteger(options.maxAttempts, "maxAttempts");
2388
- const baseDelayMs = nonNegativeInteger3(options.baseDelayMs, "baseDelayMs");
2389
- const maxDelayMs = nonNegativeInteger3(options.maxDelayMs, "maxDelayMs");
2390
- if (maxDelayMs < baseDelayMs) fail("maxDelayMs must be greater than or equal to baseDelayMs.", "INVALID_INPUT");
2391
- if (options.timeoutMs !== void 0) positiveInteger(options.timeoutMs, "timeoutMs");
2392
- const sleep = options.sleep ?? ((delayMs) => new Promise((resolve6) => setTimeout(resolve6, delayMs)));
2393
- const observations = [];
2394
- for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
2395
- const controller = new AbortController();
2396
- let timer;
2397
- try {
2398
- const operationPromise = operation(controller.signal, attempt);
2399
- const value = options.timeoutMs === void 0 ? await operationPromise : await Promise.race([
2400
- operationPromise,
2401
- new Promise((_, reject) => {
2402
- timer = setTimeout(() => {
2403
- controller.abort();
2404
- reject(new Error("operation timed out"));
2405
- }, options.timeoutMs);
2406
- })
2407
- ]);
2408
- return { status: "completed", attempts: attempt, observations, value };
2409
- } catch (error) {
2410
- const failure = classifyFailure(error);
2411
- const delayMs = failure.retryable && attempt < maxAttempts ? recoveryDelayMs(attempt, { baseDelayMs, maxDelayMs }) : 0;
2412
- const observation = { attempt, failure, delayMs };
2413
- observations.push(observation);
2414
- options.onObservation?.(observation);
2415
- if (!failure.retryable || attempt >= maxAttempts) return { status: "failed", attempts: attempt, observations, failure };
2416
- await wait(delayMs, sleep);
2417
- } finally {
2418
- if (timer) clearTimeout(timer);
2419
- }
2420
- }
2421
- return fail("Recovery loop exhausted unexpectedly.", "HARNESS_ERROR");
2422
- };
2423
3440
  var DOC_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdx", ".txt", ".adoc", ".rst"]);
2424
3441
  var TEST_SUFFIXES = [".test.", ".spec.", "__tests__"];
2425
3442
  var SHELL_META = /[;&|`$()<>\n\r]/;
@@ -2454,9 +3471,9 @@ var planFilePreflight = (files, options = {}) => {
2454
3471
  return { files: unique2, codeFiles, testFiles, docsOnly, checks: docsOnly ? [] : ["lint", "typecheck", ...testFiles.length ? ["test"] : []] };
2455
3472
  };
2456
3473
 
2457
- // src/block.ts
3474
+ // src/kernel/block.ts
2458
3475
  var BLOCK_STATUSES = ["todo", "picked", "development", "validation", "pr-open", "merged", "post-merge", "done", "blocked", "scope-cut"];
2459
- var text3 = (value, label) => {
3476
+ var text5 = (value, label) => {
2460
3477
  return typeof value === "string" && value.trim() ? value.trim() : fail(`${label} must be a non-empty string.`, "INVALID_INPUT");
2461
3478
  };
2462
3479
  var list = (value, label) => {
@@ -2483,17 +3500,17 @@ var validateBlockManifest = (value) => {
2483
3500
  for (const key of ["maxMinutes", "maxAttempts"]) if (candidate[key] !== void 0 && (!Number.isInteger(candidate[key]) || candidate[key] < 1)) fail(`budget.${key} must be a positive integer.`, "INVALID_INPUT");
2484
3501
  budget = { ...candidate["maxMinutes"] === void 0 ? {} : { maxMinutes: candidate["maxMinutes"] }, ...candidate["maxAttempts"] === void 0 ? {} : { maxAttempts: candidate["maxAttempts"] } };
2485
3502
  }
2486
- return { schemaVersion: 1, id: text3(raw["id"], "id"), title: text3(raw["title"], "title"), tracker: text3(raw["tracker"], "tracker"), repository: text3(raw["repository"], "repository"), acceptanceCriteria: criteria, dependencies, wave, status, ...budget ? { budget } : {}, ...raw["humanGates"] === void 0 ? {} : { humanGates: list(raw["humanGates"], "humanGates") }, ...raw["sourceHash"] === void 0 ? {} : { sourceHash: text3(raw["sourceHash"], "sourceHash") } };
3503
+ return { schemaVersion: 1, id: text5(raw["id"], "id"), title: text5(raw["title"], "title"), tracker: text5(raw["tracker"], "tracker"), repository: text5(raw["repository"], "repository"), acceptanceCriteria: criteria, dependencies, wave, status, ...budget ? { budget } : {}, ...raw["humanGates"] === void 0 ? {} : { humanGates: list(raw["humanGates"], "humanGates") }, ...raw["sourceHash"] === void 0 ? {} : { sourceHash: text5(raw["sourceHash"], "sourceHash") } };
2487
3504
  };
2488
3505
  var assessBlock = (manifest, completedDependencies = []) => {
2489
3506
  const value = validateBlockManifest(manifest);
2490
- const completed = new Set(completedDependencies.map((item) => text3(item, "completedDependencies[]")));
3507
+ const completed = new Set(completedDependencies.map((item) => text5(item, "completedDependencies[]")));
2491
3508
  const blockers = value.dependencies.filter((dependency) => !completed.has(dependency));
2492
3509
  const next = blockers.length ? [`Complete dependencies: ${blockers.join(", ")}`] : value.status === "blocked" ? ["Resolve the recorded blocker before dispatch."] : ["Dispatch the block with the frozen acceptance criteria."];
2493
3510
  return { status: blockers.length || value.status === "blocked" ? "blocked" : "ready", manifestHash: hashJson(value), blockers, next };
2494
3511
  };
2495
3512
  var LEARNING_STATUSES = ["proposed", "promoted", "rejected"];
2496
- var text4 = (value, label) => {
3513
+ var text6 = (value, label) => {
2497
3514
  return typeof value === "string" && value.trim() ? value.trim() : fail(`${label} must be a non-empty string.`, "INVALID_INPUT");
2498
3515
  };
2499
3516
  var category = (heading) => {
@@ -2504,8 +3521,8 @@ var category = (heading) => {
2504
3521
  return "other";
2505
3522
  };
2506
3523
  var parseRetro = (markdown, source, recordedAt = (/* @__PURE__ */ new Date()).toISOString()) => {
2507
- const input = text4(markdown, "markdown");
2508
- const origin = text4(source, "source");
3524
+ const input = text6(markdown, "markdown");
3525
+ const origin = text6(source, "source");
2509
3526
  if (!Number.isFinite(Date.parse(recordedAt))) fail("recordedAt must be a valid timestamp.", "INVALID_INPUT");
2510
3527
  const records = [];
2511
3528
  let current = "other";
@@ -2525,7 +3542,7 @@ var parseRetro = (markdown, source, recordedAt = (/* @__PURE__ */ new Date()).to
2525
3542
  };
2526
3543
  var promoteLearnings = (records, input) => {
2527
3544
  if (input.actor !== "human") fail("Learning promotion requires a human actor.", "HUMAN_APPROVAL_REQUIRED");
2528
- const ids = new Set(input.ids.map((id2) => text4(id2, "ids[]")));
3545
+ const ids = new Set(input.ids.map((id2) => text6(id2, "ids[]")));
2529
3546
  const status = input.status ?? "promoted";
2530
3547
  const result = records.map((record3) => ids.has(record3.id) ? { ...record3, status } : record3);
2531
3548
  const unknown = [...ids].filter((id2) => !records.some((record3) => record3.id === id2));
@@ -2533,12 +3550,12 @@ var promoteLearnings = (records, input) => {
2533
3550
  return result;
2534
3551
  };
2535
3552
 
2536
- // src/status.ts
2537
- var required11 = (value, label) => {
3553
+ // src/kernel/status.ts
3554
+ var required12 = (value, label) => {
2538
3555
  return typeof value === "string" && value.trim() ? value.trim() : fail(`${label} must be a non-empty string.`, "INVALID_INPUT");
2539
3556
  };
2540
3557
  var createStatusSnapshot = (input) => {
2541
- const sourceRevision = required11(input.sourceRevision, "sourceRevision");
3558
+ const sourceRevision = required12(input.sourceRevision, "sourceRevision");
2542
3559
  if (!Number.isFinite(Date.parse(input.generatedAt))) fail("generatedAt must be a valid timestamp.", "INVALID_INPUT");
2543
3560
  if (!Array.isArray(input.blocks)) fail("blocks must be an array.", "INVALID_INPUT");
2544
3561
  const blocks = input.blocks.map((block, index2) => {
@@ -2549,20 +3566,20 @@ var createStatusSnapshot = (input) => {
2549
3566
  return { ...value, id: value.id.trim() };
2550
3567
  }).sort((left, right) => left.id.localeCompare(right.id));
2551
3568
  if (input.metrics !== void 0 && Object.entries(input.metrics).some(([key, value]) => !key.trim() || typeof value !== "number" || !Number.isFinite(value) || value < 0)) fail("metrics must contain finite non-negative numbers.", "INVALID_INPUT");
2552
- const body2 = { schemaVersion: 1, generatedAt: input.generatedAt, sourceRevision, blocks, ...input.machine ? { machine: input.machine } : {}, ...input.metrics ? { metrics: input.metrics } : {}, ...input.next ? { next: required11(input.next, "next") } : {} };
2553
- return { ...body2, digest: hashJson(body2) };
3569
+ const body3 = { schemaVersion: 1, generatedAt: input.generatedAt, sourceRevision, blocks, ...input.machine ? { machine: input.machine } : {}, ...input.metrics ? { metrics: input.metrics } : {}, ...input.next ? { next: required12(input.next, "next") } : {} };
3570
+ return { ...body3, digest: hashJson(body3) };
2554
3571
  };
2555
3572
  var validateStatusSnapshot = (value) => {
2556
3573
  if (typeof value !== "object" || value === null || Array.isArray(value)) fail("status snapshot must be an object.", "INVALID_INPUT");
2557
3574
  const raw = value;
2558
- const snapshot = createStatusSnapshot({ generatedAt: required11(raw.generatedAt, "generatedAt"), sourceRevision: required11(raw.sourceRevision, "sourceRevision"), blocks: raw.blocks, ...raw.machine ? { machine: raw.machine } : {}, ...raw.metrics ? { metrics: raw.metrics } : {}, ...raw.next ? { next: raw.next } : {} });
3575
+ const snapshot = createStatusSnapshot({ generatedAt: required12(raw.generatedAt, "generatedAt"), sourceRevision: required12(raw.sourceRevision, "sourceRevision"), blocks: raw.blocks, ...raw.machine ? { machine: raw.machine } : {}, ...raw.metrics ? { metrics: raw.metrics } : {}, ...raw.next ? { next: raw.next } : {} });
2559
3576
  if (raw.schemaVersion !== 1 || raw.digest !== snapshot.digest) fail("status snapshot digest or schemaVersion is invalid.", "HARNESS_ERROR");
2560
3577
  return snapshot;
2561
3578
  };
2562
3579
 
2563
- // src/model-policy.ts
3580
+ // src/kernel/model-policy.ts
2564
3581
  var MODEL_ROLES = ["orchestrator", "reviewer", "builder", "watcher"];
2565
- var required12 = (value, label) => {
3582
+ var required13 = (value, label) => {
2566
3583
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
2567
3584
  return value.trim();
2568
3585
  };
@@ -2572,7 +3589,7 @@ var createModelPolicy = (bindings) => {
2572
3589
  if (typeof binding2 !== "object" || binding2 === null || Array.isArray(binding2)) fail(`bindings[${index2}] must be an object.`, "INVALID_INPUT");
2573
3590
  if (!MODEL_ROLES.includes(binding2.role)) fail(`bindings[${index2}].role is invalid.`, "INVALID_INPUT");
2574
3591
  if (binding2.maxTokens !== void 0 && (!Number.isInteger(binding2.maxTokens) || binding2.maxTokens < 1)) fail(`bindings[${index2}].maxTokens must be a positive integer.`, "INVALID_INPUT");
2575
- return { role: binding2.role, provider: required12(binding2.provider, `bindings[${index2}].provider`), model: required12(binding2.model, `bindings[${index2}].model`), ...binding2.maxTokens === void 0 ? {} : { maxTokens: binding2.maxTokens } };
3592
+ return { role: binding2.role, provider: required13(binding2.provider, `bindings[${index2}].provider`), model: required13(binding2.model, `bindings[${index2}].model`), ...binding2.maxTokens === void 0 ? {} : { maxTokens: binding2.maxTokens } };
2576
3593
  });
2577
3594
  if (new Set(normalized.map((binding2) => binding2.role)).size !== normalized.length) fail("Each model role may be bound only once.", "INVALID_INPUT");
2578
3595
  return { bindings: normalized, digest: hashJson(normalized) };
@@ -2580,42 +3597,69 @@ var createModelPolicy = (bindings) => {
2580
3597
  var modelFor = (policy, role) => policy.bindings.find((binding2) => binding2.role === role) ?? fail(`No model binding exists for role: ${role}.`, "INVALID_STATE");
2581
3598
 
2582
3599
  // src/adapters/orca.ts
2583
- var required13 = (value, label) => {
3600
+ var required14 = (value, label) => {
2584
3601
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
2585
3602
  return value.trim();
2586
3603
  };
2587
3604
  var createOrcaDispatchPlan = (input) => {
2588
- const repository = required13(input.repository, "repository");
2589
- const worktree = required13(input.worktree, "worktree");
2590
- const branch = required13(input.branch, "branch");
2591
- const baseBranch = required13(input.baseBranch, "baseBranch");
2592
- const goalFile = required13(input.goalFile, "goalFile");
2593
- const agent = required13(input.agent ?? "default", "agent");
3605
+ const repository = required14(input.repository, "repository");
3606
+ const worktree = required14(input.worktree, "worktree");
3607
+ const branch = required14(input.branch, "branch");
3608
+ const baseBranch = required14(input.baseBranch, "baseBranch");
3609
+ const goalFile = required14(input.goalFile, "goalFile");
3610
+ const agent = required14(input.agent ?? "default", "agent");
2594
3611
  const argv = ["orca", "worktree", "create", "--repo", repository, "--name", worktree, "--base-branch", baseBranch, "--agent", agent, "--prompt-file", goalFile];
2595
3612
  validateSafeCommand(argv.join(" "));
2596
3613
  const identity = { repository, worktree, branch, baseBranch, goalFile, agent };
2597
3614
  return { argv, commandDigest: hashJson(argv), idempotencyKey: hashJson(identity) };
2598
3615
  };
3616
+ var createOrcaLifecycleProjection = (input) => {
3617
+ const issueRef = required14(input.issueRef, "issueRef");
3618
+ const repository = required14(input.repository, "repository");
3619
+ const worktree = required14(input.worktree, "worktree");
3620
+ const branch = required14(input.branch, "branch");
3621
+ if (!["acquired", "resumed", "conflict", "released"].includes(input.leaseState)) fail("leaseState is invalid.", "INVALID_INPUT");
3622
+ if (input.issueLock !== "held" && input.issueLock !== "missing") fail("issueLock is invalid.", "INVALID_INPUT");
3623
+ const expected = input.expectedRemoteSha?.trim();
3624
+ const observed = input.observedRemoteSha?.trim();
3625
+ const remoteShaConfirmed = Boolean(expected && observed && expected === observed);
3626
+ const cleanupAllowed = input.cleanupRequested === true && remoteShaConfirmed && input.leaseState === "released";
3627
+ const status = input.leaseState === "conflict" || input.issueLock === "missing" ? "blocked" : input.cleanupRequested === true && !remoteShaConfirmed ? "escalated" : input.leaseState === "resumed" ? "resume" : "ready";
3628
+ return { status, leaseState: input.leaseState, worktreeKey: hashJson({ issueRef, repository, worktree, branch }), issueLock: input.issueLock, remoteShaConfirmed, cleanupAllowed, assurance: "contract-tested", telemetry: { status: "measured", durationMs: 0 } };
3629
+ };
2599
3630
 
2600
3631
  // src/adapters/tracking.ts
2601
- var required14 = (value, label) => {
3632
+ var required15 = (value, label) => {
2602
3633
  if (typeof value !== "string" || !value.trim()) fail(`${label} is required.`, "INVALID_INPUT");
2603
3634
  return value.trim();
2604
3635
  };
2605
3636
  var createTrackingTransition = (input) => {
2606
- const transition2 = { tracker: required14(input.tracker, "tracker"), issue: required14(input.issue, "issue"), ...input.from ? { from: required14(input.from, "from") } : {}, to: required14(input.to, "to"), reason: required14(input.reason, "reason") };
3637
+ const transition2 = { tracker: required15(input.tracker, "tracker"), issue: required15(input.issue, "issue"), ...input.from ? { from: required15(input.from, "from") } : {}, to: required15(input.to, "to"), reason: required15(input.reason, "reason") };
2607
3638
  return { ...transition2, idempotencyKey: hashJson(transition2) };
2608
3639
  };
2609
- var createTrackingAdapter = (id2, handler) => {
2610
- const adapterId = required14(id2, "id");
2611
- return { id: adapterId, transition: async (input) => {
2612
- const transition2 = createTrackingTransition(input);
2613
- await handler(transition2);
2614
- return transition2;
2615
- } };
3640
+ var createTrackingAdapter = (id2, handler, options = {}) => {
3641
+ const adapterId = required15(id2, "id");
3642
+ const completed = /* @__PURE__ */ new Set();
3643
+ let writes = 0;
3644
+ return {
3645
+ id: adapterId,
3646
+ assurance: "contract-tested",
3647
+ telemetry: () => ({ status: "measured", externalMutations: writes }),
3648
+ transition: async (input) => {
3649
+ const transition2 = createTrackingTransition(input);
3650
+ if (!completed.has(transition2.idempotencyKey)) {
3651
+ if (!options.dryRun) {
3652
+ await handler(transition2);
3653
+ writes += 1;
3654
+ }
3655
+ completed.add(transition2.idempotencyKey);
3656
+ }
3657
+ return transition2;
3658
+ }
3659
+ };
2616
3660
  };
2617
3661
  var EVIDENCE_BUNDLE_SCHEMA_VERSION = 1;
2618
- var body = (bundle) => {
3662
+ var body2 = (bundle) => {
2619
3663
  const { payloadHash: _payloadHash, signature: _signature, ...unsigned } = bundle;
2620
3664
  return unsigned;
2621
3665
  };
@@ -2640,7 +3684,7 @@ var exportEvidenceBundle = async ({ configPath, runId, outputPath, privateKeyPat
2640
3684
  const loaded = loadConfig(configPath);
2641
3685
  const run = requireRun2(runId ? readJson(join(loaded.stateDir, "runs", runId, "run.json")) : loadLatestRun(loaded.stateDir));
2642
3686
  const reconciliation = await reconcileRun({ configPath, runId: run.runId });
2643
- const digest3 = run.verificationDigest ?? fail("Only a reconciled COMPLETE run can be exported.", "INVALID_STATE");
3687
+ const digest6 = run.verificationDigest ?? fail("Only a reconciled COMPLETE run can be exported.", "INVALID_STATE");
2644
3688
  if (reconciliation.state !== "COMPLETE") fail("Only a reconciled COMPLETE run can be exported.", "INVALID_STATE");
2645
3689
  const eventLog = new FileEventStore(loaded.stateDir);
2646
3690
  eventLog.read(run.runId);
@@ -2655,7 +3699,7 @@ var exportEvidenceBundle = async ({ configPath, runId, outputPath, privateKeyPat
2655
3699
  return bundleFile(loaded.stateDir, path);
2656
3700
  });
2657
3701
  const privateKey = createPrivateKey(readFileSync(privateKeyPath));
2658
- const unsigned = { type: "agentskit-harness-evidence-bundle", schemaVersion: EVIDENCE_BUNDLE_SCHEMA_VERSION, runId: run.runId, signerKeyId: keyId, sourceRevision: run.sourceRevision, configHash: run.configHash, contractHash: run.contractHash, verificationDigest: digest3, eventLog: eventVerification, files };
3702
+ const unsigned = { type: "agentskit-harness-evidence-bundle", schemaVersion: EVIDENCE_BUNDLE_SCHEMA_VERSION, runId: run.runId, signerKeyId: keyId, sourceRevision: run.sourceRevision, configHash: run.configHash, contractHash: run.contractHash, verificationDigest: digest6, eventLog: eventVerification, files };
2659
3703
  const payloadHash = sha256(JSON.stringify(unsigned));
2660
3704
  const publicKeyPem = createPublicKey(privateKey).export({ type: "spki", format: "pem" }).toString();
2661
3705
  const bundle = { ...unsigned, payloadHash, signature: { algorithm: "ed25519", keyId, publicKeyPem, signatureBase64: sign(null, Buffer.from(payloadHash), privateKey).toString("base64") } };
@@ -2680,7 +3724,7 @@ var verifyEvidenceBundle = (path, { trustedKeys = [] } = {}) => {
2680
3724
  if (sha256(content) !== file.sha256) fail(`Evidence bundle file hash mismatch: ${file.path}`, "HARNESS_ERROR");
2681
3725
  }
2682
3726
  if (!paths.has(`runs/${bundle.runId}/run.json`) || !paths.has(`runs/${bundle.runId}/events.ndjson`)) fail("Evidence bundle is missing the run projection or event log.", "HARNESS_ERROR");
2683
- if (sha256(JSON.stringify(body(bundle))) !== bundle.payloadHash) fail("Evidence bundle payload hash mismatch.", "HARNESS_ERROR");
3727
+ if (sha256(JSON.stringify(body2(bundle))) !== bundle.payloadHash) fail("Evidence bundle payload hash mismatch.", "HARNESS_ERROR");
2684
3728
  let valid = false;
2685
3729
  try {
2686
3730
  valid = verify(null, Buffer.from(bundle.payloadHash), createPublicKey(bundle.signature.publicKeyPem), Buffer.from(bundle.signature.signatureBase64, "base64"));
@@ -2699,6 +3743,6 @@ var readEvidenceTrustStore = (path) => {
2699
3743
  });
2700
3744
  };
2701
3745
 
2702
- export { BENCHMARK_SCHEMA_VERSION, BLOCK_STATUSES, CONTEXT_PROVIDER_SLOT, EVENT_LOG_GENESIS, EVIDENCE_BUNDLE_SCHEMA_VERSION, FileEventStore, HARNESS_EVENT_SCHEMA_VERSION, HARNESS_EVENT_TYPES, HARNESS_PLUGIN_API_VERSION, HarnessError, IMPROVEMENT_CYCLE_STEPS, LEARNING_STATUSES, LEGAL_TRANSITIONS, MEMORY_SCOPES, MODEL_ROLES, STATES, WIP_STATES, adaptiveConcurrency, approveRun, approvedDecision, assertHuman, assessAcceptance, assessAgentEval, assessBlock, assessDiscovery, assessImprovementCycle, assessIntegration, assessPilot, assessPreflight, assessProduction, assessWip, assessWorktreeCleanup, authorizeRun, benchmarkRuns, cancelRun, classifyFailure, cleanTaskArtifacts, compareOptimization, composePullRequest, createConfiguredToolRuntime, createDispatchLedger, createDocBridgeContextProvider, createDockerToolRuntime, createInMemoryMemoryAdapter, createKvMemoryAdapter, createLlmCache, createLlmCacheKey, createMachineMonitor, createModelPolicy, createOrcaDispatchPlan, createPluginRegistry, createPluginSlot, createPolicyGate, createProcessToolRuntime, createSessionRecorder, createStatusSnapshot, createToolRuntime, createTrackingAdapter, createTrackingTransition, exportEvidenceBundle, hashContextSnapshot, hashContextSnapshots, inspectEventLogLock, isDiscoveryCurrent, loadBenchmarkManifest, loadConfig, loadLatestRun, modelFor, parseRetro, planFilePreflight, planRun, promoteLearnings, readContextSnapshots, readEvidenceTrustStore, reconcileRun, recordBenchmarkObservation, recoverEventLogLock, recoveryDelayMs, retryRun, runAgentEval, runWithRecovery, runWorkflow, sampleMachine, selectRuntime, startRun, summarizeMachine, transition, validateBenchmarkManifest, validateBlockManifest, validateCacheableOperation, validateConfig, validateContextSnapshot, validateContextSnapshots, validateMemoryRecord, validateOptimizationObservation, validateSafeCommand, validateStatusSnapshot, verifyEvidenceBundle, verifyRun };
3746
+ export { ARTIFACT_SCHEMA_VERSION, ARTIFACT_TYPES, ASSURANCE_LEVELS, BENCHMARK_SCHEMA_VERSION, BLOCK_STATUSES, CAPABILITY_KINDS, CAPABILITY_MANIFEST_SCHEMA_VERSION, COMPATIBILITY_COMPONENTS, COMPATIBILITY_SCHEMA_VERSION, CONTEXT_PROVIDER_SLOT, EVAL_COMPONENTS, EVAL_LAYERS, EVAL_MANIFEST_SCHEMA_VERSION, EVENT_LOG_GENESIS, EVIDENCE_BUNDLE_SCHEMA_VERSION, FileArtifactStore, FileEventStore, HARNESS_ERROR_CATALOG, HARNESS_ERROR_CODES, HARNESS_EVENT_ENVELOPE_SCHEMA_VERSION, HARNESS_EVENT_SCHEMA_VERSION, HARNESS_EVENT_TYPES, HARNESS_PLUGIN_API_VERSION, HarnessError, IMPROVEMENT_CYCLE_STEPS, LEARNING_STATUSES, LEGAL_TRANSITIONS, MEMORY_SCOPES, MODEL_ROLES, PHASE_DECISIONS, PHASE_EFFECTS, PHASE_EFFECT_ACTIONS, PHASE_MODES, QUALITY_DIMENSIONS, STATES, WIP_STATES, adaptiveConcurrency, approveRun, approvedDecision, artifactDigest, artifactFilePath, artifactIsFresh, artifactMarkdownPath, assertHuman, assessAcceptance, assessAgentEval, assessBlock, assessCompatibility, assessDiscovery, assessImprovementCycle, assessIntegration, assessPilot, assessPreflight, assessProduction, assessQaTransition, assessWip, assessWorktreeCleanup, authorizeRun, benchmarkRuns, cancelRun, classifyFailure, classifyHarnessError, cleanTaskArtifacts, compareOptimization, composePullRequest, createArtifactEnvelope, createCapabilityManifest, createCodingAgentAdapter, createCompatibilityManifest, createConfiguredToolRuntime, createDispatchLedger, createDocBridgeContextProvider, createDockerToolRuntime, createEvalManifest, createHarnessEventEnvelope, createInMemoryMemoryAdapter, createKvMemoryAdapter, createLlmCache, createLlmCacheKey, createMachineMonitor, createModelPolicy, createOrcaDispatchPlan, createOrcaLifecycleProjection, createPhaseArtifact, createPhaseProfile, createPluginRegistry, createPluginSlot, createPolicyGate, createProcessToolRuntime, createPullRequestApproval, createQualityMatrix, createSessionRecorder, createStatusSnapshot, createToolRuntime, createTrackingAdapter, createTrackingTransition, evaluateWatchdog, executePhaseProfile, exportEvidenceBundle, hashContextSnapshot, hashContextSnapshots, inspectEventLogLock, isDiscoveryCurrent, loadBenchmarkManifest, loadConfig, loadLatestRun, modelFor, parseRetro, planFilePreflight, planPhaseProfile, planRun, promoteLearnings, readArtifactFile, readContextSnapshots, readEvidenceTrustStore, reconcileRun, recordBenchmarkObservation, recoverEventLogLock, recoveryDelayMs, renderArtifactMarkdown, resumeStateFromArtifacts, retryRun, runAdversarialReview, runAgentEval, runEvalBattery, runWithRecovery, runWorkflow, sampleMachine, selectRuntime, startRun, summarizeMachine, transition, unknownTelemetry, validateAdapterMetadata, validateArtifactEnvelope, validateBenchmarkManifest, validateBlockManifest, validateCacheableOperation, validateCapabilityManifest, validateCompatibilityManifest, validateConfig, validateContextSnapshot, validateContextSnapshots, validateEvalManifest, validateHarnessErrorClassification, validateHarnessEventEnvelope, validateMemoryRecord, validateOptimizationObservation, validatePhaseTelemetry, validateSafeCommand, validateStatusSnapshot, verifyEvidenceBundle, verifyPullRequestApproval, verifyRun };
2703
3747
  //# sourceMappingURL=index.js.map
2704
3748
  //# sourceMappingURL=index.js.map