witnora 0.18.4 → 0.18.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/gateway.js CHANGED
@@ -655,6 +655,9 @@ export async function createConfiguredWorkflowHarness(input) {
655
655
  client: hosted,
656
656
  checkpoints: new input.managed.FileWorkflowEvaluationCheckpointStore(join(input.directory, "data", "workflow-evaluations")),
657
657
  maxConcurrency: input.config.maxConcurrency,
658
+ supportedModes: Array.isArray(healthBody.modes)
659
+ ? healthBody.modes.filter((mode) => mode === "REPLAY" || mode === "SHADOW")
660
+ : [],
658
661
  evaluate: async ({ task, evaluation }) => {
659
662
  const response = await requestFetch(`${evaluatorOrigin}/v1/evaluate`, {
660
663
  method: "POST",
@@ -1257,20 +1260,33 @@ export async function activateManagedWorkflowHarness(options) {
1257
1260
  const path = join(directory, "workflow-harness.json");
1258
1261
  const serialized = `${JSON.stringify(config, null, 2)}\n`;
1259
1262
  let created = false;
1263
+ let changed = false;
1260
1264
  if (await exists(path)) {
1261
1265
  const current = await readFile(path, "utf8");
1262
1266
  if (current !== serialized) {
1263
1267
  const parsed = parseManagedWorkflowHarnessConfig(current);
1264
- if (parsed.schemaVersion !== MANAGED_WORKFLOW_HARNESS_SCHEMA || canonicalHarnessConfig(parsed) !== canonicalHarnessConfig(config))
1268
+ if (parsed.schemaVersion !== MANAGED_WORKFLOW_HARNESS_SCHEMA
1269
+ || (canonicalHarnessConfig(parsed) !== canonicalHarnessConfig(config)
1270
+ && !isExactGeneratedHarnessUpgrade(parsed, config, options.previousGeneratedModuleSha256))) {
1265
1271
  throw new Error("Existing workflow-harness.json differs from the generated Assurance Harness binding; refusing to overwrite customer configuration.");
1272
+ }
1266
1273
  await writeFile(path, serialized, { encoding: "utf8", mode: 0o600 });
1274
+ changed = true;
1267
1275
  }
1268
1276
  }
1269
1277
  else {
1270
1278
  await writeFile(path, serialized, { encoding: "utf8", mode: 0o600, flag: "wx" });
1271
1279
  created = true;
1280
+ changed = true;
1272
1281
  }
1273
- return { state: "READY_TO_START", path, modulePath: evaluatorModulePath, config, created };
1282
+ return { state: "READY_TO_START", path, modulePath: evaluatorModulePath, config, created, changed };
1283
+ }
1284
+ function isExactGeneratedHarnessUpgrade(current, next, previousGeneratedModuleSha256) {
1285
+ if (!previousGeneratedModuleSha256 || current.evaluatorModuleSha256 !== previousGeneratedModuleSha256 || current.evaluatorContractSha256 !== previousGeneratedModuleSha256)
1286
+ return false;
1287
+ const { realPathActivations: _currentActivations, evaluatorModuleSha256: _currentModule, evaluatorContractSha256: _currentContract, ...currentStable } = current;
1288
+ const { realPathActivations: _nextActivations, evaluatorModuleSha256: _nextModule, evaluatorContractSha256: _nextContract, ...nextStable } = next;
1289
+ return JSON.stringify(currentStable) === JSON.stringify(nextStable);
1274
1290
  }
1275
1291
  function canonicalHarnessConfig(value) {
1276
1292
  const { realPathActivations: _activations, ...stable } = value;
package/dist/onboard.js CHANGED
@@ -88,6 +88,7 @@ export async function runOnboard(options) {
88
88
  let gatewayMigration;
89
89
  let managedGateway;
90
90
  let runtimeUpgrade;
91
+ let realPathActivation;
91
92
  let assuranceHarnessReadiness = {
92
93
  state: "WAITING_FOR_CUSTOMER_HARNESS",
93
94
  limitation: "No approved customer Harness module is bound to this Agent repository.",
@@ -196,13 +197,13 @@ export async function runOnboard(options) {
196
197
  }
197
198
  const runtimeConfigured = await gatewayHasRuntimeWorker(repositoryPath);
198
199
  generatedFiles.push(...await generateAutopilotFiles(repositoryPath, repository.name, runtimeConfigured));
199
- const realPathActivation = await activateRealPathIntegrations({ repository: repositoryPath, server, projectId: token.projectId, apiKey: token.apiKey, env: options.env, fetch: requestFetch });
200
+ realPathActivation = await activateRealPathIntegrations({ repository: repositoryPath, server, projectId: token.projectId, apiKey: token.apiKey, env: options.env, fetch: requestFetch });
200
201
  generatedFiles.push(...realPathActivation.generatedFiles);
201
202
  try {
202
- const activation = await activateManagedWorkflowHarness({ repository: repositoryPath, realPathActivations: realPathActivation.activations });
203
+ const activation = await activateManagedWorkflowHarness({ repository: repositoryPath, realPathActivations: realPathActivation.activations, previousGeneratedModuleSha256: realPathActivation.previousGeneratedModuleSha256 });
203
204
  if (activation.created)
204
205
  generatedFiles.push(activation.path);
205
- assuranceHarnessChanged = activation.created;
206
+ assuranceHarnessChanged = activation.changed;
206
207
  assuranceHarnessReadiness = { state: "ACTIVE" };
207
208
  }
208
209
  catch (error) {
@@ -266,6 +267,7 @@ export async function runOnboard(options) {
266
267
  if (managedGateway?.started) {
267
268
  await gatewayLifecycle.stop({ repository: repositoryPath, configHome: options.configHome, fetch: requestFetch }).catch(() => undefined);
268
269
  }
270
+ await realPathActivation?.rollback().catch(() => undefined);
269
271
  await rollbackGeneratedFiles(generatedFiles);
270
272
  await runtimeUpgrade?.rollback().catch(() => undefined);
271
273
  if (gatewayMigration)
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
- import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
2
+ import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
3
  import { dirname, join, resolve } from "node:path";
4
4
  export async function activateRealPathIntegrations(options) {
5
5
  const repository = resolve(options.repository ?? process.cwd());
@@ -7,14 +7,14 @@ export async function activateRealPathIntegrations(options) {
7
7
  const base = options.server.replace(/\/$/, "");
8
8
  const response = await request(`${base}/v1/projects/${encodeURIComponent(options.projectId)}/real-path-integrations`, { headers: { authorization: `Bearer ${options.apiKey}` } });
9
9
  if (response.status === 404)
10
- return { state: "NOT_CONFIGURED", created: false, activations: [], generatedFiles: [] };
10
+ return { state: "NOT_CONFIGURED", created: false, activations: [], generatedFiles: [], rollback: async () => undefined };
11
11
  if (!response.ok)
12
12
  throw new Error(`Could not load approved real-path integrations (${response.status}).`);
13
13
  const body = await boundedJson(response);
14
14
  const approved = Array.isArray(body.integrations) ? body.integrations.map(parsePlan).filter((plan) => plan.status === "READY_TO_ACTIVATE") : [];
15
15
  const plans = approved.filter((plan) => ["STRIPE_REFUND", "SHOPIFY_DISPUTE", "ZENDESK_TICKET", "SALESFORCE_RECORD", "HUBSPOT_CRM_RECORD", "POSTGRES_RECORD"].includes(plan.generated.providerPackId) && plan.environment === "sandbox" && plan.customerSummary.evaluationMode === "SHADOW");
16
16
  if (!plans.length)
17
- return { state: "NOT_CONFIGURED", created: false, activations: [], generatedFiles: [] };
17
+ return { state: "NOT_CONFIGURED", created: false, activations: [], generatedFiles: [], rollback: async () => undefined };
18
18
  const environment = options.env ?? process.env;
19
19
  const activations = [];
20
20
  const scenarios = [];
@@ -32,7 +32,9 @@ export async function activateRealPathIntegrations(options) {
32
32
  let created = false;
33
33
  const generatedFiles = [];
34
34
  const current = await readFile(modulePath, "utf8").catch((error) => error.code === "ENOENT" ? undefined : Promise.reject(error));
35
- const prior = await readFile(manifestPath, "utf8").then((value) => JSON.parse(value)).catch(() => undefined);
35
+ const priorSource = await readFile(manifestPath, "utf8").catch((error) => error.code === "ENOENT" ? undefined : Promise.reject(error));
36
+ const prior = priorSource === undefined ? undefined : JSON.parse(priorSource);
37
+ const previousGeneratedModuleSha256 = current !== undefined && sha(current) === prior?.moduleDigestSha256 ? prior.moduleDigestSha256 : undefined;
36
38
  if (current === undefined) {
37
39
  await writeFile(modulePath, source, { encoding: "utf8", mode: 0o600, flag: "wx" });
38
40
  created = true;
@@ -44,12 +46,12 @@ export async function activateRealPathIntegrations(options) {
44
46
  const temporary = `${modulePath}.${randomUUID()}.tmp`;
45
47
  await writeFile(temporary, source, { encoding: "utf8", mode: 0o600, flag: "wx" });
46
48
  await rename(temporary, modulePath);
47
- generatedFiles.push(modulePath);
48
49
  }
49
50
  const manifest = { schemaVersion: "witnora.real_path_activation_manifest.v0.1", projectId: options.projectId, moduleDigestSha256, activations };
50
51
  await mkdir(dirname(manifestPath), { recursive: true });
51
52
  await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
52
- generatedFiles.push(manifestPath);
53
+ if (priorSource === undefined)
54
+ generatedFiles.push(manifestPath);
53
55
  for (const item of scenarios) {
54
56
  const path = join(repository, ".witnora", "scenarios", `${item.plan.taskContractId}.json`);
55
57
  await mkdir(dirname(path), { recursive: true });
@@ -62,7 +64,16 @@ export async function activateRealPathIntegrations(options) {
62
64
  throw error;
63
65
  }
64
66
  }
65
- return { state: "READY_TO_START", created, modulePath: "witnora.assurance-harness.mjs", activations, generatedFiles };
67
+ return { state: "READY_TO_START", created, modulePath: "witnora.assurance-harness.mjs", activations, generatedFiles, ...(previousGeneratedModuleSha256 ? { previousGeneratedModuleSha256 } : {}), rollback: async () => {
68
+ if (current === undefined)
69
+ await rm(modulePath, { force: true });
70
+ else
71
+ await writeFile(modulePath, current, { encoding: "utf8", mode: 0o600 });
72
+ if (priorSource === undefined)
73
+ await rm(manifestPath, { force: true });
74
+ else
75
+ await writeFile(manifestPath, priorSource, { encoding: "utf8", mode: 0o600 });
76
+ } };
66
77
  }
67
78
  async function providerPreflight(request, env, plan, now, postgresClientFactory) {
68
79
  if (plan.generated.providerPackId === "STRIPE_REFUND") {
@@ -231,7 +242,7 @@ const sha=(value)=>createHash("sha256").update(typeof value==="string"?value:JSO
231
242
  const request=async(url,key)=>{const response=await fetch(url,{method:"GET",headers:{accept:"application/json",authorization:"Bearer "+key},redirect:"error",signal:AbortSignal.timeout(5000)});if(!response.ok)throw new Error("Provider read-only observation failed ("+response.status+").");return response.json();};
232
243
  const observe=async(contract,resourceId,repository)=>{if(contract.sandboxObservation)return structuredClone(contract.sandboxObservation);const key=(await readFile(join(repository,contract.credentialHandle),"utf8")).trim();if(!key)throw new Error("The local read-only Provider credential is unavailable.");if(contract.providerPackId==="STRIPE_REFUND"){if(!key.startsWith("sk_test_"))throw new Error("Stripe test-mode credential is unavailable.");return request("https://api.stripe.com/v1/refunds/"+encodeURIComponent(resourceId),key);}if(contract.providerPackId==="SHOPIFY_DISPUTE"){const response=await fetch(contract.providerConfiguration.origin+"/admin/api/2025-07/shopify_payments/disputes/"+encodeURIComponent(resourceId)+".json",{method:"GET",headers:{accept:"application/json","x-shopify-access-token":key},redirect:"error",signal:AbortSignal.timeout(5000)});if(!response.ok)throw new Error("Provider read-only observation failed ("+response.status+").");return (await response.json()).dispute;}if(contract.providerPackId==="ZENDESK_TICKET")return (await request(contract.providerConfiguration.origin+"/api/v2/tickets/"+encodeURIComponent(resourceId)+".json",key)).ticket;if(contract.providerPackId==="SALESFORCE_RECORD")return request(contract.providerConfiguration.origin+"/services/data/v61.0/sobjects/"+encodeURIComponent(contract.providerConfiguration.resourceType)+"/"+encodeURIComponent(resourceId),key);if(contract.providerPackId==="HUBSPOT_CRM_RECORD")return (await request("https://api.hubapi.com/crm/v3/objects/"+encodeURIComponent(contract.providerConfiguration.resourceType)+"/"+encodeURIComponent(resourceId)+"?properties="+encodeURIComponent(contract.criterion.field),key)).properties;if(contract.providerPackId==="POSTGRES_RECORD"){for(const name of [contract.providerConfiguration.viewName,contract.providerConfiguration.idColumn,contract.criterion.field])if(!/^[A-Za-z][A-Za-z0-9_]{0,99}$/.test(name))throw new Error("PostgreSQL identifier is invalid.");const {Client}=await import("pg");const client=new Client({connectionString:key,application_name:"witnora-read-only-probe"});await client.connect();try{await client.query("BEGIN READ ONLY");const result=await client.query({name:"witnora-provider-observe",text:'SELECT "'+contract.criterion.field+'" FROM "'+contract.providerConfiguration.viewName+'" WHERE "'+contract.providerConfiguration.idColumn+'" = $1 LIMIT 1',values:[resourceId]});await client.query("ROLLBACK");return result.rows[0]??{};}catch(error){await client.query("ROLLBACK").catch(()=>{});throw error;}finally{await client.end();}}throw new Error("Provider Harness contract is unsupported.");};
233
244
  export function createWitnoraBusinessTaskEvaluatorOptions(context){return {
234
- loadShadowObservations:async(task)=>{const contract=contracts.find((item)=>item.taskContractId===task.id);if(!contract)throw new Error("No exact real-path contract.");const path=join(context.repository,".witnora","scenarios",task.id+".json");const value=JSON.parse(await readFile(path,"utf8"));if(!Array.isArray(value)||value.length>100)throw new Error("Local scenario file is invalid.");return value;},
245
+ loadShadowObservations:async(task)=>{const contract=contracts.find((item)=>item.taskContractId===task.id);if(!contract)throw new Error("No exact real-path contract.");const path=join(context.repository,".witnora","scenarios",task.id+".json");const value=JSON.parse(await readFile(path,"utf8"));if(!Array.isArray(value)||value.length>100)throw new Error("Local scenario file is invalid.");return value.map((item)=>({...item,source:"LIVE_SHADOW"}));},
235
246
  evaluateShadowCandidate:async(candidate,task)=>{const contract=contracts.find((item)=>item.taskContractId===task.id);if(!contract)throw new Error("No exact real-path contract.");const resourceId=String(candidate.input?.resourceId??"");if(!/^[A-Za-z0-9._:-]{1,200}$/.test(resourceId))throw new Error("Provider resourceId is invalid.");for(const pathId of contract.actionPathIds)candidate.propose({pathId,parametersDigestSha256:sha(resourceId)});const raw=await observe(contract,resourceId,context.repository);const actual=raw?.[contract.criterion.field];const observed=actual===undefined?{}:{[contract.criterion.field]:actual};return {resultDigestSha256:sha(observed),criteria:[{id:contract.criterion.id,passed:actual===contract.criterion.expected}]};}
236
247
  };}
237
248
  export async function checkWitnoraProviderHealth(context){for(const contract of contracts){const path=join(context.repository,".witnora","scenarios",contract.taskContractId+".json");const scenarios=JSON.parse(await readFile(path,"utf8"));const resourceId=String(scenarios?.[0]?.input?.resourceId??"");if(!/^[A-Za-z0-9._:-]{1,200}$/.test(resourceId))throw new Error("Provider health scenario is unavailable.");const raw=await observe(contract,resourceId,context.repository);if(raw?.[contract.criterion.field]===undefined)throw new Error("The approved Provider result field is no longer observable.");}return {ready:true,checked:contracts.length};}
@@ -126,6 +126,7 @@ export declare class ManagedBusinessWorkflowHarness {
126
126
  evaluation: ManagedWorkflowReadyEvaluation;
127
127
  }) => Promise<TaskEvaluationReport>;
128
128
  maxConcurrency?: number;
129
+ supportedModes?: Array<"REPLAY" | "SHADOW">;
129
130
  });
130
131
  tick(): Promise<ManagedBusinessWorkflowHarnessResult>;
131
132
  private runTick;
@@ -1 +1 @@
1
- {"version":3,"file":"managed-workflow-harness.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/managed-workflow-harness.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGzF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhE,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,+CAA+C,CAAC;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAA;KAAE,CAAC;IAC7E,KAAK,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,gBAAgB,GAAG,WAAW,CAAA;KAAE,CAAC,CAAC;IACvG,gBAAgB,EAAE,8BAA8B,EAAE,CAAC;IACnD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE;QAAE,gBAAgB,EAAE,CAAC,CAAC;QAAC,uBAAuB,EAAE,KAAK,CAAC;QAAC,uBAAuB,EAAE,IAAI,CAAA;KAAE,CAAC;IAC/F,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB,EAAE,MAAM,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,IAAI,EAAE,6BAA6B,CAAC;IACpC,gBAAgB,CAAC,EAAE;QACjB,MAAM,EAAE,iBAAiB,GAAG,gBAAgB,CAAC;QAC7C,sBAAsB,EAAE,MAAM,EAAE,CAAC;QACjC,gBAAgB,EAAE,MAAM,CAAC;QACzB,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,uCAAuC,CAAC;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,wBAAwB,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAC9H,OAAO,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAC;QAAC,qBAAqB,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,6BAA6B,CAAC;QAClH,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,qBAAqB,EAAE,MAAM,CAAC;QAAC,qBAAqB,EAAE,MAAM,EAAE,CAAC;QACpF,gBAAgB,EAAE,WAAW,CAAC,8BAA8B,CAAC,kBAAkB,CAAC,CAAC,CAAC;QAClF,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,gBAAgB,GAAG,SAAS,CAAC;KAC1E,CAAC,CAAC;IACH,MAAM,EAAE;QAAE,gBAAgB,EAAE,CAAC,CAAC;QAAC,2BAA2B,EAAE,IAAI,CAAC;QAAC,uBAAuB,EAAE,IAAI,CAAC;QAAC,sBAAsB,EAAE,KAAK,CAAA;KAAE,CAAC;IACjI,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,2BAA2B;IAC1C,mBAAmB,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC,CAAC;IAC1G,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAC5E,OAAO,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACjE,gBAAgB,CAAC,IAAI,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAC3D,MAAM,CAAC,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,4BAA4B,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvJ;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB,GAAG,2BAA2B,CAqD9B;AAED,MAAM,WAAW,iCAAiC;IAChD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAC;IAC7D,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED,qBAAa,uCAAwC,YAAW,iCAAiC;;IAGzF,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAK5D,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3C;AAED,qBAAa,qCAAsC,YAAW,iCAAiC;IACjF,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM;IAIxC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAS5D,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,OAAO,CAAC,IAAI;CAGb;AAED,MAAM,WAAW,oCAAoC;IACnD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4BAA4B,EAAE,MAAM,CAAC;IACrC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,qBAAa,8BAA8B;;gBAO7B,OAAO,EAAE;QACnB,MAAM,EAAE,2BAA2B,CAAC;QACpC,WAAW,EAAE,iCAAiC,CAAC;QAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE;YAAE,IAAI,EAAE,sBAAsB,CAAC;YAAC,UAAU,EAAE,8BAA8B,CAAA;SAAE,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACjI,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB;IAUD,IAAI,IAAI,OAAO,CAAC,oCAAoC,CAAC;YAMvC,OAAO;CAuFtB"}
1
+ {"version":3,"file":"managed-workflow-harness.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/managed-workflow-harness.ts"],"names":[],"mappings":"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"}
@@ -99,15 +99,19 @@ export class ManagedBusinessWorkflowHarness {
99
99
  #checkpoints;
100
100
  #evaluate;
101
101
  #maxConcurrency;
102
+ #supportedModes;
102
103
  #activeTick;
103
104
  constructor(options) {
104
105
  this.#client = options.client;
105
106
  this.#checkpoints = options.checkpoints;
106
107
  this.#evaluate = options.evaluate;
107
108
  this.#maxConcurrency = options.maxConcurrency ?? 4;
109
+ this.#supportedModes = new Set(options.supportedModes ?? ["REPLAY", "SHADOW"]);
108
110
  if (!Number.isSafeInteger(this.#maxConcurrency) || this.#maxConcurrency < 1 || this.#maxConcurrency > 16) {
109
111
  throw new Error("Managed Workflow Harness maxConcurrency must be between 1 and 16.");
110
112
  }
113
+ if (!this.#supportedModes.size)
114
+ throw new Error("Managed Workflow Harness requires at least one supported evaluation mode.");
111
115
  }
112
116
  tick() {
113
117
  if (this.#activeTick)
@@ -129,7 +133,7 @@ export class ManagedBusinessWorkflowHarness {
129
133
  limitations.push(`Workflow ${workflow.id} was not scheduled because its authoritative Run inspection was truncated.`);
130
134
  break;
131
135
  }
132
- const ready = plan.readyEvaluations.filter((evaluation) => !seen.has(checkpointKey(plan, evaluation)));
136
+ const ready = plan.readyEvaluations.filter((evaluation) => this.#supportedModes.has(evaluation.mode) && !seen.has(checkpointKey(plan, evaluation)));
133
137
  if (!ready.length)
134
138
  break;
135
139
  const results = await mapLimit(ready, this.#maxConcurrency, async (evaluation) => {
@@ -171,7 +175,7 @@ export class ManagedBusinessWorkflowHarness {
171
175
  limitations: ["This client does not expose Nora Autopilot dispatches."],
172
176
  };
173
177
  validateAutopilotPlan(autopilot);
174
- const readyDispatches = autopilot.dispatches.filter((dispatch) => dispatch.status === "READY");
178
+ const readyDispatches = autopilot.dispatches.filter((dispatch) => dispatch.status === "READY" && this.#supportedModes.has(dispatch.mode));
175
179
  const autopilotResults = await mapLimit(readyDispatches, this.#maxConcurrency, async (dispatch) => {
176
180
  const evaluation = {
177
181
  nodeId: `autopilot:${dispatch.id}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "witnora",
3
- "version": "0.18.4",
3
+ "version": "0.18.6",
4
4
  "description": "Independent assurance for covered agent action paths across models and frameworks.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",