@synth-deploy/server 1.0.6 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/envoy-client.d.ts +65 -15
- package/dist/agent/envoy-client.d.ts.map +1 -1
- package/dist/agent/envoy-client.js +58 -8
- package/dist/agent/envoy-client.js.map +1 -1
- package/dist/agent/stale-deployment-detector.js +1 -1
- package/dist/agent/stale-deployment-detector.js.map +1 -1
- package/dist/agent/synth-agent.d.ts +7 -5
- package/dist/agent/synth-agent.d.ts.map +1 -1
- package/dist/agent/synth-agent.js +59 -50
- package/dist/agent/synth-agent.js.map +1 -1
- package/dist/alert-webhooks/alert-parsers.d.ts +21 -0
- package/dist/alert-webhooks/alert-parsers.d.ts.map +1 -0
- package/dist/alert-webhooks/alert-parsers.js +184 -0
- package/dist/alert-webhooks/alert-parsers.js.map +1 -0
- package/dist/api/agent.d.ts +0 -6
- package/dist/api/agent.d.ts.map +1 -1
- package/dist/api/agent.js +6 -459
- package/dist/api/agent.js.map +1 -1
- package/dist/api/alert-webhooks.d.ts +13 -0
- package/dist/api/alert-webhooks.d.ts.map +1 -0
- package/dist/api/alert-webhooks.js +279 -0
- package/dist/api/alert-webhooks.js.map +1 -0
- package/dist/api/envoy-reports.js +2 -2
- package/dist/api/envoy-reports.js.map +1 -1
- package/dist/api/envoys.js +1 -1
- package/dist/api/envoys.js.map +1 -1
- package/dist/api/fleet.d.ts.map +1 -1
- package/dist/api/fleet.js +14 -15
- package/dist/api/fleet.js.map +1 -1
- package/dist/api/graph.js +3 -3
- package/dist/api/graph.js.map +1 -1
- package/dist/api/operations.d.ts +7 -0
- package/dist/api/operations.d.ts.map +1 -0
- package/dist/api/operations.js +1900 -0
- package/dist/api/operations.js.map +1 -0
- package/dist/api/partitions.js +1 -1
- package/dist/api/partitions.js.map +1 -1
- package/dist/api/schemas.d.ts +434 -133
- package/dist/api/schemas.d.ts.map +1 -1
- package/dist/api/schemas.js +53 -25
- package/dist/api/schemas.js.map +1 -1
- package/dist/api/system.d.ts.map +1 -1
- package/dist/api/system.js +22 -21
- package/dist/api/system.js.map +1 -1
- package/dist/artifact-analyzer.js +2 -2
- package/dist/artifact-analyzer.js.map +1 -1
- package/dist/fleet/fleet-executor.js +3 -3
- package/dist/fleet/fleet-executor.js.map +1 -1
- package/dist/graph/graph-executor.d.ts.map +1 -1
- package/dist/graph/graph-executor.js +18 -4
- package/dist/graph/graph-executor.js.map +1 -1
- package/dist/index.js +89 -61
- package/dist/index.js.map +1 -1
- package/dist/mcp/resources.js +3 -3
- package/dist/mcp/resources.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +2 -9
- package/dist/mcp/tools.js.map +1 -1
- package/dist/middleware/auth.js +1 -1
- package/dist/middleware/auth.js.map +1 -1
- package/package.json +1 -1
- package/src/agent/envoy-client.ts +111 -19
- package/src/agent/stale-deployment-detector.ts +1 -1
- package/src/agent/synth-agent.ts +76 -56
- package/src/alert-webhooks/alert-parsers.ts +291 -0
- package/src/api/agent.ts +9 -528
- package/src/api/alert-webhooks.ts +354 -0
- package/src/api/envoy-reports.ts +2 -2
- package/src/api/envoys.ts +1 -1
- package/src/api/fleet.ts +14 -15
- package/src/api/graph.ts +3 -3
- package/src/api/operations.ts +2260 -0
- package/src/api/partitions.ts +1 -1
- package/src/api/schemas.ts +59 -27
- package/src/api/system.ts +23 -21
- package/src/artifact-analyzer.ts +2 -2
- package/src/fleet/fleet-executor.ts +3 -3
- package/src/graph/graph-executor.ts +18 -4
- package/src/index.ts +91 -61
- package/src/mcp/resources.ts +3 -3
- package/src/mcp/tools.ts +5 -9
- package/src/middleware/auth.ts +1 -1
- package/tests/agent-mode.test.ts +5 -376
- package/tests/api-handlers.test.ts +27 -27
- package/tests/composite-operations.test.ts +557 -0
- package/tests/decision-diary.test.ts +62 -63
- package/tests/diary-reader.test.ts +14 -18
- package/tests/mcp-tools.test.ts +1 -1
- package/tests/orchestration.test.ts +34 -30
- package/tests/partition-isolation.test.ts +4 -9
- package/tests/rbac-enforcement.test.ts +8 -8
- package/tests/ui-journey.test.ts +9 -9
- package/dist/api/deployments.d.ts +0 -11
- package/dist/api/deployments.d.ts.map +0 -1
- package/dist/api/deployments.js +0 -1098
- package/dist/api/deployments.js.map +0 -1
- package/src/api/deployments.ts +0 -1347
package/src/agent/synth-agent.ts
CHANGED
|
@@ -2,7 +2,8 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import type {
|
|
3
3
|
Deployment,
|
|
4
4
|
DeploymentId,
|
|
5
|
-
|
|
5
|
+
OperationInput,
|
|
6
|
+
OperationTrigger,
|
|
6
7
|
DebriefWriter,
|
|
7
8
|
Environment,
|
|
8
9
|
Partition,
|
|
@@ -25,7 +26,7 @@ import { serverLog, serverError } from "../logger.js";
|
|
|
25
26
|
// Public interfaces
|
|
26
27
|
// ---------------------------------------------------------------------------
|
|
27
28
|
|
|
28
|
-
export interface
|
|
29
|
+
export interface OperationStore {
|
|
29
30
|
save(deployment: Deployment): void;
|
|
30
31
|
get(id: DeploymentId): Deployment | undefined;
|
|
31
32
|
getByPartition(partitionId: string): Deployment[];
|
|
@@ -36,6 +37,8 @@ export interface DeploymentStore {
|
|
|
36
37
|
findRecentByArtifact(artifactId: string, since: Date, status?: string): Deployment[];
|
|
37
38
|
findLatestByEnvironment(envId: string): Deployment | undefined;
|
|
38
39
|
}
|
|
40
|
+
/** @deprecated Use OperationStore */
|
|
41
|
+
export type DeploymentStore = OperationStore;
|
|
39
42
|
|
|
40
43
|
export interface AgentOptions {
|
|
41
44
|
/** Number of health check retries after initial failure. Default: 1 */
|
|
@@ -172,7 +175,7 @@ export class SynthAgent {
|
|
|
172
175
|
|
|
173
176
|
constructor(
|
|
174
177
|
private debrief: DebriefWriter,
|
|
175
|
-
private deployments:
|
|
178
|
+
private deployments: OperationStore,
|
|
176
179
|
private artifactStore: IArtifactStore,
|
|
177
180
|
private environmentStore: IEnvironmentStore,
|
|
178
181
|
private partitionStore: IPartitionStore,
|
|
@@ -217,14 +220,23 @@ export class SynthAgent {
|
|
|
217
220
|
// Main entry point
|
|
218
221
|
// -----------------------------------------------------------------------
|
|
219
222
|
|
|
220
|
-
async
|
|
221
|
-
|
|
223
|
+
async triggerOperation(
|
|
224
|
+
input: OperationInput,
|
|
225
|
+
trigger: OperationTrigger,
|
|
222
226
|
): Promise<Deployment> {
|
|
227
|
+
if (input.type !== "deploy") {
|
|
228
|
+
throw new OrchestrationError(
|
|
229
|
+
"resolve-entities",
|
|
230
|
+
`Operation type "${input.type}" is not supported via programmatic triggers`,
|
|
231
|
+
`"query" and "investigate" operations run through the REST API path (web UI), not programmatic triggers. Only "deploy" is supported via triggerOperation().`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
223
235
|
const deploymentId = crypto.randomUUID();
|
|
224
236
|
|
|
225
237
|
// --- Look up entities from stores -----------------------------------------------
|
|
226
238
|
|
|
227
|
-
serverLog("DEPLOY-TRIGGER", { deploymentId, artifactId:
|
|
239
|
+
serverLog("DEPLOY-TRIGGER", { operationId: deploymentId, artifactId: input.artifactId, environmentId: trigger.environmentId, partitionId: trigger.partitionId ?? null, triggeredBy: trigger.triggeredBy });
|
|
228
240
|
|
|
229
241
|
const environment = this.environmentStore.get(trigger.environmentId);
|
|
230
242
|
if (!environment) {
|
|
@@ -249,12 +261,12 @@ export class SynthAgent {
|
|
|
249
261
|
}
|
|
250
262
|
}
|
|
251
263
|
|
|
252
|
-
const artifact = this.artifactStore.get(
|
|
264
|
+
const artifact = this.artifactStore.get(input.artifactId);
|
|
253
265
|
if (!artifact) {
|
|
254
266
|
throw new OrchestrationError(
|
|
255
267
|
"resolve-entities",
|
|
256
|
-
`Artifact not found: ${
|
|
257
|
-
`The trigger references artifact ID "${
|
|
268
|
+
`Artifact not found: ${input.artifactId}`,
|
|
269
|
+
`The trigger references artifact ID "${input.artifactId}" which does not exist in the artifact store. ` +
|
|
258
270
|
`Verify the artifact ID is correct and the artifact has been created.`,
|
|
259
271
|
);
|
|
260
272
|
}
|
|
@@ -275,7 +287,7 @@ export class SynthAgent {
|
|
|
275
287
|
|
|
276
288
|
const analysisEntry = this.debrief.record({
|
|
277
289
|
partitionId: trigger.partitionId ?? null,
|
|
278
|
-
deploymentId,
|
|
290
|
+
operationId: deploymentId,
|
|
279
291
|
agent: "server",
|
|
280
292
|
decisionType: "artifact-analysis",
|
|
281
293
|
decision: `Analyzed artifact "${artifact.name}" (${artifact.type}) — confidence ${artifact.analysis.confidence}`,
|
|
@@ -299,7 +311,7 @@ export class SynthAgent {
|
|
|
299
311
|
|
|
300
312
|
// --- Step 1: Plan the pipeline -----------------------------------------
|
|
301
313
|
|
|
302
|
-
const version =
|
|
314
|
+
const version = input.artifactVersionId ?? "latest";
|
|
303
315
|
const pipelineSteps = [
|
|
304
316
|
"resolve-configuration",
|
|
305
317
|
"preflight-health-check",
|
|
@@ -309,7 +321,7 @@ export class SynthAgent {
|
|
|
309
321
|
|
|
310
322
|
const planEntry = this.debrief.record({
|
|
311
323
|
partitionId: trigger.partitionId ?? null,
|
|
312
|
-
deploymentId,
|
|
324
|
+
operationId: deploymentId,
|
|
313
325
|
agent: "server",
|
|
314
326
|
decisionType: "pipeline-plan",
|
|
315
327
|
decision: `Planned deployment pipeline: ${pipelineSteps.join(" → ")}`,
|
|
@@ -333,15 +345,21 @@ export class SynthAgent {
|
|
|
333
345
|
|
|
334
346
|
// Initial plan — the Envoy generates the real deployment plan during execution
|
|
335
347
|
const initialPlan = {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
348
|
+
scriptedPlan: {
|
|
349
|
+
platform: "bash" as const,
|
|
350
|
+
executionScript: `echo "Placeholder — envoy will generate the real plan"`,
|
|
351
|
+
dryRunScript: null,
|
|
352
|
+
rollbackScript: null,
|
|
353
|
+
reasoning: `Initial plan for "${artifact.name}". ` +
|
|
354
|
+
`Deployment intent: ${artifact.analysis.deploymentIntent ?? "standard deployment"}. ` +
|
|
355
|
+
`The Envoy will generate a detailed execution plan based on artifact analysis and environment state.`,
|
|
356
|
+
stepSummary: [
|
|
357
|
+
{
|
|
358
|
+
description: `Deploy ${artifact.name} v${version}`,
|
|
359
|
+
reversible: true,
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
},
|
|
345
363
|
reasoning: `Initial plan for "${artifact.name}". ` +
|
|
346
364
|
`Deployment intent: ${artifact.analysis.deploymentIntent ?? "standard deployment"}. ` +
|
|
347
365
|
`The Envoy will generate a detailed execution plan based on artifact analysis and environment state.`,
|
|
@@ -349,13 +367,13 @@ export class SynthAgent {
|
|
|
349
367
|
|
|
350
368
|
const planGenEntry = this.debrief.record({
|
|
351
369
|
partitionId: trigger.partitionId ?? null,
|
|
352
|
-
deploymentId,
|
|
370
|
+
operationId: deploymentId,
|
|
353
371
|
agent: "server",
|
|
354
372
|
decisionType: "plan-generation",
|
|
355
|
-
decision: `Generated deployment plan for "${artifact.name}" v${version} — ${initialPlan.
|
|
373
|
+
decision: `Generated deployment plan for "${artifact.name}" v${version} — ${initialPlan.scriptedPlan.stepSummary.length} step(s)`,
|
|
356
374
|
reasoning: initialPlan.reasoning,
|
|
357
375
|
context: {
|
|
358
|
-
stepCount: initialPlan.
|
|
376
|
+
stepCount: initialPlan.scriptedPlan.stepSummary.length,
|
|
359
377
|
artifactName: artifact.name,
|
|
360
378
|
version,
|
|
361
379
|
},
|
|
@@ -363,7 +381,7 @@ export class SynthAgent {
|
|
|
363
381
|
|
|
364
382
|
const approvalEntry = this.debrief.record({
|
|
365
383
|
partitionId: trigger.partitionId ?? null,
|
|
366
|
-
deploymentId,
|
|
384
|
+
operationId: deploymentId,
|
|
367
385
|
agent: "server",
|
|
368
386
|
decisionType: "plan-approval",
|
|
369
387
|
decision: `Auto-approved deployment plan for "${artifact.name}" v${version}`,
|
|
@@ -378,8 +396,7 @@ export class SynthAgent {
|
|
|
378
396
|
|
|
379
397
|
const deployment: Deployment = {
|
|
380
398
|
id: deploymentId,
|
|
381
|
-
|
|
382
|
-
artifactVersionId: trigger.artifactVersionId,
|
|
399
|
+
input,
|
|
383
400
|
environmentId: trigger.environmentId,
|
|
384
401
|
partitionId: trigger.partitionId,
|
|
385
402
|
version,
|
|
@@ -397,7 +414,7 @@ export class SynthAgent {
|
|
|
397
414
|
try {
|
|
398
415
|
// --- Step 2: Resolve configuration -----------------------------------
|
|
399
416
|
|
|
400
|
-
serverLog("DEPLOY-CONFIG-RESOLVE", {
|
|
417
|
+
serverLog("DEPLOY-CONFIG-RESOLVE", { operationId: deployment.id });
|
|
401
418
|
const { variables, hasConflicts } = this.resolveConfiguration(
|
|
402
419
|
deployment,
|
|
403
420
|
trigger.variables,
|
|
@@ -411,13 +428,13 @@ export class SynthAgent {
|
|
|
411
428
|
|
|
412
429
|
deployment.status = "running";
|
|
413
430
|
this.deployments.save(deployment);
|
|
414
|
-
serverLog("DEPLOY-HEALTH-CHECK", {
|
|
431
|
+
serverLog("DEPLOY-HEALTH-CHECK", { operationId: deployment.id, environment: environment.name });
|
|
415
432
|
|
|
416
433
|
await this.preflightHealthCheck(deployment, partition, environment, artifact);
|
|
417
434
|
|
|
418
435
|
// --- Step 4: Execute deployment ----------------------------------------
|
|
419
436
|
|
|
420
|
-
serverLog("DEPLOY-EXECUTE", {
|
|
437
|
+
serverLog("DEPLOY-EXECUTE", { operationId: deployment.id, artifact: artifact.name, version: deployment.version, environment: environment.name });
|
|
421
438
|
const delegated = await this.executeDeployment(deployment, partition, environment, artifact);
|
|
422
439
|
|
|
423
440
|
// --- Step 5: Post-deploy verify ----------------------------------------
|
|
@@ -433,11 +450,11 @@ export class SynthAgent {
|
|
|
433
450
|
|
|
434
451
|
deployment.status = "succeeded";
|
|
435
452
|
deployment.completedAt = new Date();
|
|
436
|
-
serverLog("DEPLOY-SUCCEEDED", {
|
|
453
|
+
serverLog("DEPLOY-SUCCEEDED", { operationId: deployment.id, artifact: artifact.name, version: deployment.version, environment: environment.name, durationMs: deployment.completedAt.getTime() - deployment.createdAt.getTime() });
|
|
437
454
|
|
|
438
455
|
const completionEntry = this.debrief.record({
|
|
439
456
|
partitionId: deployment.partitionId ?? null,
|
|
440
|
-
|
|
457
|
+
operationId: deployment.id,
|
|
441
458
|
agent: "server",
|
|
442
459
|
decisionType: "deployment-completion",
|
|
443
460
|
decision: `Marking deployment of ${artifact.name} v${deployment.version} as succeeded on "${environment.name}"`,
|
|
@@ -465,11 +482,11 @@ export class SynthAgent {
|
|
|
465
482
|
error instanceof OrchestrationError
|
|
466
483
|
? error.message
|
|
467
484
|
: `Unexpected error: ${error instanceof Error ? error.message : String(error)}`;
|
|
468
|
-
serverError("DEPLOY-FAILED", {
|
|
485
|
+
serverError("DEPLOY-FAILED", { operationId: deployment.id, reason: deployment.failureReason, durationMs: deployment.completedAt.getTime() - deployment.createdAt.getTime() });
|
|
469
486
|
|
|
470
487
|
const failEntry = this.debrief.record({
|
|
471
488
|
partitionId: deployment.partitionId ?? null,
|
|
472
|
-
|
|
489
|
+
operationId: deployment.id,
|
|
473
490
|
agent: "server",
|
|
474
491
|
decisionType: "deployment-failure",
|
|
475
492
|
decision: `Deployment failed: ${deployment.failureReason}`,
|
|
@@ -532,7 +549,7 @@ export class SynthAgent {
|
|
|
532
549
|
|
|
533
550
|
this.debrief.record({
|
|
534
551
|
partitionId,
|
|
535
|
-
|
|
552
|
+
operationId: null,
|
|
536
553
|
agent: "server",
|
|
537
554
|
decisionType: "diagnostic-investigation",
|
|
538
555
|
decision: `${tools.length} external tool(s) available from ${connectedServers.length} MCP server(s)`,
|
|
@@ -557,7 +574,7 @@ export class SynthAgent {
|
|
|
557
574
|
// Never let external checks block the deployment
|
|
558
575
|
this.debrief.record({
|
|
559
576
|
partitionId,
|
|
560
|
-
|
|
577
|
+
operationId: null,
|
|
561
578
|
agent: "server",
|
|
562
579
|
decisionType: "diagnostic-investigation",
|
|
563
580
|
decision: "External MCP check failed — proceeding without external intelligence",
|
|
@@ -648,7 +665,7 @@ export class SynthAgent {
|
|
|
648
665
|
const partitionVarCount = partition ? Object.keys(partition.variables).length : 0;
|
|
649
666
|
const configEntry = this.debrief.record({
|
|
650
667
|
partitionId: deployment.partitionId ?? null,
|
|
651
|
-
|
|
668
|
+
operationId: deployment.id,
|
|
652
669
|
agent: "server",
|
|
653
670
|
decisionType: "configuration-resolved",
|
|
654
671
|
decision:
|
|
@@ -828,7 +845,7 @@ export class SynthAgent {
|
|
|
828
845
|
if (crossEnvConn) {
|
|
829
846
|
const entry = this.debrief.record({
|
|
830
847
|
partitionId: deployment.partitionId ?? null,
|
|
831
|
-
|
|
848
|
+
operationId: deployment.id,
|
|
832
849
|
agent: "server",
|
|
833
850
|
decisionType: "variable-conflict",
|
|
834
851
|
decision:
|
|
@@ -859,7 +876,7 @@ export class SynthAgent {
|
|
|
859
876
|
.join("; ");
|
|
860
877
|
const entry = this.debrief.record({
|
|
861
878
|
partitionId: deployment.partitionId ?? null,
|
|
862
|
-
|
|
879
|
+
operationId: deployment.id,
|
|
863
880
|
agent: "server",
|
|
864
881
|
decisionType: "variable-conflict",
|
|
865
882
|
decision: `Cross-environment variable pattern in ${crossEnv.length} non-connectivity variable(s)`,
|
|
@@ -884,7 +901,7 @@ export class SynthAgent {
|
|
|
884
901
|
if (sensitiveDetails) {
|
|
885
902
|
const entry = this.debrief.record({
|
|
886
903
|
partitionId: deployment.partitionId ?? null,
|
|
887
|
-
|
|
904
|
+
operationId: deployment.id,
|
|
888
905
|
agent: "server",
|
|
889
906
|
decisionType: "variable-conflict",
|
|
890
907
|
decision: `Security-sensitive variable(s) overridden: ${sensitiveDetails.map((d) => d.conflict.variable).join(", ")}`,
|
|
@@ -919,7 +936,7 @@ export class SynthAgent {
|
|
|
919
936
|
.join("; ");
|
|
920
937
|
const entry = this.debrief.record({
|
|
921
938
|
partitionId: deployment.partitionId ?? null,
|
|
922
|
-
|
|
939
|
+
operationId: deployment.id,
|
|
923
940
|
agent: "server",
|
|
924
941
|
decisionType: "variable-conflict",
|
|
925
942
|
decision: `Resolved ${standardDetails.length} variable conflict(s) via precedence rules`,
|
|
@@ -993,7 +1010,7 @@ export class SynthAgent {
|
|
|
993
1010
|
if (firstCheck.reachable) {
|
|
994
1011
|
const entry = this.debrief.record({
|
|
995
1012
|
partitionId: deployment.partitionId ?? null,
|
|
996
|
-
|
|
1013
|
+
operationId: deployment.id,
|
|
997
1014
|
agent: "server",
|
|
998
1015
|
decisionType: "health-check",
|
|
999
1016
|
decision: `Proceeding with deployment — target environment "${environment.name}" confirmed healthy in ${firstCheck.responseTimeMs}ms`,
|
|
@@ -1025,7 +1042,7 @@ export class SynthAgent {
|
|
|
1025
1042
|
// Reasoning determined retrying won't help (e.g., DNS failure)
|
|
1026
1043
|
const abortEntry = this.debrief.record({
|
|
1027
1044
|
partitionId: deployment.partitionId ?? null,
|
|
1028
|
-
|
|
1045
|
+
operationId: deployment.id,
|
|
1029
1046
|
agent: "server",
|
|
1030
1047
|
decisionType: "health-check",
|
|
1031
1048
|
decision: "Pre-flight health check failed — aborting without retry",
|
|
@@ -1050,7 +1067,7 @@ export class SynthAgent {
|
|
|
1050
1067
|
// Decision is to retry
|
|
1051
1068
|
const retryEntry = this.debrief.record({
|
|
1052
1069
|
partitionId: deployment.partitionId ?? null,
|
|
1053
|
-
|
|
1070
|
+
operationId: deployment.id,
|
|
1054
1071
|
agent: "server",
|
|
1055
1072
|
decisionType: "health-check",
|
|
1056
1073
|
decision: "Pre-flight health check failed — attempting retry",
|
|
@@ -1079,7 +1096,7 @@ export class SynthAgent {
|
|
|
1079
1096
|
if (retryCheck.reachable) {
|
|
1080
1097
|
const recoveryEntry = this.debrief.record({
|
|
1081
1098
|
partitionId: deployment.partitionId ?? null,
|
|
1082
|
-
|
|
1099
|
+
operationId: deployment.id,
|
|
1083
1100
|
agent: "server",
|
|
1084
1101
|
decisionType: "health-check",
|
|
1085
1102
|
decision:
|
|
@@ -1297,7 +1314,7 @@ export class SynthAgent {
|
|
|
1297
1314
|
// No settingsReader configured — execution skipped (test/offline environment)
|
|
1298
1315
|
const execEntry = this.debrief.record({
|
|
1299
1316
|
partitionId: deployment.partitionId ?? null,
|
|
1300
|
-
|
|
1317
|
+
operationId: deployment.id,
|
|
1301
1318
|
agent: "server",
|
|
1302
1319
|
decisionType: "deployment-execution",
|
|
1303
1320
|
decision: `Skipped Envoy delegation for ${artifact.name} v${deployment.version} — no settings reader configured`,
|
|
@@ -1355,7 +1372,7 @@ export class SynthAgent {
|
|
|
1355
1372
|
// Envoy is healthy — delegate the deployment
|
|
1356
1373
|
const delegateEntry = this.debrief.record({
|
|
1357
1374
|
partitionId: deployment.partitionId ?? null,
|
|
1358
|
-
|
|
1375
|
+
operationId: deployment.id,
|
|
1359
1376
|
agent: "server",
|
|
1360
1377
|
decisionType: "deployment-execution",
|
|
1361
1378
|
decision: `Delegating execution of ${artifact.name} v${deployment.version} to Envoy at ${envoyConfig.url}`,
|
|
@@ -1382,10 +1399,10 @@ export class SynthAgent {
|
|
|
1382
1399
|
|
|
1383
1400
|
envoyResult = await client.deploy({
|
|
1384
1401
|
deploymentId: deployment.id,
|
|
1402
|
+
operationId: deployment.id,
|
|
1385
1403
|
partitionId: deployment.partitionId ?? "",
|
|
1386
1404
|
environmentId: deployment.environmentId ?? "",
|
|
1387
|
-
|
|
1388
|
-
version: deployment.version,
|
|
1405
|
+
version: deployment.version ?? "",
|
|
1389
1406
|
variables: deployment.variables,
|
|
1390
1407
|
environmentName: environment.name,
|
|
1391
1408
|
partitionName: partition?.name ?? "",
|
|
@@ -1407,7 +1424,7 @@ export class SynthAgent {
|
|
|
1407
1424
|
for (const entry of envoyResult.debriefEntries) {
|
|
1408
1425
|
const ingested = this.debrief.record({
|
|
1409
1426
|
partitionId: entry.partitionId ?? deployment.partitionId ?? null,
|
|
1410
|
-
|
|
1427
|
+
operationId: entry.operationId ?? deployment.id,
|
|
1411
1428
|
agent: entry.agent,
|
|
1412
1429
|
decisionType: entry.decisionType,
|
|
1413
1430
|
decision: entry.decision,
|
|
@@ -1442,7 +1459,7 @@ export class SynthAgent {
|
|
|
1442
1459
|
// Record successful delegation completion
|
|
1443
1460
|
const completionEntry = this.debrief.record({
|
|
1444
1461
|
partitionId: deployment.partitionId ?? null,
|
|
1445
|
-
|
|
1462
|
+
operationId: deployment.id,
|
|
1446
1463
|
agent: "server",
|
|
1447
1464
|
decisionType: "deployment-execution",
|
|
1448
1465
|
decision: `Envoy completed deployment successfully in ${envoyResult.executionDurationMs}ms — ${envoyResult.artifacts.length} artifact(s) produced`,
|
|
@@ -1475,7 +1492,7 @@ export class SynthAgent {
|
|
|
1475
1492
|
): Promise<void> {
|
|
1476
1493
|
const entry = this.debrief.record({
|
|
1477
1494
|
partitionId: deployment.partitionId ?? null,
|
|
1478
|
-
|
|
1495
|
+
operationId: deployment.id,
|
|
1479
1496
|
agent: "server",
|
|
1480
1497
|
decisionType: "deployment-verification",
|
|
1481
1498
|
decision: `Post-deploy verification skipped for ${artifact.name} v${deployment.version} — no Envoy configured`,
|
|
@@ -1506,7 +1523,10 @@ export class SynthAgent {
|
|
|
1506
1523
|
// In-memory deployment store
|
|
1507
1524
|
// ---------------------------------------------------------------------------
|
|
1508
1525
|
|
|
1509
|
-
|
|
1526
|
+
const getArtifactId = (op: Deployment): string =>
|
|
1527
|
+
op.input?.type === "deploy" ? (op.input as { type: "deploy"; artifactId: string }).artifactId : "";
|
|
1528
|
+
|
|
1529
|
+
export class InMemoryDeploymentStore implements OperationStore {
|
|
1510
1530
|
private deployments: Map<DeploymentId, Deployment> = new Map();
|
|
1511
1531
|
|
|
1512
1532
|
save(deployment: Deployment): void {
|
|
@@ -1525,7 +1545,7 @@ export class InMemoryDeploymentStore implements DeploymentStore {
|
|
|
1525
1545
|
|
|
1526
1546
|
getByArtifact(artifactId: string): Deployment[] {
|
|
1527
1547
|
return [...this.deployments.values()].filter(
|
|
1528
|
-
(d) => d
|
|
1548
|
+
(d) => getArtifactId(d) === artifactId,
|
|
1529
1549
|
);
|
|
1530
1550
|
}
|
|
1531
1551
|
|
|
@@ -1542,7 +1562,7 @@ export class InMemoryDeploymentStore implements DeploymentStore {
|
|
|
1542
1562
|
findByArtifactVersion(artifactId: string, version: string, status?: string): Deployment[] {
|
|
1543
1563
|
return [...this.deployments.values()].filter(
|
|
1544
1564
|
(d) =>
|
|
1545
|
-
d
|
|
1565
|
+
getArtifactId(d) === artifactId &&
|
|
1546
1566
|
d.version === version &&
|
|
1547
1567
|
(!status || d.status === status),
|
|
1548
1568
|
);
|
|
@@ -1552,7 +1572,7 @@ export class InMemoryDeploymentStore implements DeploymentStore {
|
|
|
1552
1572
|
return [...this.deployments.values()]
|
|
1553
1573
|
.filter(
|
|
1554
1574
|
(d) =>
|
|
1555
|
-
d
|
|
1575
|
+
getArtifactId(d) === artifactId &&
|
|
1556
1576
|
new Date(d.createdAt).getTime() >= since.getTime() &&
|
|
1557
1577
|
(!status || d.status === status),
|
|
1558
1578
|
)
|