witnora 0.20.11 → 0.20.14
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/cli.js +15 -2
- package/dist/command-help.js +5 -0
- package/dist/credentials.js +28 -6
- package/dist/gateway.js +112 -12
- package/dist/internal/control-client/durable-action-worker.d.ts.map +1 -1
- package/dist/internal/control-client/durable-action-worker.js +17 -1
- package/dist/onboard.js +7 -5
- package/dist/real-path-activation.js +22 -1
- package/dist/vendor/onegent-runtime/failure-runtime-watch.d.ts +2 -0
- package/dist/vendor/onegent-runtime/failure-runtime-watch.d.ts.map +1 -1
- package/dist/vendor/onegent-runtime/failure-runtime-watch.js +79 -62
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -155,7 +155,7 @@ else if (command === "onboard") {
|
|
|
155
155
|
throw new Error("--project <project-id> is required.");
|
|
156
156
|
await runOnboard({
|
|
157
157
|
projectId,
|
|
158
|
-
server: readFlag("--server")
|
|
158
|
+
server: readFlag("--server"),
|
|
159
159
|
name: readFlag("--name"),
|
|
160
160
|
repository: readFlag("--repo") ?? process.cwd(),
|
|
161
161
|
template: readFlag("--template") ? parseAgentTemplate(readFlag("--template")) : undefined,
|
|
@@ -282,6 +282,8 @@ else if (command === "gateway") {
|
|
|
282
282
|
configHome,
|
|
283
283
|
}, () => stopManagedCustomerGateway({ repository, dir, configHome }));
|
|
284
284
|
process.stdout.write(readBoolFlag("--json") ? `${JSON.stringify(result, null, 2)}\n` : renderManagedGatewayStatus(result));
|
|
285
|
+
if (!readBoolFlag("--json"))
|
|
286
|
+
process.stdout.write("Automatic startup remains installed if previously configured. To remove it, run witnora gateway service uninstall with the same --repo and --dir options. Saved credentials and evidence are retained.\n");
|
|
285
287
|
}
|
|
286
288
|
else if (action === "exec") {
|
|
287
289
|
const boundary = process.argv.indexOf("--", 4);
|
|
@@ -322,7 +324,9 @@ else if (command === "gateway") {
|
|
|
322
324
|
process.stdout.write(`Configured the Managed Workflow Harness for ${result.config.workflowIds?.length ?? "all active"} Workflow Contract(s).\nConfig: ${result.path}\nRestart the managed Gateway to activate it.\n`);
|
|
323
325
|
}
|
|
324
326
|
else {
|
|
325
|
-
|
|
327
|
+
process.stdout.write(renderCommandHelp("gateway"));
|
|
328
|
+
if (action !== "help")
|
|
329
|
+
process.exitCode = 1;
|
|
326
330
|
}
|
|
327
331
|
}
|
|
328
332
|
else if (command === "discover") {
|
|
@@ -901,11 +905,18 @@ else if (command === "conformance") {
|
|
|
901
905
|
}
|
|
902
906
|
else {
|
|
903
907
|
process.stdout.write(`Usage:
|
|
908
|
+
Connection and discovery:
|
|
904
909
|
witnora onboard --project <project-id>
|
|
910
|
+
witnora discover [--connection <name>] [--repo <directory>]
|
|
911
|
+
witnora gateway --help
|
|
912
|
+
witnora gateway status|doctor|start|restart|stop
|
|
913
|
+
witnora gateway service install|uninstall
|
|
905
914
|
witnora mcp
|
|
906
915
|
witnora try --template workflow [--push]
|
|
907
916
|
witnora init --subject my-browser-agent
|
|
908
917
|
witnora connect --server https://witnora.com --project <project-id>
|
|
918
|
+
|
|
919
|
+
Local setup and evaluation:
|
|
909
920
|
witnora sandbox init
|
|
910
921
|
witnora sandbox certify --adapter ./witnora.sandbox.mjs
|
|
911
922
|
witnora sandbox push --adapter ./witnora.sandbox.mjs
|
|
@@ -913,6 +924,8 @@ else {
|
|
|
913
924
|
witnora browser-adapter certify --adapter ./witnora.browser-adapter.mjs
|
|
914
925
|
witnora init --out witnora.config.json --tripwire-config tripwire.yml --force
|
|
915
926
|
witnora init --subject my-browser-agent --github-action
|
|
927
|
+
|
|
928
|
+
Evidence, reports, and history:
|
|
916
929
|
witnora report --mcpbench .mcpbench/latest/results.json --tripwire .tripwire/latest/tripwire-result.json --onegent .onegent/procurement/audit-packet.json --out .witnora/latest --subject my-agent
|
|
917
930
|
witnora corpus ingest --tripwire .tripwire/latest/tripwire-result.json --out .witnora/corpus/corpus.jsonl --subject my-agent
|
|
918
931
|
witnora corpus review --corpus .witnora/corpus/corpus.jsonl --reviews .witnora/corpus/failure-reviews.jsonl --pattern-key <failure-key> --type wrong_click --status corrected
|
package/dist/command-help.js
CHANGED
|
@@ -48,6 +48,8 @@ writes missing starter files, starts a customer-owned Gateway in the background,
|
|
|
48
48
|
isolated synthetic self-test receipt. The self-test does not create assurance evidence or establish
|
|
49
49
|
CURRENT status. When --action-transport is selected, Witnora validates that exact local transport
|
|
50
50
|
without proposing or executing an Action and reports the bounded result to Hosted.
|
|
51
|
+
Use witnora gateway stop to stop it now, or witnora gateway service uninstall to remove
|
|
52
|
+
automatic startup. Both preserve saved credentials and historical evidence.
|
|
51
53
|
|
|
52
54
|
Options:
|
|
53
55
|
--server <url> Hosted server (default: https://witnora.com)
|
|
@@ -86,6 +88,7 @@ Options:
|
|
|
86
88
|
witnora gateway service install|uninstall
|
|
87
89
|
witnora gateway stop
|
|
88
90
|
witnora gateway run
|
|
91
|
+
witnora gateway exec -- <agent command>
|
|
89
92
|
witnora gateway workflow-harness --workflow <id> --evaluator-origin http://127.0.0.1:<port>/ \\
|
|
90
93
|
--evaluator-credential-handle file://... --evaluator-contract-sha256 <sha256>
|
|
91
94
|
|
|
@@ -96,6 +99,8 @@ under customer control. The service command installs an OS-native auto-start and
|
|
|
96
99
|
boundary. Repair safely reinstalls that boundary, restarts the existing generated Gateway,
|
|
97
100
|
and reruns digest, credential, Probe, and health checks. The run command is the foreground
|
|
98
101
|
debugging path.
|
|
102
|
+
Stopping the Gateway preserves its installed service. Use gateway service uninstall
|
|
103
|
+
to remove automatic startup without deleting saved credentials or historical evidence.
|
|
99
104
|
|
|
100
105
|
The reference Gateway establishes RECORDED evidence only. ENFORCED requires target
|
|
101
106
|
write credentials behind a controlled execution adapter. OUTCOME VERIFIED requires a
|
package/dist/credentials.js
CHANGED
|
@@ -33,16 +33,27 @@ export async function loadConnection(name, options = {}) {
|
|
|
33
33
|
}
|
|
34
34
|
export async function resolveConnection(options = {}) {
|
|
35
35
|
const env = options.env ?? process.env;
|
|
36
|
-
const
|
|
36
|
+
const explicit = options.server && options.projectId && options.apiKey;
|
|
37
|
+
const stored = explicit
|
|
37
38
|
? undefined
|
|
38
39
|
: await loadConnection(options.name, options);
|
|
39
|
-
if (options.name && stored && !
|
|
40
|
-
|
|
40
|
+
if (options.name && !stored && !explicit) {
|
|
41
|
+
throw new Error(`Saved connection "${options.name}" was not found. Run \`witnora onboard --project <project-id> --name ${options.name}\` or provide all three connection flags.`);
|
|
42
|
+
}
|
|
43
|
+
// A browser-approved connection is one credential tuple. Ambient variables must
|
|
44
|
+
// not redirect it to another project or supply that project's key.
|
|
45
|
+
const witnoraEnvironment = env.WITNORA_BASE_URL !== undefined || env.WITNORA_PROJECT_ID !== undefined || env.WITNORA_API_KEY !== undefined;
|
|
46
|
+
const source = stored ?? (witnoraEnvironment
|
|
47
|
+
? { server: env.WITNORA_BASE_URL, projectId: env.WITNORA_PROJECT_ID, apiKey: env.WITNORA_API_KEY }
|
|
48
|
+
: { server: env.AGENTCERT_BASE_URL, projectId: env.AGENTCERT_PROJECT_ID, apiKey: env.AGENTCERT_API_KEY });
|
|
49
|
+
if (!explicit && ((options.server && source.server && normalizeServer(options.server) !== normalizeServer(source.server))
|
|
50
|
+
|| (options.projectId && source.projectId && options.projectId.trim() !== source.projectId.trim()))) {
|
|
51
|
+
throw new Error("Partial connection flags change the saved or environment server/project. Provide --server, --project, and --api-key together to select another credential tuple; no request was sent.");
|
|
41
52
|
}
|
|
42
53
|
const candidate = {
|
|
43
|
-
server: options.server ??
|
|
44
|
-
projectId: options.projectId ??
|
|
45
|
-
apiKey: options.apiKey ??
|
|
54
|
+
server: options.server ?? source.server,
|
|
55
|
+
projectId: options.projectId ?? source.projectId,
|
|
56
|
+
apiKey: options.apiKey ?? source.apiKey,
|
|
46
57
|
};
|
|
47
58
|
const missing = Object.entries(candidate).filter(([, value]) => !value).map(([key]) => key);
|
|
48
59
|
if (missing.length > 0) {
|
|
@@ -50,6 +61,17 @@ export async function resolveConnection(options = {}) {
|
|
|
50
61
|
}
|
|
51
62
|
return validateConnection(candidate);
|
|
52
63
|
}
|
|
64
|
+
export function resolveOnboardServer(options) {
|
|
65
|
+
if (options.server)
|
|
66
|
+
return normalizeServer(options.server);
|
|
67
|
+
const env = options.env ?? process.env;
|
|
68
|
+
const server = env.WITNORA_BASE_URL ?? env.AGENTCERT_BASE_URL;
|
|
69
|
+
const projectId = env.WITNORA_BASE_URL !== undefined ? env.WITNORA_PROJECT_ID : env.AGENTCERT_PROJECT_ID;
|
|
70
|
+
if (server && projectId && projectId !== options.projectId) {
|
|
71
|
+
throw new Error(`Onboarding project "${options.projectId}" differs from environment project "${projectId}". Pass --server <url> explicitly to choose the intended server; no authorization request was sent.`);
|
|
72
|
+
}
|
|
73
|
+
return normalizeServer(server ?? DEFAULT_WITNORA_SERVER);
|
|
74
|
+
}
|
|
53
75
|
export function credentialsPath(options = {}) {
|
|
54
76
|
const configHome = options.configHome
|
|
55
77
|
?? process.env.WITNORA_CONFIG_HOME
|
package/dist/gateway.js
CHANGED
|
@@ -574,6 +574,7 @@ export async function runCustomerGateway(options) {
|
|
|
574
574
|
directory, config, connection, configHome: options.configHome,
|
|
575
575
|
DurableApprovedActionWorker: (await durableWorker).DurableApprovedActionWorker,
|
|
576
576
|
FileActionCheckpointStore: (await durableWorker).FileActionCheckpointStore,
|
|
577
|
+
onReceipt: () => assuranceController.wakeRuntimeWatch(),
|
|
577
578
|
})
|
|
578
579
|
: undefined;
|
|
579
580
|
const probeCredentialReady = createBoundedRuntimeProbeReadiness({
|
|
@@ -738,6 +739,10 @@ export async function createConfiguredWorkflowHarness(input) {
|
|
|
738
739
|
: undefined;
|
|
739
740
|
const basePollIntervalMs = input.config.pollIntervalMs ?? 5_000;
|
|
740
741
|
const maxIdlePollIntervalMs = Math.max(basePollIntervalMs, 15 * 60_000);
|
|
742
|
+
// Receipt events wake the read-only Watch; this modest periodic check covers
|
|
743
|
+
// restart recovery, new cases, and results produced by another local worker.
|
|
744
|
+
const watchPollIntervalMs = 60_000;
|
|
745
|
+
let nextWatchAt = Date.now() + watchPollIntervalMs;
|
|
741
746
|
const runtimeWatch = runtimeWatchConfiguration
|
|
742
747
|
&& input.managed.ManagedFailureRuntimeWatch
|
|
743
748
|
&& input.managed.FileFailureRuntimeWatchCheckpointStore
|
|
@@ -751,7 +756,8 @@ export async function createConfiguredWorkflowHarness(input) {
|
|
|
751
756
|
fetch: requestFetch,
|
|
752
757
|
}),
|
|
753
758
|
checkpoints: new input.managed.FileFailureRuntimeWatchCheckpointStore(join(input.directory, "data", "failure-runtime-watch")),
|
|
754
|
-
intervalMs:
|
|
759
|
+
intervalMs: watchPollIntervalMs,
|
|
760
|
+
nextCheckAt: () => new Date(nextWatchAt).toISOString(),
|
|
755
761
|
...(activation ? { bindings: [{ taskContractId: activation.taskContractId, actionPathId: activation.actionPathIds[0], environment: "sandbox" }] } : {}),
|
|
756
762
|
readOutcome: async ({ resourceId, actions, receipts }) => input.managed.readLocalSandboxRuntimeWatchOutcome({
|
|
757
763
|
path: join(input.directory, "data", "runtime-sandbox", "fixture", "audit.jsonl"),
|
|
@@ -764,19 +770,66 @@ export async function createConfiguredWorkflowHarness(input) {
|
|
|
764
770
|
})
|
|
765
771
|
: undefined;
|
|
766
772
|
let timer;
|
|
773
|
+
let watchTimer;
|
|
774
|
+
let wakeTimer;
|
|
775
|
+
let watchInFlight;
|
|
776
|
+
let watchPending = false;
|
|
767
777
|
let closing = false;
|
|
768
778
|
let idleTicks = 0;
|
|
769
779
|
let lastTickAt;
|
|
770
780
|
let lastError;
|
|
771
781
|
let lastProviderHealthAt = 0;
|
|
772
|
-
const
|
|
782
|
+
const runWatch = () => {
|
|
783
|
+
if (!runtimeWatch || closing)
|
|
784
|
+
return Promise.resolve(undefined);
|
|
785
|
+
if (watchInFlight)
|
|
786
|
+
return watchInFlight;
|
|
787
|
+
watchInFlight = runtimeWatch.tick().finally(() => {
|
|
788
|
+
watchInFlight = undefined;
|
|
789
|
+
if (watchPending)
|
|
790
|
+
wakeRuntimeWatch();
|
|
791
|
+
});
|
|
792
|
+
return watchInFlight;
|
|
793
|
+
};
|
|
794
|
+
const wakeRuntimeWatch = () => {
|
|
795
|
+
if (!runtimeWatch || closing)
|
|
796
|
+
return;
|
|
797
|
+
watchPending = true;
|
|
798
|
+
if (wakeTimer || watchInFlight)
|
|
799
|
+
return;
|
|
800
|
+
wakeTimer = setTimeout(() => {
|
|
801
|
+
wakeTimer = undefined;
|
|
802
|
+
// A Receipt arriving during a scan requires one following scan: the
|
|
803
|
+
// in-flight snapshot may already have read its Action/Receipt list.
|
|
804
|
+
if (watchInFlight)
|
|
805
|
+
return;
|
|
806
|
+
watchPending = false;
|
|
807
|
+
void runWatch().catch((error) => {
|
|
808
|
+
process.stderr.write(`Runtime Watch check failed: ${message(error)}\n`);
|
|
809
|
+
});
|
|
810
|
+
}, 100);
|
|
811
|
+
wakeTimer.unref?.();
|
|
812
|
+
};
|
|
813
|
+
const scheduleWatch = () => {
|
|
814
|
+
if (!runtimeWatch || closing)
|
|
815
|
+
return;
|
|
816
|
+
nextWatchAt = Date.now() + watchPollIntervalMs;
|
|
817
|
+
watchTimer = setTimeout(() => {
|
|
818
|
+
scheduleWatch();
|
|
819
|
+
wakeRuntimeWatch();
|
|
820
|
+
}, watchPollIntervalMs);
|
|
821
|
+
watchTimer.unref?.();
|
|
822
|
+
};
|
|
823
|
+
const tick = async (includeWatch = true) => {
|
|
773
824
|
try {
|
|
774
825
|
if (managedEvaluator?.healthCheck && Date.now() - lastProviderHealthAt >= 30_000) {
|
|
775
826
|
lastProviderHealthAt = Date.now();
|
|
776
827
|
await managedEvaluator.healthCheck();
|
|
777
828
|
}
|
|
778
|
-
const result = await
|
|
779
|
-
|
|
829
|
+
const [result, watchResult] = await Promise.all([
|
|
830
|
+
worker.tick(),
|
|
831
|
+
includeWatch ? runWatch() : Promise.resolve(undefined),
|
|
832
|
+
]);
|
|
780
833
|
lastTickAt = new Date().toISOString();
|
|
781
834
|
lastError = (result.evaluationsFailed ?? 0) > 0 ? result.limitations?.[0] ?? "One or more evaluations failed closed." : undefined;
|
|
782
835
|
if ((result.evaluationsFailed ?? 0) > 0) {
|
|
@@ -800,6 +853,8 @@ export async function createConfiguredWorkflowHarness(input) {
|
|
|
800
853
|
start() {
|
|
801
854
|
if (timer || closing)
|
|
802
855
|
return;
|
|
856
|
+
scheduleWatch();
|
|
857
|
+
wakeRuntimeWatch();
|
|
803
858
|
const schedule = (delayMs) => {
|
|
804
859
|
if (closing)
|
|
805
860
|
return;
|
|
@@ -809,7 +864,7 @@ export async function createConfiguredWorkflowHarness(input) {
|
|
|
809
864
|
const run = async () => {
|
|
810
865
|
let didWork = false;
|
|
811
866
|
try {
|
|
812
|
-
const result = await tick();
|
|
867
|
+
const result = await tick(false);
|
|
813
868
|
didWork = workflowHarnessTickDidWork(result);
|
|
814
869
|
}
|
|
815
870
|
catch (error) {
|
|
@@ -823,11 +878,19 @@ export async function createConfiguredWorkflowHarness(input) {
|
|
|
823
878
|
};
|
|
824
879
|
schedule(0);
|
|
825
880
|
},
|
|
881
|
+
wakeRuntimeWatch,
|
|
826
882
|
async close() {
|
|
827
883
|
closing = true;
|
|
828
884
|
if (timer)
|
|
829
885
|
clearTimeout(timer);
|
|
886
|
+
if (watchTimer)
|
|
887
|
+
clearTimeout(watchTimer);
|
|
888
|
+
if (wakeTimer)
|
|
889
|
+
clearTimeout(wakeTimer);
|
|
830
890
|
timer = undefined;
|
|
891
|
+
watchTimer = undefined;
|
|
892
|
+
wakeTimer = undefined;
|
|
893
|
+
await watchInFlight?.catch(() => undefined);
|
|
831
894
|
await managedEvaluator?.close();
|
|
832
895
|
},
|
|
833
896
|
async status() {
|
|
@@ -856,6 +919,7 @@ export async function createContinuousAssuranceController(input) {
|
|
|
856
919
|
const managed = input.managed ?? await configManagedWorkflowHarnessImport();
|
|
857
920
|
let harness;
|
|
858
921
|
let harnessFingerprint;
|
|
922
|
+
let harnessHasRealPathBindings = false;
|
|
859
923
|
let timer;
|
|
860
924
|
let reconciling = false;
|
|
861
925
|
let closing = false;
|
|
@@ -879,29 +943,38 @@ export async function createContinuousAssuranceController(input) {
|
|
|
879
943
|
const previous = harness;
|
|
880
944
|
harness = next;
|
|
881
945
|
harnessFingerprint = fingerprint;
|
|
946
|
+
harnessHasRealPathBindings = config.schemaVersion === MANAGED_WORKFLOW_HARNESS_SCHEMA && Boolean(config.realPathActivations?.length);
|
|
882
947
|
await previous?.close();
|
|
883
948
|
};
|
|
884
949
|
const workflowHarnessPath = join(input.directory, "workflow-harness.json");
|
|
885
950
|
if (await exists(workflowHarnessPath)) {
|
|
886
951
|
try {
|
|
887
|
-
|
|
952
|
+
const current = parseManagedWorkflowHarnessConfig(await readFile(workflowHarnessPath, "utf8"));
|
|
953
|
+
// Reconcile generated provider bindings against this Agent before starting
|
|
954
|
+
// a cached Harness; older installations may contain another Agent's plan.
|
|
955
|
+
if (current.schemaVersion !== MANAGED_WORKFLOW_HARNESS_SCHEMA || !current.realPathActivations?.length)
|
|
956
|
+
await replaceHarness(current);
|
|
888
957
|
}
|
|
889
958
|
catch (error) {
|
|
890
959
|
lastReportedError = message(error);
|
|
891
960
|
process.stderr.write(`Existing Assurance Harness will be repaired in the background: ${lastReportedError}\n`);
|
|
892
961
|
}
|
|
893
962
|
}
|
|
894
|
-
const reconcile = async () => {
|
|
963
|
+
const reconcile = async (signal) => {
|
|
895
964
|
if (closing || reconciling)
|
|
896
965
|
return;
|
|
897
966
|
reconciling = true;
|
|
967
|
+
const reconciliationFetch = signal
|
|
968
|
+
? (resource, init) => request(resource, { ...init, signal: init?.signal ? AbortSignal.any([signal, init.signal]) : signal })
|
|
969
|
+
: request;
|
|
898
970
|
try {
|
|
899
971
|
const activation = await activateRealPathIntegrations({
|
|
900
972
|
repository: input.repository,
|
|
901
973
|
server: input.server,
|
|
902
974
|
projectId: input.projectId,
|
|
903
975
|
apiKey: input.apiKey,
|
|
904
|
-
|
|
976
|
+
agentIdentity: input.config.agentIdentity ?? { externalId: input.config.connectionName, version: "" },
|
|
977
|
+
fetch: reconciliationFetch,
|
|
905
978
|
});
|
|
906
979
|
if (activation.state === "READY_TO_START") {
|
|
907
980
|
const configured = await activateManagedWorkflowHarness({
|
|
@@ -912,7 +985,13 @@ export async function createContinuousAssuranceController(input) {
|
|
|
912
985
|
});
|
|
913
986
|
await replaceHarness(configured.config);
|
|
914
987
|
}
|
|
915
|
-
|
|
988
|
+
else if (harnessHasRealPathBindings) {
|
|
989
|
+
await harness?.close();
|
|
990
|
+
harness = undefined;
|
|
991
|
+
harnessFingerprint = undefined;
|
|
992
|
+
harnessHasRealPathBindings = false;
|
|
993
|
+
}
|
|
994
|
+
await publishCurrentChangeManifests({ ...input, fetch: reconciliationFetch }, harness ? await harness.status() : undefined);
|
|
916
995
|
lastReportedError = undefined;
|
|
917
996
|
}
|
|
918
997
|
catch (error) {
|
|
@@ -925,6 +1004,10 @@ export async function createContinuousAssuranceController(input) {
|
|
|
925
1004
|
reconciling = false;
|
|
926
1005
|
}
|
|
927
1006
|
};
|
|
1007
|
+
// The collector sends its first signed heartbeat as soon as its server starts.
|
|
1008
|
+
// Resolve the exact Harness first so HTTP readiness cannot race that heartbeat.
|
|
1009
|
+
// A failed or timed-out lookup leaves cached provider bindings unstarted.
|
|
1010
|
+
await reconcile(AbortSignal.timeout(5_000));
|
|
928
1011
|
return {
|
|
929
1012
|
start() {
|
|
930
1013
|
if (timer || closing)
|
|
@@ -934,6 +1017,8 @@ export async function createContinuousAssuranceController(input) {
|
|
|
934
1017
|
timer.unref?.();
|
|
935
1018
|
},
|
|
936
1019
|
reconcile,
|
|
1020
|
+
wakeRuntimeWatch: () => { if (!closing)
|
|
1021
|
+
harness?.wakeRuntimeWatch(); },
|
|
937
1022
|
status: () => harness?.status() ?? Promise.resolve(undefined),
|
|
938
1023
|
async close() {
|
|
939
1024
|
closing = true;
|
|
@@ -1191,10 +1276,25 @@ export async function createConfiguredRuntimeActionWorker(input) {
|
|
|
1191
1276
|
},
|
|
1192
1277
|
store: new input.FileActionCheckpointStore(resolve(input.directory, "data", "runtime-actions", "checkpoints")),
|
|
1193
1278
|
hosted: {
|
|
1194
|
-
getAction: (actionId) =>
|
|
1279
|
+
getAction: async (actionId) => {
|
|
1280
|
+
const action = await primary(`actions/${encodeURIComponent(actionId)}`);
|
|
1281
|
+
if (action.status === "VERIFIED" && action.verificationSuccess === true && action.receiptId && Number(action.receiptSignatureCount) > 0)
|
|
1282
|
+
input.onReceipt?.();
|
|
1283
|
+
return action;
|
|
1284
|
+
},
|
|
1195
1285
|
issueExecutionGrant: (actionId, body, idempotencyKey) => primary(`actions/${encodeURIComponent(actionId)}/execution-grant`, { method: "POST", body, idempotencyKey }),
|
|
1196
|
-
verifyAction: (actionId, body, idempotencyKey) =>
|
|
1197
|
-
|
|
1286
|
+
verifyAction: async (actionId, body, idempotencyKey) => {
|
|
1287
|
+
const action = await verifier(`actions/${encodeURIComponent(actionId)}/verify`, { method: "POST", body, idempotencyKey });
|
|
1288
|
+
if (action.status === "VERIFIED" && action.verificationSuccess === true && action.receiptId && Number(action.receiptSignatureCount) > 0)
|
|
1289
|
+
input.onReceipt?.();
|
|
1290
|
+
return action;
|
|
1291
|
+
},
|
|
1292
|
+
listActionReceipts: async (actionId) => {
|
|
1293
|
+
const receipts = (await primary(`actions/${encodeURIComponent(actionId)}/receipts`)).receipts ?? [];
|
|
1294
|
+
if (receipts.some((receipt) => (receipt.receipt?.signatureSet?.length ?? 0) > 0))
|
|
1295
|
+
input.onReceipt?.();
|
|
1296
|
+
return receipts;
|
|
1297
|
+
},
|
|
1198
1298
|
claimExecutionGrant: (executionGrantId, claim, idempotencyKey) => claimHostedExecutionGrant(input.connection, requestFetch, executionGrantId, claim, idempotencyKey),
|
|
1199
1299
|
},
|
|
1200
1300
|
runtime: { reconcileReadOnly: true, prepareClaim: runtime.prepareClaim, execute: runtime.execute, reconcile: runtime.reconcile, submitEvidence: runtime.submitEvidence },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable-action-worker.d.ts","sourceRoot":"","sources":["../../../../agentcert-sdk/src/durable-action-worker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"durable-action-worker.d.ts","sourceRoot":"","sources":["../../../../agentcert-sdk/src/durable-action-worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { mkdir, open, readFile, readdir, rename } from "node:fs/promises";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
4
5
|
import { canonicalJson } from "./canonical.js";
|
|
5
6
|
export class FileActionCheckpointStore {
|
|
6
7
|
directory;
|
|
@@ -27,7 +28,22 @@ export class FileActionCheckpointStore {
|
|
|
27
28
|
finally {
|
|
28
29
|
await handle.close();
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
+
// Windows readers and scanners may briefly deny atomic replacement. Retry
|
|
32
|
+
// publication of this same synced file, never the action or its execution claim.
|
|
33
|
+
const retryDelaysMs = [10, 25, 50, 100, 200, 400];
|
|
34
|
+
for (let attempt = 0;; attempt++) {
|
|
35
|
+
try {
|
|
36
|
+
await rename(temporary, path);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
|
|
41
|
+
const retryDelay = retryDelaysMs[attempt];
|
|
42
|
+
if (retryDelay === undefined || (code !== "EPERM" && code !== "EACCES" && code !== "EBUSY"))
|
|
43
|
+
throw error;
|
|
44
|
+
await delay(retryDelay);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
31
47
|
}
|
|
32
48
|
async list() {
|
|
33
49
|
let names;
|
package/dist/onboard.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { access, mkdir, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { basename, dirname, join, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { credentialsPath,
|
|
5
|
+
import { credentialsPath, loadConnection, resolveOnboardServer, saveConnection } from "./credentials.js";
|
|
6
6
|
import { authorizeProjectConnection } from "./device-authorization.js";
|
|
7
7
|
import { verifyControlPlaneConnection } from "./control-plane.js";
|
|
8
8
|
import { inferPrivateCapabilities, runPrivateCapabilityDiscovery } from "./private-discovery.js";
|
|
@@ -17,7 +17,7 @@ import { runCustomerGatewayCommand } from "./gateway-exec.js";
|
|
|
17
17
|
export async function runOnboard(options) {
|
|
18
18
|
const requestFetch = options.fetch ?? fetch;
|
|
19
19
|
const output = options.output ?? ((message) => process.stdout.write(message));
|
|
20
|
-
const server =
|
|
20
|
+
const server = resolveOnboardServer(options);
|
|
21
21
|
const repositoryPath = resolve(options.repository ?? process.cwd());
|
|
22
22
|
const repository = await inspectRepository(repositoryPath, options.template);
|
|
23
23
|
const agentIdentity = {
|
|
@@ -249,7 +249,7 @@ export async function runOnboard(options) {
|
|
|
249
249
|
}
|
|
250
250
|
const runtimeConfigured = await gatewayHasRuntimeWorker(repositoryPath);
|
|
251
251
|
generatedFiles.push(...await generateAutopilotFiles(repositoryPath, repository.name, runtimeConfigured));
|
|
252
|
-
realPathActivation = await activateRealPathIntegrations({ repository: repositoryPath, server, projectId: token.projectId, apiKey: token.apiKey, env: options.env, fetch: requestFetch });
|
|
252
|
+
realPathActivation = await activateRealPathIntegrations({ repository: repositoryPath, server, projectId: token.projectId, apiKey: token.apiKey, agentIdentity, env: options.env, fetch: requestFetch });
|
|
253
253
|
generatedFiles.push(...realPathActivation.generatedFiles);
|
|
254
254
|
try {
|
|
255
255
|
const activation = await activateManagedWorkflowHarness({ repository: repositoryPath, realPathActivations: realPathActivation.activations, previousGeneratedModuleSha256: realPathActivation.previousGeneratedModuleSha256 });
|
|
@@ -352,6 +352,7 @@ export async function runOnboard(options) {
|
|
|
352
352
|
output(`Keep this command open for up to ${Math.max(1, Math.ceil((options.waitForActionPathMs ?? 0) / 60_000))} minutes. It will finish automatically after you confirm the Business Task in the browser; no second onboard command is required. Press Ctrl+C to pause safely.\n`);
|
|
353
353
|
const resolution = await waitForOnboardingResolution({
|
|
354
354
|
repository: repositoryPath, server, projectId: token.projectId, apiKey: token.apiKey,
|
|
355
|
+
agentIdentity,
|
|
355
356
|
env: options.env, fetch: requestFetch, sleep: options.sleep, timeoutMs: options.waitForActionPathMs ?? 0,
|
|
356
357
|
});
|
|
357
358
|
if (resolution?.kind === "LOCAL_OUTPUT") {
|
|
@@ -420,13 +421,14 @@ export async function runOnboard(options) {
|
|
|
420
421
|
output(`Action transport: ${actionTransportTest.transport.toUpperCase()} is waiting for one exact sandbox Task/action path. ${actionTransportTest.limitation}\n`);
|
|
421
422
|
}
|
|
422
423
|
output(localOutputTaskConfirmed
|
|
423
|
-
? "
|
|
424
|
+
? "Setup complete. Check this Agent's connection in the workspace; setup alone does not establish a live connection for this Agent, version, and environment. The approved read-only local-output task is confirmed; no external Action transport is required.\n"
|
|
424
425
|
: actionTransportTest?.state === "WAITING_FOR_ACTION_PATH"
|
|
425
426
|
? `Base Gateway connected, but ${actionTransportTest.transport.toUpperCase()} Action is not verified yet. Run the Agent once and confirm its Business Task in the browser. Recovery only: rerun this command if the original waiting process was closed.\n`
|
|
426
|
-
: "
|
|
427
|
+
: "Setup complete. Check this Agent's connection in the workspace; setup alone does not establish a live connection for this Agent, version, and environment. Run it normally to send source-signed activity.\n");
|
|
427
428
|
output(localWorkflowCommand
|
|
428
429
|
? `Local sandbox command: ${agentRunCommand}\n`
|
|
429
430
|
: `For a local sandbox workflow, use npx --yes witnora@${cliVersion} gateway exec -- <your normal sandbox command> so the Gateway token stays out of shell history.\n`);
|
|
431
|
+
output("To stop now: npx witnora@latest gateway stop. To remove automatic startup: npx witnora@latest gateway service uninstall. Run these in this Agent repository; saved credentials and evidence are retained.\n");
|
|
430
432
|
return { projectId: token.projectId, connectionName: token.connectionName, credentialsPath, template: repository.template,
|
|
431
433
|
repositoryKind: repository.kind, generatedFiles, receiptPath, discovery, setupPlanId: setupPlan.id,
|
|
432
434
|
gatewayDirectory: join(repositoryPath, ".witnora", "gateway"), gatewayArchiveDirectory: gatewayMigration?.archiveDirectory,
|
|
@@ -12,7 +12,28 @@ export async function activateRealPathIntegrations(options) {
|
|
|
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" || plan.status === "HARNESS_ACTIVE") : [];
|
|
15
|
-
|
|
15
|
+
let plans = approved.filter((plan) => plan.projectId === options.projectId && ["STRIPE_REFUND", "SHOPIFY_DISPUTE", "ZENDESK_TICKET", "SALESFORCE_RECORD", "HUBSPOT_CRM_RECORD", "POSTGRES_RECORD", "QUEUE_JOB"].includes(plan.generated.providerPackId) && plan.environment === "sandbox" && plan.customerSummary.evaluationMode === "SHADOW");
|
|
16
|
+
if (plans.length && options.agentIdentity) {
|
|
17
|
+
const identity = options.agentIdentity;
|
|
18
|
+
if (!identity.externalId || !identity.version)
|
|
19
|
+
plans = [];
|
|
20
|
+
else {
|
|
21
|
+
const setupResponse = await request(`${base}/v1/projects/${encodeURIComponent(options.projectId)}/setup-plans`, { method: "GET", headers: { authorization: `Bearer ${options.apiKey}` } });
|
|
22
|
+
if (!setupResponse.ok)
|
|
23
|
+
throw new Error(`Could not resolve this Agent's exact setup binding (${setupResponse.status}). No provider preflight was attempted.`);
|
|
24
|
+
const setup = await boundedJson(setupResponse);
|
|
25
|
+
const plan = setup.plan;
|
|
26
|
+
const connectedAgentId = plan?.autopilot?.install?.connectedAgentId;
|
|
27
|
+
// Autopilot credentials can read their own setup, not the workspace-wide
|
|
28
|
+
// Agent directory. Installation events bind the canonical ID to the exact
|
|
29
|
+
// locally observed identity; before that event, activation stays pending.
|
|
30
|
+
const matches = Array.isArray(setup.events) ? setup.events.filter((event) => event?.type === "execution_completed"
|
|
31
|
+
&& event.details?.connectedAgentExternalId === identity.externalId && event.details?.connectedAgentVersion === identity.version
|
|
32
|
+
&& typeof event.details?.connectedAgentId === "string" && (!connectedAgentId || event.details.connectedAgentId === connectedAgentId)) : [];
|
|
33
|
+
const ids = [...new Set(matches.map((event) => event.details.connectedAgentId))];
|
|
34
|
+
plans = ids.length === 1 ? plans.filter((integration) => integration.subject.agentId === ids[0] && integration.subject.agentVersion === identity.version) : [];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
16
37
|
if (!plans.length)
|
|
17
38
|
return { state: "NOT_CONFIGURED", created: false, activations: [], generatedFiles: [], rollback: async () => undefined };
|
|
18
39
|
const environment = options.env ?? process.env;
|
|
@@ -118,6 +118,7 @@ export declare class ManagedFailureRuntimeWatch {
|
|
|
118
118
|
checkpoints: FailureRuntimeWatchCheckpointStore;
|
|
119
119
|
intervalMs?: number;
|
|
120
120
|
now?: () => Date;
|
|
121
|
+
nextCheckAt?: () => string;
|
|
121
122
|
readOutcome: FailureRuntimeWatchOutcomeReader;
|
|
122
123
|
bindings?: Array<{
|
|
123
124
|
taskContractId: string;
|
|
@@ -126,6 +127,7 @@ export declare class ManagedFailureRuntimeWatch {
|
|
|
126
127
|
}>;
|
|
127
128
|
});
|
|
128
129
|
tick(): Promise<ManagedFailureRuntimeWatchResult>;
|
|
130
|
+
private nextCheckAt;
|
|
129
131
|
private runTick;
|
|
130
132
|
}
|
|
131
133
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failure-runtime-watch.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/failure-runtime-watch.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"failure-runtime-watch.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/failure-runtime-watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -77,6 +77,7 @@ export class ManagedFailureRuntimeWatch {
|
|
|
77
77
|
#checkpoints;
|
|
78
78
|
#intervalMs;
|
|
79
79
|
#now;
|
|
80
|
+
#scheduledCheck;
|
|
80
81
|
#readOutcome;
|
|
81
82
|
#bindings;
|
|
82
83
|
#activeTick;
|
|
@@ -85,6 +86,7 @@ export class ManagedFailureRuntimeWatch {
|
|
|
85
86
|
this.#checkpoints = options.checkpoints;
|
|
86
87
|
this.#intervalMs = options.intervalMs ?? 5_000;
|
|
87
88
|
this.#now = options.now ?? (() => new Date());
|
|
89
|
+
this.#scheduledCheck = options.nextCheckAt;
|
|
88
90
|
this.#readOutcome = options.readOutcome;
|
|
89
91
|
this.#bindings = options.bindings ? new Set(options.bindings.map(bindingKey)) : undefined;
|
|
90
92
|
if (!Number.isSafeInteger(this.#intervalMs) || this.#intervalMs < 1_000 || this.#intervalMs > 15 * 60_000) {
|
|
@@ -97,6 +99,10 @@ export class ManagedFailureRuntimeWatch {
|
|
|
97
99
|
this.#activeTick = this.runTick().finally(() => { this.#activeTick = undefined; });
|
|
98
100
|
return this.#activeTick;
|
|
99
101
|
}
|
|
102
|
+
nextCheckAt(checkedAt) {
|
|
103
|
+
const scheduled = this.#scheduledCheck?.();
|
|
104
|
+
return scheduled ?? new Date(Date.parse(checkedAt) + this.#intervalMs).toISOString();
|
|
105
|
+
}
|
|
100
106
|
async runTick() {
|
|
101
107
|
const failureCases = await this.#client.listFailureCases();
|
|
102
108
|
const candidates = failureCases.filter((failureCase) => failureCase.definition.environment === "sandbox"
|
|
@@ -126,7 +132,7 @@ export class ManagedFailureRuntimeWatch {
|
|
|
126
132
|
return this.#client.updateStatus(failureCase.id, {
|
|
127
133
|
health: "CONNECTION_UNAVAILABLE",
|
|
128
134
|
lastCheckedAt: checkedAt,
|
|
129
|
-
nextCheckAt:
|
|
135
|
+
nextCheckAt: this.nextCheckAt(checkedAt),
|
|
130
136
|
detail,
|
|
131
137
|
});
|
|
132
138
|
}));
|
|
@@ -142,7 +148,7 @@ export class ManagedFailureRuntimeWatch {
|
|
|
142
148
|
return this.#client.updateStatus(failureCase.id, {
|
|
143
149
|
health: "INSUFFICIENT_EVIDENCE",
|
|
144
150
|
lastCheckedAt: checkedAt,
|
|
145
|
-
nextCheckAt:
|
|
151
|
+
nextCheckAt: this.nextCheckAt(checkedAt),
|
|
146
152
|
detail,
|
|
147
153
|
});
|
|
148
154
|
}));
|
|
@@ -156,9 +162,8 @@ export class ManagedFailureRuntimeWatch {
|
|
|
156
162
|
const limitations = [];
|
|
157
163
|
for (const failureCase of eligible) {
|
|
158
164
|
const checkedAt = this.#now().toISOString();
|
|
159
|
-
const nextCheckAt = new Date(Date.parse(checkedAt) + this.#intervalMs).toISOString();
|
|
160
165
|
const storedCheckpoint = await this.#checkpoints.load(failureCase.id);
|
|
161
|
-
|
|
166
|
+
let checkpoint = storedCheckpoint ?? {
|
|
162
167
|
processedReceiptIds: failureCase.runtimeWatch?.receiptIds ?? failureCase.runtimeWatch?.latest?.receiptIds ?? [],
|
|
163
168
|
updatedAt: checkedAt,
|
|
164
169
|
};
|
|
@@ -168,75 +173,87 @@ export class ManagedFailureRuntimeWatch {
|
|
|
168
173
|
await this.#client.updateStatus(failureCase.id, {
|
|
169
174
|
health: failureCase.status === "REGRESSION_DETECTED" ? "REGRESSION" : "HEALTHY",
|
|
170
175
|
lastCheckedAt: checkedAt,
|
|
171
|
-
nextCheckAt,
|
|
176
|
+
nextCheckAt: this.nextCheckAt(checkedAt),
|
|
172
177
|
});
|
|
173
178
|
if (!storedCheckpoint)
|
|
174
179
|
await this.#checkpoints.save(failureCase.id, checkpoint);
|
|
175
180
|
continue;
|
|
176
181
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
await this.#client.updateStatus(failureCase.id, {
|
|
189
|
-
health: outcome.classification === "SCHEMA_DIGEST_DRIFT" ? "INSUFFICIENT_EVIDENCE" : outcome.classification,
|
|
190
|
-
lastCheckedAt: checkedAt,
|
|
191
|
-
nextCheckAt,
|
|
192
|
-
...(outcome.reason ? { detail: outcome.reason } : {}),
|
|
182
|
+
// One wake can represent several resources. Drain that snapshot in order
|
|
183
|
+
// so a coalesced Receipt does not have to wait for the periodic fallback.
|
|
184
|
+
let batchStatus = { health: "HEALTHY" };
|
|
185
|
+
for (const resourceId of unique(pending.map((item) => item.resourceId))) {
|
|
186
|
+
const checkedAt = this.#now().toISOString();
|
|
187
|
+
const group = covered.filter((item) => item.resourceId === resourceId);
|
|
188
|
+
const outcome = await this.#readOutcome({
|
|
189
|
+
failureCase,
|
|
190
|
+
resourceId,
|
|
191
|
+
actions: group.map((item) => item.action),
|
|
192
|
+
receipts: group.map((item) => item.receipt),
|
|
193
193
|
});
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
: "A covered sandbox result remained healthy after the candidate was verified.",
|
|
220
|
-
measurements: {
|
|
194
|
+
if (outcome.classification !== "HEALTHY" && outcome.classification !== "REGRESSION") {
|
|
195
|
+
outcomesDeferred += 1;
|
|
196
|
+
limitations.push(outcome.reason ?? `Failure Runtime Watch deferred ${failureCase.id}: ${outcome.classification}.`);
|
|
197
|
+
if (batchStatus.health !== "REGRESSION")
|
|
198
|
+
batchStatus = {
|
|
199
|
+
health: outcome.classification === "SCHEMA_DIGEST_DRIFT" ? "INSUFFICIENT_EVIDENCE" : outcome.classification,
|
|
200
|
+
...(outcome.reason ? { detail: outcome.reason } : {}),
|
|
201
|
+
};
|
|
202
|
+
await this.#client.updateStatus(failureCase.id, {
|
|
203
|
+
...batchStatus,
|
|
204
|
+
lastCheckedAt: checkedAt,
|
|
205
|
+
nextCheckAt: this.nextCheckAt(checkedAt),
|
|
206
|
+
});
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const receiptIds = group.map((item) => item.receipt.id);
|
|
210
|
+
const agentVersion = requiredAgentVersion(failureCase, group.map((item) => item.action));
|
|
211
|
+
await this.#client.uploadObservation({
|
|
212
|
+
discoveryKey: failureCase.discovery?.discoveryKey ?? failureCase.id,
|
|
213
|
+
phase: "RUNTIME",
|
|
214
|
+
observedAt: outcome.observedAt,
|
|
215
|
+
definition: structuredClone(failureCase.definition),
|
|
216
|
+
result: {
|
|
217
|
+
agentVersion,
|
|
218
|
+
attempts: outcome.attempts ?? group.length,
|
|
221
219
|
providerCommitCount: outcome.providerCommitCount ?? 0,
|
|
222
220
|
duplicateOutcomeCount: outcome.duplicateOutcomeCount ?? 0,
|
|
223
221
|
failureCount: outcome.failureCount ?? 0,
|
|
224
222
|
hardInvariantViolations: outcome.hardInvariantViolations ?? 0,
|
|
225
|
-
|
|
223
|
+
observation: "RECORDED",
|
|
224
|
+
executionControl: "ENFORCED",
|
|
225
|
+
outcome: "VERIFIED",
|
|
226
|
+
review: "NOT_REVIEWED",
|
|
227
|
+
receiptIds,
|
|
226
228
|
},
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
229
|
+
evidence: {
|
|
230
|
+
summary: outcome.classification === "REGRESSION"
|
|
231
|
+
? "A covered sandbox result reproduced the defined failure after the candidate was verified."
|
|
232
|
+
: "A covered sandbox result remained healthy after the candidate was verified.",
|
|
233
|
+
measurements: {
|
|
234
|
+
providerCommitCount: outcome.providerCommitCount ?? 0,
|
|
235
|
+
duplicateOutcomeCount: outcome.duplicateOutcomeCount ?? 0,
|
|
236
|
+
failureCount: outcome.failureCount ?? 0,
|
|
237
|
+
hardInvariantViolations: outcome.hardInvariantViolations ?? 0,
|
|
238
|
+
receiptCount: receiptIds.length,
|
|
239
|
+
},
|
|
240
|
+
limitations: ["This automated observation covers the exact customer-owned sandbox task and action path only; it does not establish production reliability."],
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
observationsUploaded += 1;
|
|
244
|
+
if (outcome.classification === "REGRESSION")
|
|
245
|
+
batchStatus = { health: "REGRESSION" };
|
|
246
|
+
await this.#client.updateStatus(failureCase.id, {
|
|
247
|
+
...batchStatus,
|
|
248
|
+
lastCheckedAt: checkedAt,
|
|
249
|
+
nextCheckAt: this.nextCheckAt(checkedAt),
|
|
250
|
+
});
|
|
251
|
+
checkpoint = {
|
|
252
|
+
processedReceiptIds: unique([...checkpoint.processedReceiptIds, ...receiptIds]),
|
|
253
|
+
updatedAt: checkedAt,
|
|
254
|
+
};
|
|
255
|
+
await this.#checkpoints.save(failureCase.id, checkpoint);
|
|
256
|
+
}
|
|
240
257
|
}
|
|
241
258
|
return { casesInspected: eligible.length, observationsUploaded, outcomesDeferred, limitations };
|
|
242
259
|
}
|