@sw4rm/js-sdk 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.
@@ -1907,15 +1907,15 @@ var require_fetch = __commonJS({
1907
1907
  var require_path = __commonJS({
1908
1908
  "node_modules/@protobufjs/path/index.js"(exports2) {
1909
1909
  "use strict";
1910
- var path3 = exports2;
1910
+ var path4 = exports2;
1911
1911
  var isAbsolute = (
1912
1912
  /**
1913
1913
  * Tests if the specified path is absolute.
1914
1914
  * @param {string} path Path to test
1915
1915
  * @returns {boolean} `true` if path is absolute
1916
1916
  */
1917
- path3.isAbsolute = function isAbsolute2(path4) {
1918
- return /^(?:\/|\w+:)/.test(path4);
1917
+ path4.isAbsolute = function isAbsolute2(path5) {
1918
+ return /^(?:\/|\w+:)/.test(path5);
1919
1919
  }
1920
1920
  );
1921
1921
  var normalize = (
@@ -1924,9 +1924,9 @@ var require_path = __commonJS({
1924
1924
  * @param {string} path Path to normalize
1925
1925
  * @returns {string} Normalized path
1926
1926
  */
1927
- path3.normalize = function normalize2(path4) {
1928
- path4 = path4.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
1929
- var parts = path4.split("/"), absolute = isAbsolute(path4), prefix = "";
1927
+ path4.normalize = function normalize2(path5) {
1928
+ path5 = path5.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
1929
+ var parts = path5.split("/"), absolute = isAbsolute(path5), prefix = "";
1930
1930
  if (absolute)
1931
1931
  prefix = parts.shift() + "/";
1932
1932
  for (var i = 0; i < parts.length; ) {
@@ -1945,7 +1945,7 @@ var require_path = __commonJS({
1945
1945
  return prefix + parts.join("/");
1946
1946
  }
1947
1947
  );
1948
- path3.resolve = function resolve(originPath, includePath, alreadyNormalized) {
1948
+ path4.resolve = function resolve(originPath, includePath, alreadyNormalized) {
1949
1949
  if (!alreadyNormalized)
1950
1950
  includePath = normalize(includePath);
1951
1951
  if (isAbsolute(includePath))
@@ -2096,16 +2096,16 @@ var require_namespace = __commonJS({
2096
2096
  object.onRemove(this);
2097
2097
  return clearCache(this);
2098
2098
  };
2099
- Namespace.prototype.define = function define2(path3, json) {
2100
- if (util.isString(path3))
2101
- path3 = path3.split(".");
2102
- else if (!Array.isArray(path3))
2099
+ Namespace.prototype.define = function define2(path4, json) {
2100
+ if (util.isString(path4))
2101
+ path4 = path4.split(".");
2102
+ else if (!Array.isArray(path4))
2103
2103
  throw TypeError("illegal path");
2104
- if (path3 && path3.length && path3[0] === "")
2104
+ if (path4 && path4.length && path4[0] === "")
2105
2105
  throw Error("path must be relative");
2106
2106
  var ptr = this;
2107
- while (path3.length > 0) {
2108
- var part = path3.shift();
2107
+ while (path4.length > 0) {
2108
+ var part = path4.shift();
2109
2109
  if (ptr.nested && ptr.nested[part]) {
2110
2110
  ptr = ptr.nested[part];
2111
2111
  if (!(ptr instanceof Namespace))
@@ -2142,26 +2142,26 @@ var require_namespace = __commonJS({
2142
2142
  });
2143
2143
  return this;
2144
2144
  };
2145
- Namespace.prototype.lookup = function lookup(path3, filterTypes, parentAlreadyChecked) {
2145
+ Namespace.prototype.lookup = function lookup(path4, filterTypes, parentAlreadyChecked) {
2146
2146
  if (typeof filterTypes === "boolean") {
2147
2147
  parentAlreadyChecked = filterTypes;
2148
2148
  filterTypes = void 0;
2149
2149
  } else if (filterTypes && !Array.isArray(filterTypes))
2150
2150
  filterTypes = [filterTypes];
2151
- if (util.isString(path3) && path3.length) {
2152
- if (path3 === ".")
2151
+ if (util.isString(path4) && path4.length) {
2152
+ if (path4 === ".")
2153
2153
  return this.root;
2154
- path3 = path3.split(".");
2155
- } else if (!path3.length)
2154
+ path4 = path4.split(".");
2155
+ } else if (!path4.length)
2156
2156
  return this;
2157
- var flatPath = path3.join(".");
2158
- if (path3[0] === "")
2159
- return this.root.lookup(path3.slice(1), filterTypes);
2157
+ var flatPath = path4.join(".");
2158
+ if (path4[0] === "")
2159
+ return this.root.lookup(path4.slice(1), filterTypes);
2160
2160
  var found = this.root._fullyQualifiedObjects && this.root._fullyQualifiedObjects["." + flatPath];
2161
2161
  if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
2162
2162
  return found;
2163
2163
  }
2164
- found = this._lookupImpl(path3, flatPath);
2164
+ found = this._lookupImpl(path4, flatPath);
2165
2165
  if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
2166
2166
  return found;
2167
2167
  }
@@ -2169,7 +2169,7 @@ var require_namespace = __commonJS({
2169
2169
  return null;
2170
2170
  var current = this;
2171
2171
  while (current.parent) {
2172
- found = current.parent._lookupImpl(path3, flatPath);
2172
+ found = current.parent._lookupImpl(path4, flatPath);
2173
2173
  if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
2174
2174
  return found;
2175
2175
  }
@@ -2177,49 +2177,49 @@ var require_namespace = __commonJS({
2177
2177
  }
2178
2178
  return null;
2179
2179
  };
2180
- Namespace.prototype._lookupImpl = function lookup(path3, flatPath) {
2180
+ Namespace.prototype._lookupImpl = function lookup(path4, flatPath) {
2181
2181
  if (Object.prototype.hasOwnProperty.call(this._lookupCache, flatPath)) {
2182
2182
  return this._lookupCache[flatPath];
2183
2183
  }
2184
- var found = this.get(path3[0]);
2184
+ var found = this.get(path4[0]);
2185
2185
  var exact = null;
2186
2186
  if (found) {
2187
- if (path3.length === 1) {
2187
+ if (path4.length === 1) {
2188
2188
  exact = found;
2189
2189
  } else if (found instanceof Namespace) {
2190
- path3 = path3.slice(1);
2191
- exact = found._lookupImpl(path3, path3.join("."));
2190
+ path4 = path4.slice(1);
2191
+ exact = found._lookupImpl(path4, path4.join("."));
2192
2192
  }
2193
2193
  } else {
2194
2194
  for (var i = 0; i < this.nestedArray.length; ++i)
2195
- if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path3, flatPath)))
2195
+ if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path4, flatPath)))
2196
2196
  exact = found;
2197
2197
  }
2198
2198
  this._lookupCache[flatPath] = exact;
2199
2199
  return exact;
2200
2200
  };
2201
- Namespace.prototype.lookupType = function lookupType(path3) {
2202
- var found = this.lookup(path3, [Type]);
2201
+ Namespace.prototype.lookupType = function lookupType(path4) {
2202
+ var found = this.lookup(path4, [Type]);
2203
2203
  if (!found)
2204
- throw Error("no such type: " + path3);
2204
+ throw Error("no such type: " + path4);
2205
2205
  return found;
2206
2206
  };
2207
- Namespace.prototype.lookupEnum = function lookupEnum(path3) {
2208
- var found = this.lookup(path3, [Enum]);
2207
+ Namespace.prototype.lookupEnum = function lookupEnum(path4) {
2208
+ var found = this.lookup(path4, [Enum]);
2209
2209
  if (!found)
2210
- throw Error("no such Enum '" + path3 + "' in " + this);
2210
+ throw Error("no such Enum '" + path4 + "' in " + this);
2211
2211
  return found;
2212
2212
  };
2213
- Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path3) {
2214
- var found = this.lookup(path3, [Type, Enum]);
2213
+ Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path4) {
2214
+ var found = this.lookup(path4, [Type, Enum]);
2215
2215
  if (!found)
2216
- throw Error("no such Type or Enum '" + path3 + "' in " + this);
2216
+ throw Error("no such Type or Enum '" + path4 + "' in " + this);
2217
2217
  return found;
2218
2218
  };
2219
- Namespace.prototype.lookupService = function lookupService(path3) {
2220
- var found = this.lookup(path3, [Service]);
2219
+ Namespace.prototype.lookupService = function lookupService(path4) {
2220
+ var found = this.lookup(path4, [Service]);
2221
2221
  if (!found)
2222
- throw Error("no such Service '" + path3 + "' in " + this);
2222
+ throw Error("no such Service '" + path4 + "' in " + this);
2223
2223
  return found;
2224
2224
  };
2225
2225
  Namespace._configure = function(Type_, Service_, Enum_) {
@@ -3620,14 +3620,14 @@ var require_util = __commonJS({
3620
3620
  Object.defineProperty(object, "$type", { value: enm, enumerable: false });
3621
3621
  return enm;
3622
3622
  };
3623
- util.setProperty = function setProperty(dst, path3, value, ifNotSet) {
3624
- function setProp(dst2, path4, value2) {
3625
- var part = path4.shift();
3623
+ util.setProperty = function setProperty(dst, path4, value, ifNotSet) {
3624
+ function setProp(dst2, path5, value2) {
3625
+ var part = path5.shift();
3626
3626
  if (part === "__proto__" || part === "prototype") {
3627
3627
  return dst2;
3628
3628
  }
3629
- if (path4.length > 0) {
3630
- dst2[part] = setProp(dst2[part] || {}, path4, value2);
3629
+ if (path5.length > 0) {
3630
+ dst2[part] = setProp(dst2[part] || {}, path5, value2);
3631
3631
  } else {
3632
3632
  var prevValue = dst2[part];
3633
3633
  if (prevValue && ifNotSet)
@@ -3640,10 +3640,10 @@ var require_util = __commonJS({
3640
3640
  }
3641
3641
  if (typeof dst !== "object")
3642
3642
  throw TypeError("dst must be an object");
3643
- if (!path3)
3643
+ if (!path4)
3644
3644
  throw TypeError("path must be specified");
3645
- path3 = path3.split(".");
3646
- return setProp(dst, path3, value);
3645
+ path4 = path4.split(".");
3646
+ return setProp(dst, path4, value);
3647
3647
  };
3648
3648
  Object.defineProperty(util, "decorateRoot", {
3649
3649
  get: function() {
@@ -4190,12 +4190,12 @@ var require_object = __commonJS({
4190
4190
  */
4191
4191
  fullName: {
4192
4192
  get: function() {
4193
- var path3 = [this.name], ptr = this.parent;
4193
+ var path4 = [this.name], ptr = this.parent;
4194
4194
  while (ptr) {
4195
- path3.unshift(ptr.name);
4195
+ path4.unshift(ptr.name);
4196
4196
  ptr = ptr.parent;
4197
4197
  }
4198
- return path3.join(".");
4198
+ return path4.join(".");
4199
4199
  }
4200
4200
  }
4201
4201
  });
@@ -8178,16 +8178,16 @@ var require_util2 = __commonJS({
8178
8178
  Object.defineProperty(exports2, "__esModule", { value: true });
8179
8179
  exports2.addCommonProtos = exports2.loadProtosWithOptionsSync = exports2.loadProtosWithOptions = void 0;
8180
8180
  var fs = require("fs");
8181
- var path3 = require("path");
8181
+ var path4 = require("path");
8182
8182
  var Protobuf = require_protobufjs();
8183
8183
  function addIncludePathResolver(root, includePaths) {
8184
8184
  const originalResolvePath = root.resolvePath;
8185
8185
  root.resolvePath = (origin, target) => {
8186
- if (path3.isAbsolute(target)) {
8186
+ if (path4.isAbsolute(target)) {
8187
8187
  return target;
8188
8188
  }
8189
8189
  for (const directory of includePaths) {
8190
- const fullPath = path3.join(directory, target);
8190
+ const fullPath = path4.join(directory, target);
8191
8191
  try {
8192
8192
  fs.accessSync(fullPath, fs.constants.R_OK);
8193
8193
  return fullPath;
@@ -9487,24 +9487,46 @@ __export(src_exports, {
9487
9487
  ActivityBuffer: () => ActivityBuffer,
9488
9488
  ActivityBufferSync: () => ActivityBufferSync,
9489
9489
  ActivityClient: () => ActivityClient,
9490
+ AgentState: () => AgentState,
9491
+ AgentStateMachine: () => AgentStateMachine,
9492
+ ArtifactType: () => ArtifactType,
9490
9493
  BaseClient: () => BaseClient,
9494
+ BordaCountAggregator: () => BordaCountAggregator,
9491
9495
  CT_AGENT_REPORT_V1: () => CT_AGENT_REPORT_V1,
9492
9496
  CT_SCHEDULER_COMMAND_V1: () => CT_SCHEDULER_COMMAND_V1,
9497
+ ConfidenceWeightedAggregator: () => ConfidenceWeightedAggregator,
9493
9498
  ConnectorClient: () => ConnectorClient,
9499
+ DEFAULT_ESCALATION_POLICY: () => DEFAULT_ESCALATION_POLICY,
9500
+ DEFAULT_EXECUTION_POLICY: () => DEFAULT_EXECUTION_POLICY,
9501
+ DEFAULT_NEGOTIATION_POLICY: () => DEFAULT_NEGOTIATION_POLICY,
9502
+ DecisionOutcome: () => DecisionOutcome,
9494
9503
  DefaultWorktreePolicy: () => DefaultWorktreePolicy,
9495
9504
  ErrorCode: () => ErrorCode,
9496
9505
  ErrorCodeMapper: () => ErrorCodeMapper,
9497
9506
  FileBackend: () => FileBackend,
9498
9507
  HITLClient: () => HITLClient,
9508
+ HandoffClient: () => HandoffClient,
9509
+ HandoffStatus: () => HandoffStatus,
9510
+ HandoffTimeoutError: () => HandoffTimeoutError,
9511
+ HandoffValidationError: () => HandoffValidationError,
9512
+ HitlMode: () => HitlMode,
9513
+ InMemoryPolicyStore: () => InMemoryPolicyStore,
9499
9514
  InterceptorChain: () => InterceptorChain,
9500
9515
  JSONFilePersistence: () => JSONFilePersistence,
9516
+ JsonFilePolicyStore: () => JsonFilePolicyStore,
9501
9517
  KeyringBackend: () => KeyringBackend,
9502
9518
  LoggingClient: () => LoggingClient,
9519
+ MajorityVoteAggregator: () => MajorityVoteAggregator,
9503
9520
  MaxEntriesStrategy: () => MaxEntriesStrategy,
9504
9521
  MessageProcessor: () => MessageProcessor,
9505
9522
  MessageType: () => MessageType,
9506
9523
  NegotiationClient: () => NegotiationClient,
9524
+ NegotiationRoomClient: () => NegotiationRoomClient,
9525
+ NegotiationTimeoutError: () => NegotiationTimeoutError,
9526
+ NegotiationValidationError: () => NegotiationValidationError,
9527
+ NodeStatus: () => NodeStatus,
9507
9528
  PersistentWorktreeState: () => PersistentWorktreeState,
9529
+ PolicyStoreError: () => PolicyStoreError,
9508
9530
  ReasoningClient: () => ReasoningClient,
9509
9531
  RegistryClient: () => RegistryClient,
9510
9532
  Resolver: () => Resolver,
@@ -9522,9 +9544,18 @@ __export(src_exports, {
9522
9544
  SecretValidationError: () => SecretValidationError,
9523
9545
  SecretValue: () => SecretValue,
9524
9546
  Secrets: () => Secrets,
9547
+ SimpleAverageAggregator: () => SimpleAverageAggregator,
9548
+ StateTransitionError: () => StateTransitionError,
9525
9549
  Sw4rmError: () => Sw4rmError,
9526
9550
  ToolClient: () => ToolClient,
9551
+ TriggerType: () => TriggerType,
9552
+ VotingAnalyzer: () => VotingAnalyzer,
9553
+ WorkflowClient: () => WorkflowClient,
9554
+ WorkflowCycleError: () => WorkflowCycleError,
9555
+ WorkflowStatus: () => WorkflowStatus,
9556
+ WorkflowValidationError: () => WorkflowValidationError,
9527
9557
  WorktreeClient: () => WorktreeClient,
9558
+ aggregateVotes: () => aggregateVotes,
9528
9559
  buildAckEnvelope: () => buildAckEnvelope,
9529
9560
  buildEnvelope: () => buildEnvelope,
9530
9561
  computeIdempotencyToken: () => computeIdempotencyToken,
@@ -9533,6 +9564,8 @@ __export(src_exports, {
9533
9564
  decodeBase64: () => decodeBase64,
9534
9565
  durationToMs: () => durationToMs,
9535
9566
  encodeSchedulerCommandV1: () => encodeSchedulerCommandV1,
9567
+ getValidTransitions: () => getValidTransitions,
9568
+ isValidTransition: () => isValidTransition,
9536
9569
  loggingInterceptor: () => loggingInterceptor,
9537
9570
  mapGrpcStatusToErrorCode: () => mapGrpcStatusToErrorCode,
9538
9571
  msToDuration: () => msToDuration,
@@ -9672,7 +9705,7 @@ var InterceptorChain = class {
9672
9705
  };
9673
9706
  function timingInterceptor() {
9674
9707
  return {
9675
- onRequest(ctx) {
9708
+ onRequest(_ctx) {
9676
9709
  },
9677
9710
  onResponse(ctx, status) {
9678
9711
  if (typeof console !== "undefined" && console.debug) {
@@ -10342,6 +10375,961 @@ var RegistryClient = class extends BaseClient {
10342
10375
  }
10343
10376
  };
10344
10377
 
10378
+ // src/clients/negotiationRoom.ts
10379
+ var ArtifactType = /* @__PURE__ */ ((ArtifactType2) => {
10380
+ ArtifactType2[ArtifactType2["ARTIFACT_TYPE_UNSPECIFIED"] = 0] = "ARTIFACT_TYPE_UNSPECIFIED";
10381
+ ArtifactType2[ArtifactType2["REQUIREMENTS"] = 1] = "REQUIREMENTS";
10382
+ ArtifactType2[ArtifactType2["PLAN"] = 2] = "PLAN";
10383
+ ArtifactType2[ArtifactType2["CODE"] = 3] = "CODE";
10384
+ ArtifactType2[ArtifactType2["DEPLOYMENT"] = 4] = "DEPLOYMENT";
10385
+ return ArtifactType2;
10386
+ })(ArtifactType || {});
10387
+ var DecisionOutcome = /* @__PURE__ */ ((DecisionOutcome2) => {
10388
+ DecisionOutcome2[DecisionOutcome2["DECISION_OUTCOME_UNSPECIFIED"] = 0] = "DECISION_OUTCOME_UNSPECIFIED";
10389
+ DecisionOutcome2[DecisionOutcome2["APPROVED"] = 1] = "APPROVED";
10390
+ DecisionOutcome2[DecisionOutcome2["REVISION_REQUESTED"] = 2] = "REVISION_REQUESTED";
10391
+ DecisionOutcome2[DecisionOutcome2["ESCALATED_TO_HITL"] = 3] = "ESCALATED_TO_HITL";
10392
+ return DecisionOutcome2;
10393
+ })(DecisionOutcome || {});
10394
+ var NegotiationTimeoutError = class extends Error {
10395
+ constructor(message) {
10396
+ super(message);
10397
+ this.name = "NegotiationTimeoutError";
10398
+ }
10399
+ };
10400
+ var NegotiationValidationError = class extends Error {
10401
+ constructor(message) {
10402
+ super(message);
10403
+ this.name = "NegotiationValidationError";
10404
+ }
10405
+ };
10406
+ function validateVote(vote) {
10407
+ if (vote.score < 0 || vote.score > 10) {
10408
+ throw new NegotiationValidationError(
10409
+ `score must be in range [0, 10], got ${vote.score}`
10410
+ );
10411
+ }
10412
+ if (vote.confidence < 0 || vote.confidence > 1) {
10413
+ throw new NegotiationValidationError(
10414
+ `confidence must be in range [0, 1], got ${vote.confidence}`
10415
+ );
10416
+ }
10417
+ }
10418
+ var NegotiationRoomClient = class {
10419
+ proposals = /* @__PURE__ */ new Map();
10420
+ votes = /* @__PURE__ */ new Map();
10421
+ decisions = /* @__PURE__ */ new Map();
10422
+ /**
10423
+ * Submit an artifact proposal for multi-agent review.
10424
+ *
10425
+ * Stores the proposal and initializes empty vote tracking for the artifact.
10426
+ * This method is typically called by producer agents.
10427
+ *
10428
+ * @param proposal - The negotiation proposal containing artifact details
10429
+ * @returns The artifact_id of the submitted proposal
10430
+ * @throws NegotiationValidationError if a proposal with the same artifact_id already exists
10431
+ *
10432
+ * @example
10433
+ * ```typescript
10434
+ * const client = new NegotiationRoomClient();
10435
+ * const proposal: NegotiationProposal = {
10436
+ * artifactType: ArtifactType.CODE,
10437
+ * artifactId: "code-123",
10438
+ * producerId: "agent-producer",
10439
+ * artifact: new TextEncoder().encode("def hello(): pass"),
10440
+ * artifactContentType: "text/x-python",
10441
+ * requestedCritics: ["critic-1", "critic-2"],
10442
+ * negotiationRoomId: "room-1"
10443
+ * };
10444
+ * const artifactId = await client.submitProposal(proposal);
10445
+ * console.log(artifactId); // "code-123"
10446
+ * ```
10447
+ */
10448
+ async submitProposal(proposal) {
10449
+ const artifactId = proposal.artifactId;
10450
+ if (this.proposals.has(artifactId)) {
10451
+ throw new NegotiationValidationError(
10452
+ `Proposal with artifact_id '${artifactId}' already exists`
10453
+ );
10454
+ }
10455
+ const proposalWithTimestamp = {
10456
+ ...proposal,
10457
+ createdAt: proposal.createdAt || (/* @__PURE__ */ new Date()).toISOString()
10458
+ };
10459
+ this.proposals.set(artifactId, proposalWithTimestamp);
10460
+ this.votes.set(artifactId, []);
10461
+ return artifactId;
10462
+ }
10463
+ /**
10464
+ * Submit a critic's vote for an artifact.
10465
+ *
10466
+ * Adds the vote to the collection for the specified artifact.
10467
+ * This method is typically called by critic agents after evaluating
10468
+ * an artifact.
10469
+ *
10470
+ * @param vote - The negotiation vote containing the critic's evaluation
10471
+ * @throws NegotiationValidationError if no proposal exists for the vote's artifact_id
10472
+ * @throws NegotiationValidationError if the critic has already voted for this artifact
10473
+ * @throws NegotiationValidationError if score or confidence are out of range
10474
+ *
10475
+ * @example
10476
+ * ```typescript
10477
+ * const vote: NegotiationVote = {
10478
+ * artifactId: "code-123",
10479
+ * criticId: "critic-1",
10480
+ * score: 8.5,
10481
+ * confidence: 0.9,
10482
+ * passed: true,
10483
+ * strengths: ["Good structure"],
10484
+ * weaknesses: ["Needs tests"],
10485
+ * recommendations: ["Add unit tests"],
10486
+ * negotiationRoomId: "room-1"
10487
+ * };
10488
+ * await client.submitVote(vote);
10489
+ * ```
10490
+ */
10491
+ async submitVote(vote) {
10492
+ const artifactId = vote.artifactId;
10493
+ if (!this.proposals.has(artifactId)) {
10494
+ throw new NegotiationValidationError(
10495
+ `No proposal found for artifact_id '${artifactId}'`
10496
+ );
10497
+ }
10498
+ validateVote(vote);
10499
+ const existingVotes = this.votes.get(artifactId) || [];
10500
+ for (const existingVote of existingVotes) {
10501
+ if (existingVote.criticId === vote.criticId) {
10502
+ throw new NegotiationValidationError(
10503
+ `Critic '${vote.criticId}' has already voted for artifact '${artifactId}'`
10504
+ );
10505
+ }
10506
+ }
10507
+ const voteWithTimestamp = {
10508
+ ...vote,
10509
+ votedAt: vote.votedAt || (/* @__PURE__ */ new Date()).toISOString()
10510
+ };
10511
+ existingVotes.push(voteWithTimestamp);
10512
+ this.votes.set(artifactId, existingVotes);
10513
+ }
10514
+ /**
10515
+ * Retrieve all votes for a specific artifact.
10516
+ *
10517
+ * Returns all critic votes that have been submitted for the artifact.
10518
+ * This method is typically called by coordinator agents to aggregate
10519
+ * votes and make decisions.
10520
+ *
10521
+ * @param artifactId - The identifier of the artifact
10522
+ * @returns List of all votes for the artifact (empty array if no votes yet)
10523
+ * @throws NegotiationValidationError if no proposal exists for the artifact_id
10524
+ *
10525
+ * @example
10526
+ * ```typescript
10527
+ * const votes = await client.getVotes("code-123");
10528
+ * console.log(votes.length); // 1
10529
+ * ```
10530
+ */
10531
+ async getVotes(artifactId) {
10532
+ if (!this.proposals.has(artifactId)) {
10533
+ throw new NegotiationValidationError(
10534
+ `No proposal found for artifact_id '${artifactId}'`
10535
+ );
10536
+ }
10537
+ return this.votes.get(artifactId) || [];
10538
+ }
10539
+ /**
10540
+ * Retrieve the decision for a specific artifact if available.
10541
+ *
10542
+ * Returns the final decision if one has been made, or null if the
10543
+ * artifact is still under review.
10544
+ *
10545
+ * @param artifactId - The identifier of the artifact
10546
+ * @returns The negotiation decision if available, null otherwise
10547
+ * @throws NegotiationValidationError if no proposal exists for the artifact_id
10548
+ *
10549
+ * @example
10550
+ * ```typescript
10551
+ * const decision = await client.getDecision("code-123");
10552
+ * if (decision === null) {
10553
+ * console.log("Decision pending");
10554
+ * }
10555
+ * ```
10556
+ */
10557
+ async getDecision(artifactId) {
10558
+ if (!this.proposals.has(artifactId)) {
10559
+ throw new NegotiationValidationError(
10560
+ `No proposal found for artifact_id '${artifactId}'`
10561
+ );
10562
+ }
10563
+ return this.decisions.get(artifactId) || null;
10564
+ }
10565
+ /**
10566
+ * Store a decision for an artifact.
10567
+ *
10568
+ * This is an internal method used by coordinators to record the
10569
+ * final decision after evaluating votes. Once a decision is stored,
10570
+ * it becomes available via getDecision() and waitForDecision().
10571
+ *
10572
+ * @param decision - The negotiation decision to store
10573
+ * @throws NegotiationValidationError if no proposal exists for the decision's artifact_id
10574
+ * @throws NegotiationValidationError if a decision already exists for this artifact
10575
+ *
10576
+ * @example
10577
+ * ```typescript
10578
+ * const votes = await client.getVotes("code-123");
10579
+ * const aggregated = aggregateVotes(votes);
10580
+ * const decision: NegotiationDecision = {
10581
+ * artifactId: "code-123",
10582
+ * outcome: DecisionOutcome.APPROVED,
10583
+ * votes: votes,
10584
+ * aggregatedScore: aggregated,
10585
+ * policyVersion: "1.0",
10586
+ * reason: "Met all criteria",
10587
+ * negotiationRoomId: "room-1"
10588
+ * };
10589
+ * await client.storeDecision(decision);
10590
+ * ```
10591
+ */
10592
+ async storeDecision(decision) {
10593
+ const artifactId = decision.artifactId;
10594
+ if (!this.proposals.has(artifactId)) {
10595
+ throw new NegotiationValidationError(
10596
+ `No proposal found for artifact_id '${artifactId}'`
10597
+ );
10598
+ }
10599
+ if (this.decisions.has(artifactId)) {
10600
+ throw new NegotiationValidationError(
10601
+ `Decision already exists for artifact_id '${artifactId}'`
10602
+ );
10603
+ }
10604
+ const decisionWithTimestamp = {
10605
+ ...decision,
10606
+ decidedAt: decision.decidedAt || (/* @__PURE__ */ new Date()).toISOString()
10607
+ };
10608
+ this.decisions.set(artifactId, decisionWithTimestamp);
10609
+ }
10610
+ /**
10611
+ * Wait for a decision to be made on an artifact.
10612
+ *
10613
+ * Polls for a decision until one is available or the timeout is reached.
10614
+ * This method is useful for producer agents waiting for the outcome
10615
+ * of their artifact review.
10616
+ *
10617
+ * @param artifactId - The identifier of the artifact
10618
+ * @param timeoutMs - Maximum time to wait in milliseconds (default: 30000)
10619
+ * @param pollIntervalMs - Time between polling attempts in milliseconds (default: 100)
10620
+ * @returns The negotiation decision once available
10621
+ * @throws NegotiationValidationError if no proposal exists for the artifact_id
10622
+ * @throws NegotiationTimeoutError if no decision is made within the timeout period
10623
+ *
10624
+ * @example
10625
+ * ```typescript
10626
+ * // In a separate thread/process, a coordinator makes a decision
10627
+ * const decision = await client.waitForDecision("code-123", 10000);
10628
+ * console.log(decision.outcome); // DecisionOutcome.APPROVED
10629
+ * ```
10630
+ */
10631
+ async waitForDecision(artifactId, timeoutMs = 3e4, pollIntervalMs = 100) {
10632
+ if (!this.proposals.has(artifactId)) {
10633
+ throw new NegotiationValidationError(
10634
+ `No proposal found for artifact_id '${artifactId}'`
10635
+ );
10636
+ }
10637
+ const startTime = Date.now();
10638
+ while (Date.now() - startTime < timeoutMs) {
10639
+ const decision = await this.getDecision(artifactId);
10640
+ if (decision !== null) {
10641
+ return decision;
10642
+ }
10643
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
10644
+ }
10645
+ throw new NegotiationTimeoutError(
10646
+ `No decision made for artifact '${artifactId}' within ${timeoutMs} milliseconds`
10647
+ );
10648
+ }
10649
+ /**
10650
+ * Retrieve the original proposal for an artifact.
10651
+ *
10652
+ * Useful for critics that need to review the original artifact
10653
+ * before submitting a vote.
10654
+ *
10655
+ * @param artifactId - The identifier of the artifact
10656
+ * @returns The negotiation proposal if it exists, null otherwise
10657
+ *
10658
+ * @example
10659
+ * ```typescript
10660
+ * const proposal = await client.getProposal("code-123");
10661
+ * console.log(proposal?.artifactType); // ArtifactType.CODE
10662
+ * ```
10663
+ */
10664
+ async getProposal(artifactId) {
10665
+ return this.proposals.get(artifactId) || null;
10666
+ }
10667
+ /**
10668
+ * List all proposals, optionally filtered by negotiation room.
10669
+ *
10670
+ * @param negotiationRoomId - If provided, only return proposals for this room
10671
+ * @returns List of proposals matching the filter criteria
10672
+ *
10673
+ * @example
10674
+ * ```typescript
10675
+ * const proposals = await client.listProposals("room-1");
10676
+ * console.log(proposals.length); // 1
10677
+ * ```
10678
+ */
10679
+ async listProposals(negotiationRoomId) {
10680
+ const allProposals = Array.from(this.proposals.values());
10681
+ if (negotiationRoomId === void 0) {
10682
+ return allProposals;
10683
+ }
10684
+ return allProposals.filter(
10685
+ (p) => p.negotiationRoomId === negotiationRoomId
10686
+ );
10687
+ }
10688
+ };
10689
+ function aggregateVotes(votes) {
10690
+ if (votes.length === 0) {
10691
+ throw new NegotiationValidationError(
10692
+ "Cannot aggregate empty list of votes"
10693
+ );
10694
+ }
10695
+ const scores = votes.map((v) => v.score);
10696
+ const confidences = votes.map((v) => v.confidence);
10697
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
10698
+ const minScore = Math.min(...scores);
10699
+ const maxScore = Math.max(...scores);
10700
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
10701
+ const stdDev = Math.sqrt(variance);
10702
+ const totalConfidence = confidences.reduce((a, b) => a + b, 0);
10703
+ let weightedMean;
10704
+ if (totalConfidence > 0) {
10705
+ weightedMean = scores.reduce((sum, s, i) => sum + s * confidences[i], 0) / totalConfidence;
10706
+ } else {
10707
+ weightedMean = mean;
10708
+ }
10709
+ return {
10710
+ mean,
10711
+ minScore,
10712
+ maxScore,
10713
+ stdDev,
10714
+ weightedMean,
10715
+ voteCount: votes.length
10716
+ };
10717
+ }
10718
+
10719
+ // src/clients/handoff.ts
10720
+ var HandoffStatus = /* @__PURE__ */ ((HandoffStatus2) => {
10721
+ HandoffStatus2[HandoffStatus2["HANDOFF_STATUS_UNSPECIFIED"] = 0] = "HANDOFF_STATUS_UNSPECIFIED";
10722
+ HandoffStatus2[HandoffStatus2["PENDING"] = 1] = "PENDING";
10723
+ HandoffStatus2[HandoffStatus2["ACCEPTED"] = 2] = "ACCEPTED";
10724
+ HandoffStatus2[HandoffStatus2["REJECTED"] = 3] = "REJECTED";
10725
+ HandoffStatus2[HandoffStatus2["COMPLETED"] = 4] = "COMPLETED";
10726
+ HandoffStatus2[HandoffStatus2["EXPIRED"] = 5] = "EXPIRED";
10727
+ return HandoffStatus2;
10728
+ })(HandoffStatus || {});
10729
+ var HandoffValidationError = class extends Error {
10730
+ constructor(message) {
10731
+ super(message);
10732
+ this.name = "HandoffValidationError";
10733
+ }
10734
+ };
10735
+ var HandoffTimeoutError = class extends Error {
10736
+ constructor(message) {
10737
+ super(message);
10738
+ this.name = "HandoffTimeoutError";
10739
+ }
10740
+ };
10741
+ var HandoffClient = class {
10742
+ requests = /* @__PURE__ */ new Map();
10743
+ responses = /* @__PURE__ */ new Map();
10744
+ pendingByAgent = /* @__PURE__ */ new Map();
10745
+ /**
10746
+ * Request a handoff to another agent.
10747
+ *
10748
+ * Initiates a handoff request that the target agent can accept or reject.
10749
+ * The request is stored and made available to the target agent via
10750
+ * getPendingHandoffs().
10751
+ *
10752
+ * @param request - The handoff request containing context and requirements
10753
+ * @returns The response once the handoff is accepted, rejected, or times out
10754
+ * @throws HandoffValidationError if a request with the same ID already exists
10755
+ *
10756
+ * @example
10757
+ * ```typescript
10758
+ * const client = new HandoffClient();
10759
+ * const request: HandoffRequest = {
10760
+ * requestId: "handoff-123",
10761
+ * fromAgent: "agent-a",
10762
+ * toAgent: "agent-b",
10763
+ * reason: "Capability mismatch",
10764
+ * contextSnapshot: new TextEncoder().encode('{"state": "in_progress"}'),
10765
+ * capabilitiesRequired: ["code_review"],
10766
+ * priority: 5
10767
+ * };
10768
+ * const response = await client.requestHandoff(request);
10769
+ * ```
10770
+ */
10771
+ async requestHandoff(request) {
10772
+ if (this.requests.has(request.requestId)) {
10773
+ throw new HandoffValidationError(
10774
+ `Handoff request with ID '${request.requestId}' already exists`
10775
+ );
10776
+ }
10777
+ const requestWithTimestamp = {
10778
+ ...request,
10779
+ createdAt: request.createdAt || (/* @__PURE__ */ new Date()).toISOString()
10780
+ };
10781
+ this.requests.set(request.requestId, requestWithTimestamp);
10782
+ if (request.toAgent) {
10783
+ if (!this.pendingByAgent.has(request.toAgent)) {
10784
+ this.pendingByAgent.set(request.toAgent, /* @__PURE__ */ new Set());
10785
+ }
10786
+ this.pendingByAgent.get(request.toAgent).add(request.requestId);
10787
+ }
10788
+ const timeoutMs = request.timeoutMs || 3e4;
10789
+ const startTime = Date.now();
10790
+ const pollIntervalMs = 100;
10791
+ while (Date.now() - startTime < timeoutMs) {
10792
+ const response = this.responses.get(request.requestId);
10793
+ if (response) {
10794
+ return response;
10795
+ }
10796
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
10797
+ }
10798
+ const timeoutResponse = {
10799
+ requestId: request.requestId,
10800
+ accepted: false,
10801
+ rejectionReason: `Handoff request timed out after ${timeoutMs}ms`
10802
+ };
10803
+ this.responses.set(request.requestId, timeoutResponse);
10804
+ if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
10805
+ this.pendingByAgent.get(request.toAgent).delete(request.requestId);
10806
+ }
10807
+ return timeoutResponse;
10808
+ }
10809
+ /**
10810
+ * Accept a pending handoff request.
10811
+ *
10812
+ * Called by the target agent to accept a handoff. After acceptance,
10813
+ * the agent should process the context snapshot and continue the work.
10814
+ *
10815
+ * @param handoffId - The ID of the handoff request to accept
10816
+ * @throws HandoffValidationError if no request exists with the given ID
10817
+ * @throws HandoffValidationError if the request has already been responded to
10818
+ *
10819
+ * @example
10820
+ * ```typescript
10821
+ * // Get pending handoffs for this agent
10822
+ * const pending = await client.getPendingHandoffs("agent-b");
10823
+ * if (pending.length > 0) {
10824
+ * await client.acceptHandoff(pending[0].requestId);
10825
+ * }
10826
+ * ```
10827
+ */
10828
+ async acceptHandoff(handoffId) {
10829
+ const request = this.requests.get(handoffId);
10830
+ if (!request) {
10831
+ throw new HandoffValidationError(
10832
+ `No handoff request found with ID '${handoffId}'`
10833
+ );
10834
+ }
10835
+ if (this.responses.has(handoffId)) {
10836
+ throw new HandoffValidationError(
10837
+ `Handoff request '${handoffId}' has already been responded to`
10838
+ );
10839
+ }
10840
+ const response = {
10841
+ requestId: handoffId,
10842
+ accepted: true,
10843
+ acceptingAgent: request.toAgent
10844
+ };
10845
+ this.responses.set(handoffId, response);
10846
+ if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
10847
+ this.pendingByAgent.get(request.toAgent).delete(handoffId);
10848
+ }
10849
+ }
10850
+ /**
10851
+ * Reject a pending handoff request.
10852
+ *
10853
+ * Called by the target agent to reject a handoff. A reason should be
10854
+ * provided to help the originating agent determine next steps.
10855
+ *
10856
+ * @param handoffId - The ID of the handoff request to reject
10857
+ * @param reason - Human-readable reason for the rejection
10858
+ * @throws HandoffValidationError if no request exists with the given ID
10859
+ * @throws HandoffValidationError if the request has already been responded to
10860
+ *
10861
+ * @example
10862
+ * ```typescript
10863
+ * await client.rejectHandoff("handoff-123", "Agent at capacity");
10864
+ * ```
10865
+ */
10866
+ async rejectHandoff(handoffId, reason) {
10867
+ const request = this.requests.get(handoffId);
10868
+ if (!request) {
10869
+ throw new HandoffValidationError(
10870
+ `No handoff request found with ID '${handoffId}'`
10871
+ );
10872
+ }
10873
+ if (this.responses.has(handoffId)) {
10874
+ throw new HandoffValidationError(
10875
+ `Handoff request '${handoffId}' has already been responded to`
10876
+ );
10877
+ }
10878
+ const response = {
10879
+ requestId: handoffId,
10880
+ accepted: false,
10881
+ rejectionReason: reason
10882
+ };
10883
+ this.responses.set(handoffId, response);
10884
+ if (request.toAgent && this.pendingByAgent.has(request.toAgent)) {
10885
+ this.pendingByAgent.get(request.toAgent).delete(handoffId);
10886
+ }
10887
+ }
10888
+ /**
10889
+ * Get all pending handoff requests for an agent.
10890
+ *
10891
+ * Returns handoff requests that have been addressed to the specified
10892
+ * agent and have not yet been accepted or rejected.
10893
+ *
10894
+ * @param agentId - The ID of the agent to get pending handoffs for
10895
+ * @returns List of pending handoff requests for the agent
10896
+ *
10897
+ * @example
10898
+ * ```typescript
10899
+ * const pending = await client.getPendingHandoffs("agent-b");
10900
+ * console.log(`${pending.length} pending handoffs`);
10901
+ * for (const request of pending) {
10902
+ * console.log(`From ${request.fromAgent}: ${request.reason}`);
10903
+ * }
10904
+ * ```
10905
+ */
10906
+ async getPendingHandoffs(agentId) {
10907
+ const pendingIds = this.pendingByAgent.get(agentId);
10908
+ if (!pendingIds) {
10909
+ return [];
10910
+ }
10911
+ const pending = [];
10912
+ for (const requestId of pendingIds) {
10913
+ const request = this.requests.get(requestId);
10914
+ if (request && !this.responses.has(requestId)) {
10915
+ pending.push(request);
10916
+ }
10917
+ }
10918
+ return pending;
10919
+ }
10920
+ /**
10921
+ * Get the response for a handoff request.
10922
+ *
10923
+ * Returns the response if the handoff has been accepted, rejected, or
10924
+ * timed out. Returns null if the handoff is still pending.
10925
+ *
10926
+ * @param handoffId - The ID of the handoff request
10927
+ * @returns The handoff response if available, null otherwise
10928
+ */
10929
+ async getHandoffResponse(handoffId) {
10930
+ return this.responses.get(handoffId) || null;
10931
+ }
10932
+ /**
10933
+ * Get the original handoff request.
10934
+ *
10935
+ * @param handoffId - The ID of the handoff request
10936
+ * @returns The handoff request if it exists, null otherwise
10937
+ */
10938
+ async getHandoffRequest(handoffId) {
10939
+ return this.requests.get(handoffId) || null;
10940
+ }
10941
+ };
10942
+
10943
+ // src/clients/workflow.ts
10944
+ var NodeStatus = /* @__PURE__ */ ((NodeStatus2) => {
10945
+ NodeStatus2[NodeStatus2["NODE_STATUS_UNSPECIFIED"] = 0] = "NODE_STATUS_UNSPECIFIED";
10946
+ NodeStatus2[NodeStatus2["PENDING"] = 1] = "PENDING";
10947
+ NodeStatus2[NodeStatus2["READY"] = 2] = "READY";
10948
+ NodeStatus2[NodeStatus2["RUNNING"] = 3] = "RUNNING";
10949
+ NodeStatus2[NodeStatus2["COMPLETED"] = 4] = "COMPLETED";
10950
+ NodeStatus2[NodeStatus2["FAILED"] = 5] = "FAILED";
10951
+ NodeStatus2[NodeStatus2["SKIPPED"] = 6] = "SKIPPED";
10952
+ return NodeStatus2;
10953
+ })(NodeStatus || {});
10954
+ var TriggerType = /* @__PURE__ */ ((TriggerType2) => {
10955
+ TriggerType2[TriggerType2["TRIGGER_TYPE_UNSPECIFIED"] = 0] = "TRIGGER_TYPE_UNSPECIFIED";
10956
+ TriggerType2[TriggerType2["EVENT"] = 1] = "EVENT";
10957
+ TriggerType2[TriggerType2["SCHEDULE"] = 2] = "SCHEDULE";
10958
+ TriggerType2[TriggerType2["MANUAL"] = 3] = "MANUAL";
10959
+ TriggerType2[TriggerType2["DEPENDENCY"] = 4] = "DEPENDENCY";
10960
+ return TriggerType2;
10961
+ })(TriggerType || {});
10962
+ var WorkflowStatus = /* @__PURE__ */ ((WorkflowStatus2) => {
10963
+ WorkflowStatus2[WorkflowStatus2["WORKFLOW_STATUS_UNSPECIFIED"] = 0] = "WORKFLOW_STATUS_UNSPECIFIED";
10964
+ WorkflowStatus2[WorkflowStatus2["CREATED"] = 1] = "CREATED";
10965
+ WorkflowStatus2[WorkflowStatus2["RUNNING"] = 2] = "RUNNING";
10966
+ WorkflowStatus2[WorkflowStatus2["COMPLETED"] = 3] = "COMPLETED";
10967
+ WorkflowStatus2[WorkflowStatus2["FAILED"] = 4] = "FAILED";
10968
+ WorkflowStatus2[WorkflowStatus2["CANCELLED"] = 5] = "CANCELLED";
10969
+ WorkflowStatus2[WorkflowStatus2["PAUSED"] = 6] = "PAUSED";
10970
+ return WorkflowStatus2;
10971
+ })(WorkflowStatus || {});
10972
+ var WorkflowValidationError = class extends Error {
10973
+ constructor(message) {
10974
+ super(message);
10975
+ this.name = "WorkflowValidationError";
10976
+ }
10977
+ };
10978
+ var WorkflowCycleError = class extends Error {
10979
+ constructor(message) {
10980
+ super(message);
10981
+ this.name = "WorkflowCycleError";
10982
+ }
10983
+ };
10984
+ function validateWorkflowDefinition(definition) {
10985
+ const nodeIds = new Set(Object.keys(definition.nodes));
10986
+ for (const [nodeId, node] of Object.entries(definition.nodes)) {
10987
+ for (const dep of node.dependencies) {
10988
+ if (!nodeIds.has(dep)) {
10989
+ throw new WorkflowValidationError(
10990
+ `Node '${nodeId}' has dependency '${dep}' which does not exist`
10991
+ );
10992
+ }
10993
+ if (dep === nodeId) {
10994
+ throw new WorkflowCycleError(
10995
+ `Node '${nodeId}' has a self-dependency`
10996
+ );
10997
+ }
10998
+ }
10999
+ }
11000
+ const visited = /* @__PURE__ */ new Set();
11001
+ const recursionStack = /* @__PURE__ */ new Set();
11002
+ function hasCycle(nodeId) {
11003
+ if (recursionStack.has(nodeId)) {
11004
+ return true;
11005
+ }
11006
+ if (visited.has(nodeId)) {
11007
+ return false;
11008
+ }
11009
+ visited.add(nodeId);
11010
+ recursionStack.add(nodeId);
11011
+ const node = definition.nodes[nodeId];
11012
+ for (const dep of node.dependencies) {
11013
+ if (hasCycle(dep)) {
11014
+ return true;
11015
+ }
11016
+ }
11017
+ recursionStack.delete(nodeId);
11018
+ return false;
11019
+ }
11020
+ for (const nodeId of nodeIds) {
11021
+ if (hasCycle(nodeId)) {
11022
+ throw new WorkflowCycleError(
11023
+ `Workflow contains a cycle involving node '${nodeId}'`
11024
+ );
11025
+ }
11026
+ }
11027
+ }
11028
+ function generateInstanceId() {
11029
+ return `wf-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
11030
+ }
11031
+ var WorkflowClient = class {
11032
+ definitions = /* @__PURE__ */ new Map();
11033
+ instances = /* @__PURE__ */ new Map();
11034
+ instancesByWorkflow = /* @__PURE__ */ new Map();
11035
+ /**
11036
+ * Create a new workflow from a definition.
11037
+ *
11038
+ * Validates the workflow definition and stores it for later execution.
11039
+ *
11040
+ * @param definition - The workflow definition to create
11041
+ * @returns The workflow_id of the created workflow
11042
+ * @throws WorkflowValidationError if the definition is invalid
11043
+ * @throws WorkflowCycleError if the workflow contains a cycle
11044
+ *
11045
+ * @example
11046
+ * ```typescript
11047
+ * const client = new WorkflowClient();
11048
+ * const definition: WorkflowDefinition = {
11049
+ * workflowId: "review-workflow",
11050
+ * nodes: {
11051
+ * "produce": {
11052
+ * nodeId: "produce",
11053
+ * agentId: "producer-agent",
11054
+ * dependencies: [],
11055
+ * triggerType: TriggerType.MANUAL,
11056
+ * inputMapping: {},
11057
+ * outputMapping: { "artifact": "produced_artifact" },
11058
+ * metadata: {}
11059
+ * },
11060
+ * "review": {
11061
+ * nodeId: "review",
11062
+ * agentId: "critic-agent",
11063
+ * dependencies: ["produce"],
11064
+ * triggerType: TriggerType.DEPENDENCY,
11065
+ * inputMapping: { "artifact": "produced_artifact" },
11066
+ * outputMapping: { "result": "review_result" },
11067
+ * metadata: {}
11068
+ * }
11069
+ * },
11070
+ * metadata: {}
11071
+ * };
11072
+ * const workflowId = await client.createWorkflow(definition);
11073
+ * ```
11074
+ */
11075
+ async createWorkflow(definition) {
11076
+ validateWorkflowDefinition(definition);
11077
+ if (this.definitions.has(definition.workflowId)) {
11078
+ throw new WorkflowValidationError(
11079
+ `Workflow with ID '${definition.workflowId}' already exists`
11080
+ );
11081
+ }
11082
+ const definitionWithTimestamp = {
11083
+ ...definition,
11084
+ createdAt: definition.createdAt || (/* @__PURE__ */ new Date()).toISOString()
11085
+ };
11086
+ this.definitions.set(definition.workflowId, definitionWithTimestamp);
11087
+ this.instancesByWorkflow.set(definition.workflowId, /* @__PURE__ */ new Set());
11088
+ return definition.workflowId;
11089
+ }
11090
+ /**
11091
+ * Start a new instance of a workflow.
11092
+ *
11093
+ * Creates a new workflow instance and initializes all nodes to their
11094
+ * starting states based on dependencies.
11095
+ *
11096
+ * @param workflowId - The ID of the workflow to start
11097
+ * @param initialData - Optional initial workflow data (JSON string)
11098
+ * @param metadata - Optional runtime metadata
11099
+ * @returns The created workflow instance
11100
+ * @throws WorkflowValidationError if the workflow does not exist
11101
+ *
11102
+ * @example
11103
+ * ```typescript
11104
+ * const instance = await client.startWorkflow("review-workflow");
11105
+ * console.log(instance.status); // WorkflowStatus.RUNNING
11106
+ * ```
11107
+ */
11108
+ async startWorkflow(workflowId, initialData, metadata) {
11109
+ const definition = this.definitions.get(workflowId);
11110
+ if (!definition) {
11111
+ throw new WorkflowValidationError(
11112
+ `Workflow with ID '${workflowId}' does not exist`
11113
+ );
11114
+ }
11115
+ const instanceId = generateInstanceId();
11116
+ const now = (/* @__PURE__ */ new Date()).toISOString();
11117
+ const nodeStates = {};
11118
+ for (const [nodeId, node] of Object.entries(definition.nodes)) {
11119
+ const status = node.dependencies.length === 0 ? 2 /* READY */ : 1 /* PENDING */;
11120
+ nodeStates[nodeId] = {
11121
+ nodeId,
11122
+ status
11123
+ };
11124
+ }
11125
+ const instance = {
11126
+ instanceId,
11127
+ workflowId,
11128
+ status: 2 /* RUNNING */,
11129
+ nodeStates,
11130
+ workflowData: initialData || "{}",
11131
+ startedAt: now,
11132
+ metadata: metadata || {}
11133
+ };
11134
+ this.instances.set(instanceId, instance);
11135
+ this.instancesByWorkflow.get(workflowId).add(instanceId);
11136
+ return instance;
11137
+ }
11138
+ /**
11139
+ * Get the current status of a workflow instance.
11140
+ *
11141
+ * @param instanceId - The ID of the workflow instance
11142
+ * @returns The workflow instance with current state
11143
+ * @throws WorkflowValidationError if the instance does not exist
11144
+ *
11145
+ * @example
11146
+ * ```typescript
11147
+ * const instance = await client.getWorkflowStatus("wf-123-abc");
11148
+ * console.log(instance.status);
11149
+ * for (const [nodeId, state] of Object.entries(instance.nodeStates)) {
11150
+ * console.log(`${nodeId}: ${NodeStatus[state.status]}`);
11151
+ * }
11152
+ * ```
11153
+ */
11154
+ async getWorkflowStatus(instanceId) {
11155
+ const instance = this.instances.get(instanceId);
11156
+ if (!instance) {
11157
+ throw new WorkflowValidationError(
11158
+ `Workflow instance with ID '${instanceId}' does not exist`
11159
+ );
11160
+ }
11161
+ return instance;
11162
+ }
11163
+ /**
11164
+ * Cancel a running workflow instance.
11165
+ *
11166
+ * Marks the workflow as cancelled and stops any pending nodes.
11167
+ *
11168
+ * @param instanceId - The ID of the workflow instance to cancel
11169
+ * @throws WorkflowValidationError if the instance does not exist
11170
+ * @throws WorkflowValidationError if the workflow is not in a cancellable state
11171
+ *
11172
+ * @example
11173
+ * ```typescript
11174
+ * await client.cancelWorkflow("wf-123-abc");
11175
+ * const instance = await client.getWorkflowStatus("wf-123-abc");
11176
+ * console.log(instance.status); // WorkflowStatus.CANCELLED
11177
+ * ```
11178
+ */
11179
+ async cancelWorkflow(instanceId) {
11180
+ const instance = this.instances.get(instanceId);
11181
+ if (!instance) {
11182
+ throw new WorkflowValidationError(
11183
+ `Workflow instance with ID '${instanceId}' does not exist`
11184
+ );
11185
+ }
11186
+ if (instance.status === 3 /* COMPLETED */ || instance.status === 4 /* FAILED */ || instance.status === 5 /* CANCELLED */) {
11187
+ throw new WorkflowValidationError(
11188
+ `Workflow instance '${instanceId}' is already in terminal state '${WorkflowStatus[instance.status]}'`
11189
+ );
11190
+ }
11191
+ instance.status = 5 /* CANCELLED */;
11192
+ instance.completedAt = (/* @__PURE__ */ new Date()).toISOString();
11193
+ for (const nodeState of Object.values(instance.nodeStates)) {
11194
+ if (nodeState.status === 1 /* PENDING */ || nodeState.status === 2 /* READY */) {
11195
+ nodeState.status = 6 /* SKIPPED */;
11196
+ }
11197
+ }
11198
+ this.instances.set(instanceId, instance);
11199
+ }
11200
+ /**
11201
+ * Get the workflow definition.
11202
+ *
11203
+ * @param workflowId - The ID of the workflow
11204
+ * @returns The workflow definition if it exists, null otherwise
11205
+ */
11206
+ async getWorkflowDefinition(workflowId) {
11207
+ return this.definitions.get(workflowId) || null;
11208
+ }
11209
+ /**
11210
+ * List all instances of a workflow.
11211
+ *
11212
+ * @param workflowId - The ID of the workflow
11213
+ * @returns List of all instances for the workflow
11214
+ */
11215
+ async listWorkflowInstances(workflowId) {
11216
+ const instanceIds = this.instancesByWorkflow.get(workflowId);
11217
+ if (!instanceIds) {
11218
+ return [];
11219
+ }
11220
+ const instances = [];
11221
+ for (const instanceId of instanceIds) {
11222
+ const instance = this.instances.get(instanceId);
11223
+ if (instance) {
11224
+ instances.push(instance);
11225
+ }
11226
+ }
11227
+ return instances;
11228
+ }
11229
+ /**
11230
+ * Update the state of a node in a workflow instance.
11231
+ *
11232
+ * This is an internal method used by node executors to report progress.
11233
+ *
11234
+ * @param instanceId - The ID of the workflow instance
11235
+ * @param nodeId - The ID of the node to update
11236
+ * @param status - The new status of the node
11237
+ * @param output - Optional output data from the node
11238
+ * @param error - Optional error message if the node failed
11239
+ * @throws WorkflowValidationError if the instance or node does not exist
11240
+ */
11241
+ async updateNodeState(instanceId, nodeId, status, output, error) {
11242
+ const instance = this.instances.get(instanceId);
11243
+ if (!instance) {
11244
+ throw new WorkflowValidationError(
11245
+ `Workflow instance with ID '${instanceId}' does not exist`
11246
+ );
11247
+ }
11248
+ const nodeState = instance.nodeStates[nodeId];
11249
+ if (!nodeState) {
11250
+ throw new WorkflowValidationError(
11251
+ `Node '${nodeId}' does not exist in workflow instance '${instanceId}'`
11252
+ );
11253
+ }
11254
+ const now = (/* @__PURE__ */ new Date()).toISOString();
11255
+ nodeState.status = status;
11256
+ if (status === 3 /* RUNNING */ && !nodeState.startedAt) {
11257
+ nodeState.startedAt = now;
11258
+ }
11259
+ if (status === 4 /* COMPLETED */ || status === 5 /* FAILED */ || status === 6 /* SKIPPED */) {
11260
+ nodeState.completedAt = now;
11261
+ }
11262
+ if (output !== void 0) {
11263
+ nodeState.output = output;
11264
+ }
11265
+ if (error !== void 0) {
11266
+ nodeState.error = error;
11267
+ }
11268
+ if (status === 4 /* COMPLETED */) {
11269
+ const definition = this.definitions.get(instance.workflowId);
11270
+ if (definition) {
11271
+ this.updateDependentNodes(instance, definition, nodeId);
11272
+ }
11273
+ }
11274
+ this.checkWorkflowCompletion(instance);
11275
+ this.instances.set(instanceId, instance);
11276
+ }
11277
+ /**
11278
+ * Update the status of nodes that depend on a completed node.
11279
+ */
11280
+ updateDependentNodes(instance, definition, completedNodeId) {
11281
+ for (const [nodeId, node] of Object.entries(definition.nodes)) {
11282
+ if (node.dependencies.includes(completedNodeId)) {
11283
+ const nodeState = instance.nodeStates[nodeId];
11284
+ if (nodeState.status === 1 /* PENDING */) {
11285
+ const allDepsComplete = node.dependencies.every((dep) => {
11286
+ const depState = instance.nodeStates[dep];
11287
+ return depState && depState.status === 4 /* COMPLETED */;
11288
+ });
11289
+ if (allDepsComplete) {
11290
+ nodeState.status = 2 /* READY */;
11291
+ }
11292
+ }
11293
+ }
11294
+ }
11295
+ }
11296
+ /**
11297
+ * Check if a workflow instance is complete and update its status.
11298
+ */
11299
+ checkWorkflowCompletion(instance) {
11300
+ const nodeStatuses = Object.values(instance.nodeStates).map((s) => s.status);
11301
+ if (nodeStatuses.some((s) => s === 5 /* FAILED */)) {
11302
+ instance.status = 4 /* FAILED */;
11303
+ instance.completedAt = (/* @__PURE__ */ new Date()).toISOString();
11304
+ return;
11305
+ }
11306
+ const allComplete = nodeStatuses.every(
11307
+ (s) => s === 4 /* COMPLETED */ || s === 6 /* SKIPPED */
11308
+ );
11309
+ if (allComplete) {
11310
+ instance.status = 3 /* COMPLETED */;
11311
+ instance.completedAt = (/* @__PURE__ */ new Date()).toISOString();
11312
+ }
11313
+ }
11314
+ /**
11315
+ * Update the shared workflow data.
11316
+ *
11317
+ * @param instanceId - The ID of the workflow instance
11318
+ * @param workflowData - The new workflow data (JSON string)
11319
+ * @throws WorkflowValidationError if the instance does not exist
11320
+ */
11321
+ async updateWorkflowData(instanceId, workflowData) {
11322
+ const instance = this.instances.get(instanceId);
11323
+ if (!instance) {
11324
+ throw new WorkflowValidationError(
11325
+ `Workflow instance with ID '${instanceId}' does not exist`
11326
+ );
11327
+ }
11328
+ instance.workflowData = workflowData;
11329
+ this.instances.set(instanceId, instance);
11330
+ }
11331
+ };
11332
+
10345
11333
  // src/internal/envelope.ts
10346
11334
  var import_node_crypto2 = __toESM(require("node:crypto"), 1);
10347
11335
  function nowTimestamp(date = /* @__PURE__ */ new Date()) {
@@ -10584,11 +11572,15 @@ async function sendMessageWithAck(router, inboundStream, envelope, ackLifecycle,
10584
11572
  }
10585
11573
  }
10586
11574
  };
10587
- return new Promise(async (resolve, reject) => {
10588
- let timeout;
11575
+ await router.sendMessage(envelope);
11576
+ return new Promise((resolve, reject) => {
11577
+ const timeout = setTimeout(() => {
11578
+ ackLifecycle.mark(envelope.message_id, 6 /* TIMED_OUT */, "received_timeout");
11579
+ cleanup();
11580
+ reject(new Error("ACK RECEIVED timeout exceeded"));
11581
+ }, receivedTimeoutMs);
10589
11582
  const cleanup = () => {
10590
- if (timeout)
10591
- clearTimeout(timeout);
11583
+ clearTimeout(timeout);
10592
11584
  inboundStream.removeListener("data", onData);
10593
11585
  inboundStream.removeListener("error", onErr);
10594
11586
  };
@@ -10598,27 +11590,13 @@ async function sendMessageWithAck(router, inboundStream, envelope, ackLifecycle,
10598
11590
  };
10599
11591
  inboundStream.on("data", onData);
10600
11592
  inboundStream.on("error", onErr);
10601
- try {
10602
- await router.sendMessage(envelope);
10603
- } catch (e) {
10604
- cleanup();
10605
- return reject(e);
10606
- }
10607
- timeout = setTimeout(() => {
10608
- ackLifecycle.mark(envelope.message_id, 6 /* TIMED_OUT */, "received_timeout");
10609
- cleanup();
10610
- reject(new Error("ACK RECEIVED timeout exceeded"));
10611
- }, receivedTimeoutMs);
10612
11593
  const checkInterval = setInterval(() => {
10613
11594
  const state = ackLifecycle.get(envelope.message_id);
10614
11595
  if (!state)
10615
11596
  return;
10616
11597
  if (state.stage === 1 /* RECEIVED */ || state.stage === 2 /* READ */ || state.stage === 3 /* FULFILLED */) {
10617
11598
  clearInterval(checkInterval);
10618
- if (timeout)
10619
- clearTimeout(timeout);
10620
- inboundStream.removeListener("data", onData);
10621
- inboundStream.removeListener("error", onErr);
11599
+ cleanup();
10622
11600
  resolve();
10623
11601
  }
10624
11602
  }, 25);
@@ -10765,6 +11743,1187 @@ var JSONFilePersistence = class {
10765
11743
  }
10766
11744
  };
10767
11745
 
11746
+ // src/runtime/voting.ts
11747
+ var SimpleAverageAggregator = class {
11748
+ /**
11749
+ * Aggregate votes using simple arithmetic mean.
11750
+ *
11751
+ * @param votes - List of critic votes to aggregate
11752
+ * @returns AggregatedScore with simple mean in both mean and weightedMean fields
11753
+ * @throws NegotiationValidationError if votes list is empty
11754
+ */
11755
+ aggregate(votes) {
11756
+ if (votes.length === 0) {
11757
+ throw new NegotiationValidationError(
11758
+ "Cannot aggregate empty list of votes"
11759
+ );
11760
+ }
11761
+ const scores = votes.map((v) => v.score);
11762
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
11763
+ const minScore = Math.min(...scores);
11764
+ const maxScore = Math.max(...scores);
11765
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
11766
+ const stdDev = Math.sqrt(variance);
11767
+ return {
11768
+ mean,
11769
+ minScore,
11770
+ maxScore,
11771
+ stdDev,
11772
+ weightedMean: mean,
11773
+ voteCount: votes.length
11774
+ };
11775
+ }
11776
+ };
11777
+ var ConfidenceWeightedAggregator = class {
11778
+ /**
11779
+ * Aggregate votes using confidence weighting.
11780
+ *
11781
+ * @param votes - List of critic votes to aggregate
11782
+ * @returns AggregatedScore with confidence-weighted mean
11783
+ * @throws NegotiationValidationError if votes list is empty
11784
+ */
11785
+ aggregate(votes) {
11786
+ if (votes.length === 0) {
11787
+ throw new NegotiationValidationError(
11788
+ "Cannot aggregate empty list of votes"
11789
+ );
11790
+ }
11791
+ const scores = votes.map((v) => v.score);
11792
+ const confidences = votes.map((v) => v.confidence);
11793
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
11794
+ const minScore = Math.min(...scores);
11795
+ const maxScore = Math.max(...scores);
11796
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
11797
+ const stdDev = Math.sqrt(variance);
11798
+ const totalConfidence = confidences.reduce((a, b) => a + b, 0);
11799
+ let weightedMean;
11800
+ if (totalConfidence > 0) {
11801
+ weightedMean = scores.reduce((sum, s, i) => sum + s * confidences[i], 0) / totalConfidence;
11802
+ } else {
11803
+ weightedMean = mean;
11804
+ }
11805
+ return {
11806
+ mean,
11807
+ minScore,
11808
+ maxScore,
11809
+ stdDev,
11810
+ weightedMean,
11811
+ voteCount: votes.length
11812
+ };
11813
+ }
11814
+ };
11815
+ var MajorityVoteAggregator = class {
11816
+ /**
11817
+ * Aggregate votes using majority voting.
11818
+ *
11819
+ * @param votes - List of critic votes to aggregate
11820
+ * @returns AggregatedScore with score based on majority outcome
11821
+ * @throws NegotiationValidationError if votes list is empty
11822
+ */
11823
+ aggregate(votes) {
11824
+ if (votes.length === 0) {
11825
+ throw new NegotiationValidationError(
11826
+ "Cannot aggregate empty list of votes"
11827
+ );
11828
+ }
11829
+ const scores = votes.map((v) => v.score);
11830
+ const passedCount = votes.filter((v) => v.passed).length;
11831
+ const failedCount = votes.length - passedCount;
11832
+ let majorityScore;
11833
+ if (passedCount === votes.length) {
11834
+ majorityScore = 10;
11835
+ } else if (failedCount === votes.length) {
11836
+ majorityScore = 0;
11837
+ } else if (passedCount > failedCount) {
11838
+ majorityScore = 7.5;
11839
+ } else if (failedCount > passedCount) {
11840
+ majorityScore = 2.5;
11841
+ } else {
11842
+ majorityScore = 5;
11843
+ }
11844
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
11845
+ const minScore = Math.min(...scores);
11846
+ const maxScore = Math.max(...scores);
11847
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
11848
+ const stdDev = Math.sqrt(variance);
11849
+ return {
11850
+ mean,
11851
+ minScore,
11852
+ maxScore,
11853
+ stdDev,
11854
+ weightedMean: majorityScore,
11855
+ voteCount: votes.length
11856
+ };
11857
+ }
11858
+ };
11859
+ var BordaCountAggregator = class {
11860
+ /**
11861
+ * Aggregate votes using Borda count.
11862
+ *
11863
+ * @param votes - List of critic votes to aggregate
11864
+ * @returns AggregatedScore with Borda count normalized score
11865
+ * @throws NegotiationValidationError if votes list is empty
11866
+ */
11867
+ aggregate(votes) {
11868
+ if (votes.length === 0) {
11869
+ throw new NegotiationValidationError(
11870
+ "Cannot aggregate empty list of votes"
11871
+ );
11872
+ }
11873
+ const scores = votes.map((v) => v.score);
11874
+ const n = votes.length;
11875
+ const mean = scores.reduce((a, b) => a + b, 0) / n;
11876
+ const minScore = Math.min(...scores);
11877
+ const maxScore = Math.max(...scores);
11878
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / n;
11879
+ const stdDev = Math.sqrt(variance);
11880
+ const indexedScores = scores.map((score, idx) => ({ score, idx }));
11881
+ indexedScores.sort((a, b) => b.score - a.score);
11882
+ let totalPoints = 0;
11883
+ for (let rank = 0; rank < indexedScores.length; rank++) {
11884
+ const points = n - rank;
11885
+ totalPoints += points;
11886
+ }
11887
+ const avgPoints = totalPoints / n;
11888
+ const bordaScore = avgPoints / n * 10;
11889
+ return {
11890
+ mean,
11891
+ minScore,
11892
+ maxScore,
11893
+ stdDev,
11894
+ weightedMean: bordaScore,
11895
+ voteCount: n
11896
+ };
11897
+ }
11898
+ };
11899
+ var VotingAnalyzer = class {
11900
+ strategy;
11901
+ /**
11902
+ * Initialize analyzer with a strategy.
11903
+ *
11904
+ * @param strategy - The aggregation strategy to use
11905
+ */
11906
+ constructor(strategy) {
11907
+ this.strategy = strategy;
11908
+ }
11909
+ /**
11910
+ * Aggregate votes using the configured strategy.
11911
+ *
11912
+ * @param votes - List of critic votes to aggregate
11913
+ * @returns AggregatedScore with aggregation results
11914
+ * @throws NegotiationValidationError if votes list is empty
11915
+ */
11916
+ aggregate(votes) {
11917
+ return this.strategy.aggregate(votes);
11918
+ }
11919
+ /**
11920
+ * Compute Shannon entropy of vote distribution.
11921
+ *
11922
+ * Entropy measures the uncertainty or disorder in the vote distribution.
11923
+ * Higher entropy indicates more disagreement/uncertainty, lower entropy
11924
+ * indicates more consensus.
11925
+ *
11926
+ * The score range [0, 10] is divided into bins, and entropy is computed
11927
+ * over the probability distribution of votes across bins.
11928
+ *
11929
+ * @param votes - List of critic votes
11930
+ * @returns Entropy value in bits (0 = perfect consensus, higher = more uncertainty)
11931
+ * @throws NegotiationValidationError if votes list is empty
11932
+ */
11933
+ computeEntropy(votes) {
11934
+ if (votes.length === 0) {
11935
+ throw new NegotiationValidationError(
11936
+ "Cannot compute entropy of empty vote list"
11937
+ );
11938
+ }
11939
+ const numBins = 5;
11940
+ const binWidth = 10 / numBins;
11941
+ const binCounts = new Array(numBins).fill(0);
11942
+ for (const vote of votes) {
11943
+ const binIdx = Math.min(Math.floor(vote.score / binWidth), numBins - 1);
11944
+ binCounts[binIdx]++;
11945
+ }
11946
+ const total = votes.length;
11947
+ let entropy = 0;
11948
+ for (const count of binCounts) {
11949
+ if (count > 0) {
11950
+ const probability = count / total;
11951
+ entropy -= probability * Math.log2(probability);
11952
+ }
11953
+ }
11954
+ return entropy;
11955
+ }
11956
+ /**
11957
+ * Detect if votes show strong consensus.
11958
+ *
11959
+ * Consensus is detected when:
11960
+ * 1. Standard deviation of scores is low (< 2.0)
11961
+ * 2. A large proportion of critics agree on pass/fail (>= threshold)
11962
+ *
11963
+ * @param votes - List of critic votes
11964
+ * @param threshold - Minimum proportion of agreement required (default 0.8 = 80%)
11965
+ * @returns True if consensus is detected, false otherwise
11966
+ * @throws NegotiationValidationError if votes list is empty or threshold not in [0, 1]
11967
+ */
11968
+ detectConsensus(votes, threshold = 0.8) {
11969
+ if (votes.length === 0) {
11970
+ throw new NegotiationValidationError(
11971
+ "Cannot detect consensus in empty vote list"
11972
+ );
11973
+ }
11974
+ if (threshold < 0 || threshold > 1) {
11975
+ throw new NegotiationValidationError(
11976
+ `Threshold must be in [0, 1], got ${threshold}`
11977
+ );
11978
+ }
11979
+ const scores = votes.map((v) => v.score);
11980
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
11981
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
11982
+ const stdDev = Math.sqrt(variance);
11983
+ if (stdDev >= 2) {
11984
+ return false;
11985
+ }
11986
+ const passedCount = votes.filter((v) => v.passed).length;
11987
+ const failedCount = votes.length - passedCount;
11988
+ const agreementRatio = Math.max(passedCount, failedCount) / votes.length;
11989
+ return agreementRatio >= threshold;
11990
+ }
11991
+ /**
11992
+ * Detect if votes show polarization (bimodal distribution).
11993
+ *
11994
+ * Polarization is detected when votes cluster into two distinct groups,
11995
+ * typically at opposite ends of the score spectrum. This is identified by:
11996
+ * 1. High standard deviation (>= 3.0)
11997
+ * 2. Low density in the middle range (4-6)
11998
+ * 3. High density in the extremes (0-3 or 7-10)
11999
+ *
12000
+ * @param votes - List of critic votes
12001
+ * @returns True if polarization is detected, false otherwise
12002
+ * @throws NegotiationValidationError if votes list is empty
12003
+ */
12004
+ detectPolarization(votes) {
12005
+ if (votes.length === 0) {
12006
+ throw new NegotiationValidationError(
12007
+ "Cannot detect polarization in empty vote list"
12008
+ );
12009
+ }
12010
+ if (votes.length < 3) {
12011
+ return false;
12012
+ }
12013
+ const scores = votes.map((v) => v.score);
12014
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
12015
+ const variance = scores.reduce((sum, s) => sum + Math.pow(s - mean, 2), 0) / scores.length;
12016
+ const stdDev = Math.sqrt(variance);
12017
+ if (stdDev < 3) {
12018
+ return false;
12019
+ }
12020
+ const lowCount = scores.filter((s) => s <= 3).length;
12021
+ const middleCount = scores.filter((s) => s > 3 && s < 7).length;
12022
+ const highCount = scores.filter((s) => s >= 7).length;
12023
+ const hasLowCluster = lowCount >= votes.length * 0.3;
12024
+ const hasHighCluster = highCount >= votes.length * 0.3;
12025
+ const middleSparse = middleCount <= votes.length * 0.2;
12026
+ return hasLowCluster && hasHighCluster && middleSparse;
12027
+ }
12028
+ /**
12029
+ * Compute variance of confidence levels across votes.
12030
+ *
12031
+ * High variance in confidence suggests critics have different levels of
12032
+ * certainty about their evaluations, which may indicate the artifact is
12033
+ * harder to assess or has ambiguous quality.
12034
+ *
12035
+ * @param votes - List of critic votes
12036
+ * @returns Variance of confidence values
12037
+ * @throws NegotiationValidationError if votes list is empty
12038
+ */
12039
+ computeConfidenceVariance(votes) {
12040
+ if (votes.length === 0) {
12041
+ throw new NegotiationValidationError(
12042
+ "Cannot compute confidence variance of empty vote list"
12043
+ );
12044
+ }
12045
+ const confidences = votes.map((v) => v.confidence);
12046
+ const meanConfidence = confidences.reduce((a, b) => a + b, 0) / confidences.length;
12047
+ const variance = confidences.reduce(
12048
+ (sum, c) => sum + Math.pow(c - meanConfidence, 2),
12049
+ 0
12050
+ ) / confidences.length;
12051
+ return variance;
12052
+ }
12053
+ /**
12054
+ * Get comprehensive summary of vote characteristics.
12055
+ *
12056
+ * Combines multiple analytical methods to provide a complete picture
12057
+ * of the vote distribution and critic agreement.
12058
+ *
12059
+ * @param votes - List of critic votes
12060
+ * @returns Object with summary statistics
12061
+ * @throws NegotiationValidationError if votes list is empty
12062
+ */
12063
+ getVoteSummary(votes) {
12064
+ if (votes.length === 0) {
12065
+ throw new NegotiationValidationError("Cannot summarize empty vote list");
12066
+ }
12067
+ const passedCount = votes.filter((v) => v.passed).length;
12068
+ return {
12069
+ entropy: this.computeEntropy(votes),
12070
+ consensus: this.detectConsensus(votes),
12071
+ polarization: this.detectPolarization(votes),
12072
+ confidenceVariance: this.computeConfidenceVariance(votes),
12073
+ passRate: passedCount / votes.length
12074
+ };
12075
+ }
12076
+ };
12077
+
12078
+ // src/runtime/policyStore.ts
12079
+ var import_promises2 = __toESM(require("node:fs/promises"), 1);
12080
+ var import_node_path3 = __toESM(require("node:path"), 1);
12081
+ var HitlMode = /* @__PURE__ */ ((HitlMode2) => {
12082
+ HitlMode2["NONE"] = "None";
12083
+ HitlMode2["PAUSE_BETWEEN_ROUNDS"] = "PauseBetweenRounds";
12084
+ HitlMode2["PAUSE_ON_FINAL_ACCEPT"] = "PauseOnFinalAccept";
12085
+ return HitlMode2;
12086
+ })(HitlMode || {});
12087
+ var DEFAULT_EXECUTION_POLICY = {
12088
+ timeoutMs: 6e4,
12089
+ maxRetries: 3,
12090
+ backoff: "exponential",
12091
+ worktreeRequired: false,
12092
+ networkPolicy: "restricted",
12093
+ privilegeLevel: "standard",
12094
+ budgetCpuMs: 3e4,
12095
+ budgetWallMs: 6e4
12096
+ };
12097
+ var DEFAULT_ESCALATION_POLICY = {
12098
+ autoEscalateOnDeadlock: true,
12099
+ deadlockRounds: 3,
12100
+ escalationReasons: ["debate_deadlock", "security_flag", "timeout"],
12101
+ defaultAction: "escalate"
12102
+ };
12103
+ var PolicyStoreError = class extends Error {
12104
+ constructor(message) {
12105
+ super(message);
12106
+ this.name = "PolicyStoreError";
12107
+ }
12108
+ };
12109
+ var DEFAULT_NEGOTIATION_POLICY = {
12110
+ maxRounds: 10,
12111
+ scoreThreshold: 0.7,
12112
+ diffTolerance: 0.3,
12113
+ roundTimeoutMs: 3e4,
12114
+ tokenBudgetPerRound: 4096,
12115
+ totalTokenBudget: 0,
12116
+ // unlimited
12117
+ oscillationLimit: 3,
12118
+ hitl: "None" /* NONE */,
12119
+ scoring: {
12120
+ requireSchemaValid: true,
12121
+ requireExamplesPass: false,
12122
+ llmWeight: 0.5
12123
+ }
12124
+ };
12125
+ function generatePolicyId() {
12126
+ return `policy-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
12127
+ }
12128
+ function generatePolicyVersion() {
12129
+ const timestampMs = Date.now();
12130
+ const uniqueId = Math.random().toString(36).substring(2, 11);
12131
+ return `${timestampMs}_${uniqueId}`;
12132
+ }
12133
+ var InMemoryPolicyStore = class {
12134
+ // Maps policy_id -> list of EffectivePolicy (chronological order)
12135
+ policies = /* @__PURE__ */ new Map();
12136
+ profiles = /* @__PURE__ */ new Map();
12137
+ constructor() {
12138
+ this.initializeDefaultProfiles();
12139
+ }
12140
+ /**
12141
+ * Initialize default policy profiles.
12142
+ */
12143
+ initializeDefaultProfiles() {
12144
+ const lowProfile = {
12145
+ name: "LOW",
12146
+ negotiation: {
12147
+ maxRounds: 5,
12148
+ scoreThreshold: 0.6,
12149
+ diffTolerance: 0.4,
12150
+ roundTimeoutMs: 6e4,
12151
+ tokenBudgetPerRound: 2048,
12152
+ totalTokenBudget: 0,
12153
+ oscillationLimit: 5,
12154
+ hitl: "None" /* NONE */,
12155
+ scoring: {
12156
+ requireSchemaValid: false,
12157
+ requireExamplesPass: false,
12158
+ llmWeight: 0.3
12159
+ }
12160
+ },
12161
+ execution: {
12162
+ ...DEFAULT_EXECUTION_POLICY,
12163
+ timeoutMs: 12e4,
12164
+ // More lenient for low priority
12165
+ maxRetries: 5
12166
+ },
12167
+ escalation: {
12168
+ ...DEFAULT_ESCALATION_POLICY,
12169
+ deadlockRounds: 5
12170
+ // More tolerant
12171
+ }
12172
+ };
12173
+ const mediumProfile = {
12174
+ name: "MEDIUM",
12175
+ negotiation: { ...DEFAULT_NEGOTIATION_POLICY },
12176
+ execution: { ...DEFAULT_EXECUTION_POLICY },
12177
+ escalation: { ...DEFAULT_ESCALATION_POLICY }
12178
+ };
12179
+ const highProfile = {
12180
+ name: "HIGH",
12181
+ negotiation: {
12182
+ maxRounds: 15,
12183
+ scoreThreshold: 0.85,
12184
+ diffTolerance: 0.2,
12185
+ roundTimeoutMs: 2e4,
12186
+ tokenBudgetPerRound: 8192,
12187
+ totalTokenBudget: 1e5,
12188
+ oscillationLimit: 2,
12189
+ hitl: "PauseOnFinalAccept" /* PAUSE_ON_FINAL_ACCEPT */,
12190
+ scoring: {
12191
+ requireSchemaValid: true,
12192
+ requireExamplesPass: true,
12193
+ llmWeight: 0.7
12194
+ }
12195
+ },
12196
+ execution: {
12197
+ ...DEFAULT_EXECUTION_POLICY,
12198
+ timeoutMs: 3e4,
12199
+ // Stricter timeout
12200
+ maxRetries: 2,
12201
+ networkPolicy: "none"
12202
+ // More restrictive
12203
+ },
12204
+ escalation: {
12205
+ ...DEFAULT_ESCALATION_POLICY,
12206
+ deadlockRounds: 2,
12207
+ // Quick escalation
12208
+ autoEscalateOnDeadlock: true
12209
+ }
12210
+ };
12211
+ this.profiles.set("LOW", lowProfile);
12212
+ this.profiles.set("MEDIUM", mediumProfile);
12213
+ this.profiles.set("HIGH", highProfile);
12214
+ }
12215
+ /**
12216
+ * Get the latest version of a policy by its ID.
12217
+ *
12218
+ * @param policyId - The unique identifier of the policy
12219
+ * @returns The most recent effective policy if found, null otherwise
12220
+ */
12221
+ async getPolicy(policyId) {
12222
+ const versions = this.policies.get(policyId);
12223
+ if (!versions || versions.length === 0) {
12224
+ return null;
12225
+ }
12226
+ return versions[versions.length - 1];
12227
+ }
12228
+ /**
12229
+ * Save a policy snapshot to the version history.
12230
+ *
12231
+ * If the policy does not have an ID, one will be generated.
12232
+ * If the policy does not have a version, one will be generated.
12233
+ *
12234
+ * @param policy - The effective policy to save
12235
+ * @returns The policy ID
12236
+ */
12237
+ async savePolicy(policy) {
12238
+ const policyId = policy.policyId || generatePolicyId();
12239
+ const version2 = policy.version || generatePolicyVersion();
12240
+ const policyWithMeta = {
12241
+ ...policy,
12242
+ policyId,
12243
+ version: version2,
12244
+ createdAt: policy.createdAt || (/* @__PURE__ */ new Date()).toISOString()
12245
+ };
12246
+ const versions = this.policies.get(policyId) || [];
12247
+ versions.push(policyWithMeta);
12248
+ this.policies.set(policyId, versions);
12249
+ return policyId;
12250
+ }
12251
+ /**
12252
+ * List all policy IDs, optionally filtered by prefix.
12253
+ *
12254
+ * @param prefix - Optional prefix to filter policy IDs
12255
+ * @returns List of matching policy IDs
12256
+ */
12257
+ async listPolicies(prefix) {
12258
+ const allIds = Array.from(this.policies.keys());
12259
+ if (prefix === void 0) {
12260
+ return allIds;
12261
+ }
12262
+ return allIds.filter((id) => id.startsWith(prefix));
12263
+ }
12264
+ /**
12265
+ * Delete a policy by its ID (removes all versions).
12266
+ *
12267
+ * @param policyId - The unique identifier of the policy
12268
+ * @returns True if the policy was deleted, false if not found
12269
+ */
12270
+ async deletePolicy(policyId) {
12271
+ return this.policies.delete(policyId);
12272
+ }
12273
+ /**
12274
+ * Retrieve the complete version history for a policy.
12275
+ *
12276
+ * Returns policies in chronological order (oldest to newest).
12277
+ *
12278
+ * @param policyId - The unique identifier of the policy
12279
+ * @returns List of all versions of the policy
12280
+ */
12281
+ async getHistory(policyId) {
12282
+ const versions = this.policies.get(policyId);
12283
+ if (!versions) {
12284
+ return [];
12285
+ }
12286
+ return [...versions];
12287
+ }
12288
+ /**
12289
+ * Get a policy profile by name.
12290
+ *
12291
+ * @param name - The profile name
12292
+ * @returns The policy profile if found, null otherwise
12293
+ */
12294
+ async getProfile(name) {
12295
+ return this.profiles.get(name) || null;
12296
+ }
12297
+ /**
12298
+ * Save a policy profile.
12299
+ *
12300
+ * @param profile - The policy profile to save
12301
+ * @returns The profile name
12302
+ */
12303
+ async saveProfile(profile) {
12304
+ this.profiles.set(profile.name, profile);
12305
+ return profile.name;
12306
+ }
12307
+ /**
12308
+ * List all profile names.
12309
+ *
12310
+ * @returns List of profile names
12311
+ */
12312
+ async listProfiles() {
12313
+ return Array.from(this.profiles.keys());
12314
+ }
12315
+ /**
12316
+ * Create an effective policy from a profile and agent preferences.
12317
+ *
12318
+ * Clamps agent preferences to the profile's guardrails.
12319
+ *
12320
+ * @param profileName - The profile to use as base
12321
+ * @param agentPrefs - Optional agent preferences to apply
12322
+ * @param negotiationId - Optional negotiation ID
12323
+ * @returns The effective policy
12324
+ * @throws PolicyStoreError if the profile does not exist
12325
+ */
12326
+ async createEffectivePolicy(profileName, agentPrefs, negotiationId) {
12327
+ const profile = await this.getProfile(profileName);
12328
+ if (!profile) {
12329
+ throw new PolicyStoreError(`Profile '${profileName}' does not exist`);
12330
+ }
12331
+ const baseNegotiation = { ...profile.negotiation };
12332
+ const baseExecution = { ...profile.execution };
12333
+ const baseEscalation = { ...profile.escalation };
12334
+ const applied = {};
12335
+ if (agentPrefs) {
12336
+ for (const [agentId, prefs] of Object.entries(agentPrefs)) {
12337
+ const clamped = {};
12338
+ if (prefs.maxRounds !== void 0) {
12339
+ clamped.maxRounds = Math.min(prefs.maxRounds, baseNegotiation.maxRounds);
12340
+ }
12341
+ if (prefs.scoreThreshold !== void 0) {
12342
+ clamped.scoreThreshold = Math.max(
12343
+ prefs.scoreThreshold,
12344
+ baseNegotiation.scoreThreshold
12345
+ );
12346
+ }
12347
+ if (prefs.diffTolerance !== void 0) {
12348
+ clamped.diffTolerance = Math.min(
12349
+ prefs.diffTolerance,
12350
+ baseNegotiation.diffTolerance
12351
+ );
12352
+ }
12353
+ if (prefs.roundTimeoutMs !== void 0) {
12354
+ clamped.roundTimeoutMs = Math.min(
12355
+ prefs.roundTimeoutMs,
12356
+ baseNegotiation.roundTimeoutMs
12357
+ );
12358
+ }
12359
+ if (prefs.tokenBudgetPerRound !== void 0) {
12360
+ clamped.tokenBudgetPerRound = Math.min(
12361
+ prefs.tokenBudgetPerRound,
12362
+ baseNegotiation.tokenBudgetPerRound
12363
+ );
12364
+ }
12365
+ if (prefs.totalTokenBudget !== void 0 && baseNegotiation.totalTokenBudget > 0) {
12366
+ clamped.totalTokenBudget = Math.min(
12367
+ prefs.totalTokenBudget,
12368
+ baseNegotiation.totalTokenBudget
12369
+ );
12370
+ }
12371
+ if (prefs.oscillationLimit !== void 0) {
12372
+ clamped.oscillationLimit = Math.min(
12373
+ prefs.oscillationLimit,
12374
+ baseNegotiation.oscillationLimit
12375
+ );
12376
+ }
12377
+ applied[agentId] = clamped;
12378
+ }
12379
+ }
12380
+ const effectivePolicy = {
12381
+ policyId: generatePolicyId(),
12382
+ version: generatePolicyVersion(),
12383
+ negotiation: baseNegotiation,
12384
+ execution: baseExecution,
12385
+ escalation: baseEscalation,
12386
+ negotiationId,
12387
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
12388
+ };
12389
+ if (Object.keys(applied).length > 0) {
12390
+ effectivePolicy.applied = applied;
12391
+ }
12392
+ await this.savePolicy(effectivePolicy);
12393
+ return effectivePolicy;
12394
+ }
12395
+ };
12396
+ var JsonFilePolicyStore = class {
12397
+ directory;
12398
+ profiles = /* @__PURE__ */ new Map();
12399
+ /**
12400
+ * Create a new JSON file policy store.
12401
+ *
12402
+ * @param directory - Directory to store policy files
12403
+ */
12404
+ constructor(directory) {
12405
+ this.directory = directory;
12406
+ this.initializeDefaultProfiles();
12407
+ }
12408
+ /**
12409
+ * Initialize the store, creating the directory if needed.
12410
+ */
12411
+ async initialize() {
12412
+ await import_promises2.default.mkdir(this.directory, { recursive: true });
12413
+ }
12414
+ /**
12415
+ * Initialize default policy profiles.
12416
+ */
12417
+ initializeDefaultProfiles() {
12418
+ const lowProfile = {
12419
+ name: "LOW",
12420
+ negotiation: {
12421
+ maxRounds: 5,
12422
+ scoreThreshold: 0.6,
12423
+ diffTolerance: 0.4,
12424
+ roundTimeoutMs: 6e4,
12425
+ tokenBudgetPerRound: 2048,
12426
+ totalTokenBudget: 0,
12427
+ oscillationLimit: 5,
12428
+ hitl: "None" /* NONE */,
12429
+ scoring: {
12430
+ requireSchemaValid: false,
12431
+ requireExamplesPass: false,
12432
+ llmWeight: 0.3
12433
+ }
12434
+ },
12435
+ execution: {
12436
+ ...DEFAULT_EXECUTION_POLICY,
12437
+ timeoutMs: 12e4,
12438
+ maxRetries: 5
12439
+ },
12440
+ escalation: {
12441
+ ...DEFAULT_ESCALATION_POLICY,
12442
+ deadlockRounds: 5
12443
+ }
12444
+ };
12445
+ const mediumProfile = {
12446
+ name: "MEDIUM",
12447
+ negotiation: { ...DEFAULT_NEGOTIATION_POLICY },
12448
+ execution: { ...DEFAULT_EXECUTION_POLICY },
12449
+ escalation: { ...DEFAULT_ESCALATION_POLICY }
12450
+ };
12451
+ const highProfile = {
12452
+ name: "HIGH",
12453
+ negotiation: {
12454
+ maxRounds: 15,
12455
+ scoreThreshold: 0.85,
12456
+ diffTolerance: 0.2,
12457
+ roundTimeoutMs: 2e4,
12458
+ tokenBudgetPerRound: 8192,
12459
+ totalTokenBudget: 1e5,
12460
+ oscillationLimit: 2,
12461
+ hitl: "PauseOnFinalAccept" /* PAUSE_ON_FINAL_ACCEPT */,
12462
+ scoring: {
12463
+ requireSchemaValid: true,
12464
+ requireExamplesPass: true,
12465
+ llmWeight: 0.7
12466
+ }
12467
+ },
12468
+ execution: {
12469
+ ...DEFAULT_EXECUTION_POLICY,
12470
+ timeoutMs: 3e4,
12471
+ maxRetries: 2,
12472
+ networkPolicy: "none"
12473
+ },
12474
+ escalation: {
12475
+ ...DEFAULT_ESCALATION_POLICY,
12476
+ deadlockRounds: 2,
12477
+ autoEscalateOnDeadlock: true
12478
+ }
12479
+ };
12480
+ this.profiles.set("LOW", lowProfile);
12481
+ this.profiles.set("MEDIUM", mediumProfile);
12482
+ this.profiles.set("HIGH", highProfile);
12483
+ }
12484
+ /**
12485
+ * Sanitize a policy ID for use as a filename.
12486
+ */
12487
+ sanitizeId(policyId) {
12488
+ return policyId.replace(/[/\\]/g, "_");
12489
+ }
12490
+ /**
12491
+ * Get the file path for a policy.
12492
+ */
12493
+ getFilePath(policyId) {
12494
+ return import_node_path3.default.join(this.directory, `${this.sanitizeId(policyId)}.json`);
12495
+ }
12496
+ /**
12497
+ * Load versions from a file.
12498
+ */
12499
+ async loadFromFile(policyId) {
12500
+ const filePath = this.getFilePath(policyId);
12501
+ try {
12502
+ const data = await import_promises2.default.readFile(filePath, "utf-8");
12503
+ const parsed = JSON.parse(data);
12504
+ if (Array.isArray(parsed)) {
12505
+ return parsed;
12506
+ }
12507
+ return [parsed];
12508
+ } catch {
12509
+ return [];
12510
+ }
12511
+ }
12512
+ /**
12513
+ * Save versions to a file atomically.
12514
+ */
12515
+ async saveToFile(policyId, versions) {
12516
+ await this.initialize();
12517
+ const filePath = this.getFilePath(policyId);
12518
+ const tempPath = `${filePath}.tmp.${Date.now()}`;
12519
+ const data = JSON.stringify(versions, null, 2);
12520
+ await import_promises2.default.writeFile(tempPath, data, "utf-8");
12521
+ await import_promises2.default.rename(tempPath, filePath);
12522
+ }
12523
+ async getPolicy(policyId) {
12524
+ const versions = await this.loadFromFile(policyId);
12525
+ if (versions.length === 0) {
12526
+ return null;
12527
+ }
12528
+ return versions[versions.length - 1];
12529
+ }
12530
+ async savePolicy(policy) {
12531
+ const policyId = policy.policyId || generatePolicyId();
12532
+ const version2 = policy.version || generatePolicyVersion();
12533
+ const policyWithMeta = {
12534
+ ...policy,
12535
+ policyId,
12536
+ version: version2,
12537
+ createdAt: policy.createdAt || (/* @__PURE__ */ new Date()).toISOString()
12538
+ };
12539
+ const versions = await this.loadFromFile(policyId);
12540
+ versions.push(policyWithMeta);
12541
+ await this.saveToFile(policyId, versions);
12542
+ return policyId;
12543
+ }
12544
+ async listPolicies(prefix) {
12545
+ try {
12546
+ await this.initialize();
12547
+ const files = await import_promises2.default.readdir(this.directory);
12548
+ const policyIds = files.filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -5));
12549
+ if (prefix === void 0) {
12550
+ return policyIds;
12551
+ }
12552
+ return policyIds.filter((id) => id.startsWith(prefix));
12553
+ } catch {
12554
+ return [];
12555
+ }
12556
+ }
12557
+ async deletePolicy(policyId) {
12558
+ const filePath = this.getFilePath(policyId);
12559
+ try {
12560
+ await import_promises2.default.unlink(filePath);
12561
+ return true;
12562
+ } catch {
12563
+ return false;
12564
+ }
12565
+ }
12566
+ async getHistory(policyId) {
12567
+ return this.loadFromFile(policyId);
12568
+ }
12569
+ async getProfile(name) {
12570
+ return this.profiles.get(name) || null;
12571
+ }
12572
+ async saveProfile(profile) {
12573
+ this.profiles.set(profile.name, profile);
12574
+ return profile.name;
12575
+ }
12576
+ async listProfiles() {
12577
+ return Array.from(this.profiles.keys());
12578
+ }
12579
+ /**
12580
+ * Create an effective policy from a profile and agent preferences.
12581
+ */
12582
+ async createEffectivePolicy(profileName, agentPrefs, negotiationId) {
12583
+ const profile = await this.getProfile(profileName);
12584
+ if (!profile) {
12585
+ throw new PolicyStoreError(`Profile '${profileName}' does not exist`);
12586
+ }
12587
+ const baseNegotiation = { ...profile.negotiation };
12588
+ const baseExecution = { ...profile.execution };
12589
+ const baseEscalation = { ...profile.escalation };
12590
+ const applied = {};
12591
+ if (agentPrefs) {
12592
+ for (const [agentId, prefs] of Object.entries(agentPrefs)) {
12593
+ const clamped = {};
12594
+ if (prefs.maxRounds !== void 0) {
12595
+ clamped.maxRounds = Math.min(prefs.maxRounds, baseNegotiation.maxRounds);
12596
+ }
12597
+ if (prefs.scoreThreshold !== void 0) {
12598
+ clamped.scoreThreshold = Math.max(prefs.scoreThreshold, baseNegotiation.scoreThreshold);
12599
+ }
12600
+ if (prefs.diffTolerance !== void 0) {
12601
+ clamped.diffTolerance = Math.min(prefs.diffTolerance, baseNegotiation.diffTolerance);
12602
+ }
12603
+ if (prefs.roundTimeoutMs !== void 0) {
12604
+ clamped.roundTimeoutMs = Math.min(prefs.roundTimeoutMs, baseNegotiation.roundTimeoutMs);
12605
+ }
12606
+ if (prefs.tokenBudgetPerRound !== void 0) {
12607
+ clamped.tokenBudgetPerRound = Math.min(prefs.tokenBudgetPerRound, baseNegotiation.tokenBudgetPerRound);
12608
+ }
12609
+ if (prefs.totalTokenBudget !== void 0 && baseNegotiation.totalTokenBudget > 0) {
12610
+ clamped.totalTokenBudget = Math.min(prefs.totalTokenBudget, baseNegotiation.totalTokenBudget);
12611
+ }
12612
+ if (prefs.oscillationLimit !== void 0) {
12613
+ clamped.oscillationLimit = Math.min(prefs.oscillationLimit, baseNegotiation.oscillationLimit);
12614
+ }
12615
+ applied[agentId] = clamped;
12616
+ }
12617
+ }
12618
+ const effectivePolicy = {
12619
+ policyId: generatePolicyId(),
12620
+ version: generatePolicyVersion(),
12621
+ negotiation: baseNegotiation,
12622
+ execution: baseExecution,
12623
+ escalation: baseEscalation,
12624
+ negotiationId,
12625
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
12626
+ };
12627
+ if (Object.keys(applied).length > 0) {
12628
+ effectivePolicy.applied = applied;
12629
+ }
12630
+ await this.savePolicy(effectivePolicy);
12631
+ return effectivePolicy;
12632
+ }
12633
+ };
12634
+
12635
+ // src/runtime/agentState.ts
12636
+ var AgentState = /* @__PURE__ */ ((AgentState2) => {
12637
+ AgentState2[AgentState2["AGENT_STATE_UNSPECIFIED"] = 0] = "AGENT_STATE_UNSPECIFIED";
12638
+ AgentState2[AgentState2["INITIALIZING"] = 1] = "INITIALIZING";
12639
+ AgentState2[AgentState2["RUNNABLE"] = 2] = "RUNNABLE";
12640
+ AgentState2[AgentState2["SCHEDULED"] = 3] = "SCHEDULED";
12641
+ AgentState2[AgentState2["RUNNING"] = 4] = "RUNNING";
12642
+ AgentState2[AgentState2["WAITING"] = 5] = "WAITING";
12643
+ AgentState2[AgentState2["WAITING_RESOURCES"] = 6] = "WAITING_RESOURCES";
12644
+ AgentState2[AgentState2["SUSPENDED"] = 7] = "SUSPENDED";
12645
+ AgentState2[AgentState2["RESUMED"] = 8] = "RESUMED";
12646
+ AgentState2[AgentState2["COMPLETED"] = 9] = "COMPLETED";
12647
+ AgentState2[AgentState2["FAILED"] = 10] = "FAILED";
12648
+ AgentState2[AgentState2["SHUTTING_DOWN"] = 11] = "SHUTTING_DOWN";
12649
+ AgentState2[AgentState2["RECOVERING"] = 12] = "RECOVERING";
12650
+ return AgentState2;
12651
+ })(AgentState || {});
12652
+ var StateTransitionError = class extends Error {
12653
+ fromState;
12654
+ toState;
12655
+ constructor(fromState, toState) {
12656
+ const fromName = AgentState[fromState];
12657
+ const toName = AgentState[toState];
12658
+ super(`Invalid state transition from ${fromName} to ${toName}`);
12659
+ this.name = "StateTransitionError";
12660
+ this.fromState = fromState;
12661
+ this.toState = toState;
12662
+ }
12663
+ };
12664
+ var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
12665
+ // INITIALIZING -> RUNNABLE
12666
+ [1 /* INITIALIZING */, /* @__PURE__ */ new Set([2 /* RUNNABLE */])],
12667
+ // RUNNABLE -> SCHEDULED
12668
+ [2 /* RUNNABLE */, /* @__PURE__ */ new Set([3 /* SCHEDULED */])],
12669
+ // SCHEDULED -> RUNNING
12670
+ [3 /* SCHEDULED */, /* @__PURE__ */ new Set([4 /* RUNNING */])],
12671
+ // RUNNING -> WAITING, WAITING_RESOURCES, SUSPENDED, COMPLETED, FAILED, SHUTTING_DOWN
12672
+ [
12673
+ 4 /* RUNNING */,
12674
+ /* @__PURE__ */ new Set([
12675
+ 5 /* WAITING */,
12676
+ 6 /* WAITING_RESOURCES */,
12677
+ 7 /* SUSPENDED */,
12678
+ 9 /* COMPLETED */,
12679
+ 10 /* FAILED */,
12680
+ 11 /* SHUTTING_DOWN */
12681
+ ])
12682
+ ],
12683
+ // WAITING -> RUNNING
12684
+ [5 /* WAITING */, /* @__PURE__ */ new Set([4 /* RUNNING */])],
12685
+ // WAITING_RESOURCES -> RUNNING, FAILED (resource timeout)
12686
+ [
12687
+ 6 /* WAITING_RESOURCES */,
12688
+ /* @__PURE__ */ new Set([4 /* RUNNING */, 10 /* FAILED */])
12689
+ ],
12690
+ // SUSPENDED -> RESUMED
12691
+ [7 /* SUSPENDED */, /* @__PURE__ */ new Set([8 /* RESUMED */])],
12692
+ // RESUMED -> RUNNING
12693
+ [8 /* RESUMED */, /* @__PURE__ */ new Set([4 /* RUNNING */])],
12694
+ // COMPLETED -> RUNNABLE
12695
+ [9 /* COMPLETED */, /* @__PURE__ */ new Set([2 /* RUNNABLE */])],
12696
+ // FAILED -> RECOVERING
12697
+ [10 /* FAILED */, /* @__PURE__ */ new Set([12 /* RECOVERING */])],
12698
+ // SHUTTING_DOWN -> FAILED (agent_shutdown_timeout)
12699
+ [11 /* SHUTTING_DOWN */, /* @__PURE__ */ new Set([10 /* FAILED */])],
12700
+ // RECOVERING -> RUNNABLE, SHUTTING_DOWN (recovery abort)
12701
+ [
12702
+ 12 /* RECOVERING */,
12703
+ /* @__PURE__ */ new Set([2 /* RUNNABLE */, 11 /* SHUTTING_DOWN */])
12704
+ ]
12705
+ ]);
12706
+ function isValidTransition(fromState, toState) {
12707
+ const validTargets = VALID_TRANSITIONS.get(fromState);
12708
+ if (!validTargets) {
12709
+ return false;
12710
+ }
12711
+ return validTargets.has(toState);
12712
+ }
12713
+ function getValidTransitions(fromState) {
12714
+ const validTargets = VALID_TRANSITIONS.get(fromState);
12715
+ if (!validTargets) {
12716
+ return [];
12717
+ }
12718
+ return Array.from(validTargets);
12719
+ }
12720
+ var AgentStateMachine = class {
12721
+ state = 0 /* AGENT_STATE_UNSPECIFIED */;
12722
+ hooks;
12723
+ stateHistory = [];
12724
+ /**
12725
+ * Create a new agent state machine.
12726
+ *
12727
+ * @param hooks - Optional lifecycle hooks
12728
+ */
12729
+ constructor(hooks) {
12730
+ this.hooks = hooks || {};
12731
+ }
12732
+ /**
12733
+ * Get the current state.
12734
+ *
12735
+ * @returns The current agent state
12736
+ */
12737
+ getState() {
12738
+ return this.state;
12739
+ }
12740
+ /**
12741
+ * Get the state history.
12742
+ *
12743
+ * @returns Array of state transitions with timestamps
12744
+ */
12745
+ getStateHistory() {
12746
+ return [...this.stateHistory];
12747
+ }
12748
+ /**
12749
+ * Initialize the agent (transition to INITIALIZING).
12750
+ *
12751
+ * @throws StateTransitionError if already initialized
12752
+ */
12753
+ async initialize() {
12754
+ if (this.state !== 0 /* AGENT_STATE_UNSPECIFIED */) {
12755
+ throw new StateTransitionError(this.state, 1 /* INITIALIZING */);
12756
+ }
12757
+ await this.transitionTo(1 /* INITIALIZING */);
12758
+ }
12759
+ /**
12760
+ * Transition to a new state.
12761
+ *
12762
+ * @param toState - The target state
12763
+ * @param context - Optional context for the transition
12764
+ * @throws StateTransitionError if the transition is invalid
12765
+ */
12766
+ async transitionTo(toState, context) {
12767
+ if (this.state === 0 /* AGENT_STATE_UNSPECIFIED */ && toState === 1 /* INITIALIZING */) {
12768
+ await this.doTransition(toState, context);
12769
+ return;
12770
+ }
12771
+ if (!isValidTransition(this.state, toState)) {
12772
+ throw new StateTransitionError(this.state, toState);
12773
+ }
12774
+ await this.doTransition(toState, context);
12775
+ }
12776
+ /**
12777
+ * Perform the state transition and call hooks.
12778
+ */
12779
+ async doTransition(toState, context) {
12780
+ const fromState = this.state;
12781
+ this.state = toState;
12782
+ this.stateHistory.push({
12783
+ state: toState,
12784
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12785
+ context
12786
+ });
12787
+ if (this.hooks.onStateChange) {
12788
+ await this.hooks.onStateChange(fromState, toState, context);
12789
+ }
12790
+ await this.callSpecificHooks(fromState, toState, context);
12791
+ }
12792
+ /**
12793
+ * Call specific lifecycle hooks based on the transition.
12794
+ */
12795
+ async callSpecificHooks(fromState, toState, context) {
12796
+ switch (toState) {
12797
+ case 3 /* SCHEDULED */:
12798
+ if (this.hooks.onScheduled) {
12799
+ const taskId = context?.taskId || "unknown";
12800
+ await this.hooks.onScheduled(taskId, context);
12801
+ }
12802
+ break;
12803
+ case 7 /* SUSPENDED */:
12804
+ if (fromState === 4 /* RUNNING */ && this.hooks.onPreempt) {
12805
+ const reason = context?.reason || "preemption";
12806
+ await this.hooks.onPreempt(reason, context);
12807
+ }
12808
+ break;
12809
+ case 4 /* RUNNING */:
12810
+ if (fromState === 8 /* RESUMED */ && this.hooks.onResume) {
12811
+ await this.hooks.onResume(context);
12812
+ }
12813
+ break;
12814
+ case 5 /* WAITING */:
12815
+ if (this.hooks.onWait) {
12816
+ const reason = context?.reason || "waiting";
12817
+ await this.hooks.onWait(reason, context);
12818
+ }
12819
+ break;
12820
+ case 6 /* WAITING_RESOURCES */:
12821
+ if (this.hooks.onWaitResources) {
12822
+ const resources = context?.resources || [];
12823
+ await this.hooks.onWaitResources(resources, context);
12824
+ }
12825
+ break;
12826
+ case 9 /* COMPLETED */:
12827
+ if (this.hooks.onComplete) {
12828
+ await this.hooks.onComplete(context?.result, context);
12829
+ }
12830
+ break;
12831
+ case 10 /* FAILED */:
12832
+ if (this.hooks.onFail) {
12833
+ const error = context?.error || new Error("Unknown failure");
12834
+ await this.hooks.onFail(error, context);
12835
+ }
12836
+ break;
12837
+ case 11 /* SHUTTING_DOWN */:
12838
+ if (this.hooks.onShutdown) {
12839
+ const gracePeriodMs = context?.gracePeriodMs || 3e4;
12840
+ await this.hooks.onShutdown(gracePeriodMs, context);
12841
+ }
12842
+ break;
12843
+ case 12 /* RECOVERING */:
12844
+ if (this.hooks.onRecover) {
12845
+ await this.hooks.onRecover(context);
12846
+ }
12847
+ break;
12848
+ }
12849
+ }
12850
+ /**
12851
+ * Check if the agent can transition to a given state.
12852
+ *
12853
+ * @param toState - The target state
12854
+ * @returns True if the transition is valid
12855
+ */
12856
+ canTransitionTo(toState) {
12857
+ if (this.state === 0 /* AGENT_STATE_UNSPECIFIED */ && toState === 1 /* INITIALIZING */) {
12858
+ return true;
12859
+ }
12860
+ return isValidTransition(this.state, toState);
12861
+ }
12862
+ /**
12863
+ * Get all states the agent can currently transition to.
12864
+ *
12865
+ * @returns Array of valid target states
12866
+ */
12867
+ getAvailableTransitions() {
12868
+ if (this.state === 0 /* AGENT_STATE_UNSPECIFIED */) {
12869
+ return [1 /* INITIALIZING */];
12870
+ }
12871
+ return getValidTransitions(this.state);
12872
+ }
12873
+ /**
12874
+ * Check if the agent is in a terminal state.
12875
+ *
12876
+ * Terminal states are states where the agent cannot make further
12877
+ * progress without external intervention.
12878
+ *
12879
+ * @returns True if in a terminal state
12880
+ */
12881
+ isTerminal() {
12882
+ return getValidTransitions(this.state).length === 0;
12883
+ }
12884
+ /**
12885
+ * Check if the agent is in an active state (executing work).
12886
+ *
12887
+ * @returns True if the agent is actively working
12888
+ */
12889
+ isActive() {
12890
+ return this.state === 4 /* RUNNING */ || this.state === 3 /* SCHEDULED */ || this.state === 8 /* RESUMED */;
12891
+ }
12892
+ /**
12893
+ * Check if the agent is in a waiting state.
12894
+ *
12895
+ * @returns True if the agent is waiting
12896
+ */
12897
+ isWaiting() {
12898
+ return this.state === 5 /* WAITING */ || this.state === 6 /* WAITING_RESOURCES */;
12899
+ }
12900
+ /**
12901
+ * Check if the agent is in a suspended or shutdown state.
12902
+ *
12903
+ * @returns True if the agent is suspended or shutting down
12904
+ */
12905
+ isSuspendedOrShuttingDown() {
12906
+ return this.state === 7 /* SUSPENDED */ || this.state === 11 /* SHUTTING_DOWN */;
12907
+ }
12908
+ /**
12909
+ * Update lifecycle hooks.
12910
+ *
12911
+ * @param hooks - New hooks to merge with existing hooks
12912
+ */
12913
+ setHooks(hooks) {
12914
+ this.hooks = { ...this.hooks, ...hooks };
12915
+ }
12916
+ /**
12917
+ * Reset the state machine to uninitialized state.
12918
+ *
12919
+ * This is primarily for testing purposes.
12920
+ */
12921
+ reset() {
12922
+ this.state = 0 /* AGENT_STATE_UNSPECIFIED */;
12923
+ this.stateHistory = [];
12924
+ }
12925
+ };
12926
+
10768
12927
  // src/internal/idempotency.ts
10769
12928
  var import_node_crypto3 = __toESM(require("node:crypto"), 1);
10770
12929
  function computeIdempotencyToken(input) {
@@ -10977,7 +13136,7 @@ var Resolver = class {
10977
13136
  try {
10978
13137
  const v = await this.backend.get(scope, key);
10979
13138
  return [v, scope.isGlobal ? "global" /* GLOBAL */ : "scoped" /* SCOPED */];
10980
- } catch (e) {
13139
+ } catch {
10981
13140
  }
10982
13141
  if (!scope.isGlobal) {
10983
13142
  const v = await this.backend.get(new Scope(null), key);
@@ -10989,24 +13148,24 @@ var Resolver = class {
10989
13148
 
10990
13149
  // src/secrets/backends/file.ts
10991
13150
  var import_node_fs = require("node:fs");
10992
- var import_node_path3 = require("node:path");
13151
+ var import_node_path4 = require("node:path");
10993
13152
  function defaultPath() {
10994
13153
  const isWin = process.platform === "win32";
10995
13154
  if (isWin) {
10996
- const base2 = process.env.APPDATA || (0, import_node_path3.join)(process.env.USERPROFILE || "", "AppData", "Roaming");
10997
- return (0, import_node_path3.join)(base2, "sw4rm", "secrets.json");
13155
+ const base2 = process.env.APPDATA || (0, import_node_path4.join)(process.env.USERPROFILE || "", "AppData", "Roaming");
13156
+ return (0, import_node_path4.join)(base2, "sw4rm", "secrets.json");
10998
13157
  }
10999
13158
  const xdg = process.env.XDG_CONFIG_HOME;
11000
- const base = xdg && xdg.length > 0 ? xdg : (0, import_node_path3.join)(process.env.HOME || "", ".config");
11001
- return (0, import_node_path3.join)(base, "sw4rm", "secrets.json");
13159
+ const base = xdg && xdg.length > 0 ? xdg : (0, import_node_path4.join)(process.env.HOME || "", ".config");
13160
+ return (0, import_node_path4.join)(base, "sw4rm", "secrets.json");
11002
13161
  }
11003
13162
  var FileBackend = class {
11004
13163
  path;
11005
- constructor(path3) {
11006
- this.path = path3 ?? defaultPath();
11007
- (0, import_node_fs.mkdirSync)((0, import_node_path3.dirname)(this.path), { recursive: true });
13164
+ constructor(path4) {
13165
+ this.path = path4 ?? defaultPath();
13166
+ (0, import_node_fs.mkdirSync)((0, import_node_path4.dirname)(this.path), { recursive: true });
11008
13167
  try {
11009
- (0, import_node_fs.chmodSync)((0, import_node_path3.dirname)(this.path), 448);
13168
+ (0, import_node_fs.chmodSync)((0, import_node_path4.dirname)(this.path), 448);
11010
13169
  } catch {
11011
13170
  }
11012
13171
  if (!(0, import_node_fs.existsSync)(this.path)) {
@@ -11026,7 +13185,7 @@ var FileBackend = class {
11026
13185
  }
11027
13186
  }
11028
13187
  safeWrite(obj) {
11029
- const tmp = (0, import_node_path3.join)((0, import_node_path3.dirname)(this.path), `.secrets.${Date.now()}.${Math.random().toString(16).slice(2)}`);
13188
+ const tmp = (0, import_node_path4.join)((0, import_node_path4.dirname)(this.path), `.secrets.${Date.now()}.${Math.random().toString(16).slice(2)}`);
11030
13189
  try {
11031
13190
  (0, import_node_fs.writeFileSync)(tmp, JSON.stringify(obj, null, 2), { encoding: "utf8", mode: 384 });
11032
13191
  (0, import_node_fs.renameSync)(tmp, this.path);
@@ -11134,7 +13293,7 @@ async function selectBackend(mode) {
11134
13293
  }
11135
13294
 
11136
13295
  // src/index.ts
11137
- var version = "0.3.0";
13296
+ var version = "0.4.0";
11138
13297
  // Annotate the CommonJS export names for ESM import in node:
11139
13298
  0 && (module.exports = {
11140
13299
  ACKLifecycleManager,
@@ -11142,24 +13301,46 @@ var version = "0.3.0";
11142
13301
  ActivityBuffer,
11143
13302
  ActivityBufferSync,
11144
13303
  ActivityClient,
13304
+ AgentState,
13305
+ AgentStateMachine,
13306
+ ArtifactType,
11145
13307
  BaseClient,
13308
+ BordaCountAggregator,
11146
13309
  CT_AGENT_REPORT_V1,
11147
13310
  CT_SCHEDULER_COMMAND_V1,
13311
+ ConfidenceWeightedAggregator,
11148
13312
  ConnectorClient,
13313
+ DEFAULT_ESCALATION_POLICY,
13314
+ DEFAULT_EXECUTION_POLICY,
13315
+ DEFAULT_NEGOTIATION_POLICY,
13316
+ DecisionOutcome,
11149
13317
  DefaultWorktreePolicy,
11150
13318
  ErrorCode,
11151
13319
  ErrorCodeMapper,
11152
13320
  FileBackend,
11153
13321
  HITLClient,
13322
+ HandoffClient,
13323
+ HandoffStatus,
13324
+ HandoffTimeoutError,
13325
+ HandoffValidationError,
13326
+ HitlMode,
13327
+ InMemoryPolicyStore,
11154
13328
  InterceptorChain,
11155
13329
  JSONFilePersistence,
13330
+ JsonFilePolicyStore,
11156
13331
  KeyringBackend,
11157
13332
  LoggingClient,
13333
+ MajorityVoteAggregator,
11158
13334
  MaxEntriesStrategy,
11159
13335
  MessageProcessor,
11160
13336
  MessageType,
11161
13337
  NegotiationClient,
13338
+ NegotiationRoomClient,
13339
+ NegotiationTimeoutError,
13340
+ NegotiationValidationError,
13341
+ NodeStatus,
11162
13342
  PersistentWorktreeState,
13343
+ PolicyStoreError,
11163
13344
  ReasoningClient,
11164
13345
  RegistryClient,
11165
13346
  Resolver,
@@ -11177,9 +13358,18 @@ var version = "0.3.0";
11177
13358
  SecretValidationError,
11178
13359
  SecretValue,
11179
13360
  Secrets,
13361
+ SimpleAverageAggregator,
13362
+ StateTransitionError,
11180
13363
  Sw4rmError,
11181
13364
  ToolClient,
13365
+ TriggerType,
13366
+ VotingAnalyzer,
13367
+ WorkflowClient,
13368
+ WorkflowCycleError,
13369
+ WorkflowStatus,
13370
+ WorkflowValidationError,
11182
13371
  WorktreeClient,
13372
+ aggregateVotes,
11183
13373
  buildAckEnvelope,
11184
13374
  buildEnvelope,
11185
13375
  computeIdempotencyToken,
@@ -11188,6 +13378,8 @@ var version = "0.3.0";
11188
13378
  decodeBase64,
11189
13379
  durationToMs,
11190
13380
  encodeSchedulerCommandV1,
13381
+ getValidTransitions,
13382
+ isValidTransition,
11191
13383
  loggingInterceptor,
11192
13384
  mapGrpcStatusToErrorCode,
11193
13385
  msToDuration,