@kungfu-tech/buildchain 4.0.1-alpha.9 → 4.0.1

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.
Files changed (98) hide show
  1. package/README.md +9 -6
  2. package/actions/v4-release-candidate-promote/README.md +3 -0
  3. package/architecture/agent-change-map.md +1015 -0
  4. package/architecture/ci-lane-change-budget.json +70 -1
  5. package/architecture/decisions/0004-v4-declarative-release-tail.md +47 -0
  6. package/architecture/internal-capabilities.json +156 -11
  7. package/architecture/maintainability-debt.json +3229 -0
  8. package/architecture/maintainability-policy.json +480 -129
  9. package/architecture/v3-core-mechanism-inventory.json +4 -3
  10. package/architecture/v3-v4-capability-closure.md +59 -0
  11. package/architecture/v3-v4-live-capability-inventory.json +102404 -0
  12. package/architecture/v4-cross-platform-adopter-qualification.json +52 -0
  13. package/architecture/v4-delivery-warrant-shadow-fixtures.json +3 -3
  14. package/architecture/v4-runtime-semantic-closure.json +710 -0
  15. package/bin/internal/trust-release-release-handlers.mjs +5 -0
  16. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  17. package/contracts/v4-publication-qualification-v1.schema.json +51 -0
  18. package/dist/site/agent-index.json +1 -0
  19. package/dist/site/artifact-schemas.json +2 -0
  20. package/dist/site/buildchain-contract.json +123 -32
  21. package/dist/site/buildchain-site.json +96 -28
  22. package/dist/site/capability-registry.json +6 -6
  23. package/dist/site/cli-registry.json +5 -2
  24. package/dist/site/controller-registry.json +41 -5
  25. package/dist/site/kfd-claims.json +170 -21
  26. package/dist/site/kfd-upstream-aggregate.json +1 -1
  27. package/dist/site/manual-registry.json +6 -6
  28. package/dist/site/node-api-registry.json +1474 -215
  29. package/dist/site/page-registry.json +85 -17
  30. package/dist/site/public-surface-audit.json +85 -20
  31. package/dist/site/publication-authority-registry.json +28 -1
  32. package/dist/site/publication-registry.json +4 -4
  33. package/dist/site/release-provenance.json +5 -0
  34. package/dist/site/schemas/v4-publication-qualification-v1.schema.json +51 -0
  35. package/dist/site/site-manifest.json +10 -10
  36. package/dist/site/workflow-registry.json +94 -18
  37. package/docs/MAP.md +1 -1
  38. package/docs/cli-reference.md +4 -4
  39. package/docs/dev-delivery-warrant.md +12 -9
  40. package/docs/node-api-reference.md +291 -206
  41. package/docs/publish-transaction.md +11 -4
  42. package/docs/release-candidate.md +7 -0
  43. package/docs/v4-adopter-delivery.md +23 -4
  44. package/docs/v4-declarative-release-tail-migration.md +43 -0
  45. package/package.json +8 -3
  46. package/packages/core/adopter-delivery-passport.js +36 -0
  47. package/packages/core/buildchain-contract.js +31 -1
  48. package/packages/core/buildchain-publication-authority.js +1 -0
  49. package/packages/core/dev-delivery-warrant-settlement.js +239 -3
  50. package/packages/core/dev-delivery-warrant-state.js +15 -2
  51. package/packages/core/dev-delivery-warrant.js +21 -4
  52. package/packages/core/github-governance-authority.js +4 -4
  53. package/packages/core/index.js +1 -0
  54. package/packages/core/paper-scaffold-content.js +401 -0
  55. package/packages/core/paper.js +12 -378
  56. package/packages/core/publication-control-plane-audit.js +135 -111
  57. package/packages/core/publication-rehearsal-projection.js +104 -0
  58. package/packages/core/publication-rehearsal-runtime.js +190 -0
  59. package/packages/core/release-candidate-recovery.js +6 -5
  60. package/packages/core/release-passport.js +82 -184
  61. package/packages/core/v4-cross-platform-adopter-qualification.js +343 -0
  62. package/packages/core/v4-floating-consumer-policy.js +3 -2
  63. package/packages/core/v4-floating-consumer-release-passport.js +134 -15
  64. package/packages/core/v4-publication-qualification.js +222 -0
  65. package/scripts/artifact-signing-controller-core.mjs +1 -1
  66. package/scripts/audit-publication-control-plane.mjs +17 -17
  67. package/scripts/buildchain-cli-help.mjs +3 -0
  68. package/scripts/check-internal-architecture.mjs +23 -3
  69. package/scripts/check-inventory.mjs +23 -5
  70. package/scripts/check-maintainability.mjs +145 -4
  71. package/scripts/check-project-cut-merge-queue-admission.mjs +87 -0
  72. package/scripts/check-v3-v4-capability-inventory.mjs +574 -0
  73. package/scripts/check-v4-floating-consumer-policy-contract.mjs +10 -3
  74. package/scripts/check-v4-runtime-semantic-closure.mjs +266 -0
  75. package/scripts/dev-delivery-warrant-options.mjs +27 -11
  76. package/scripts/dev-delivery-warrant.mjs +45 -5
  77. package/scripts/dev-pr-auto-merge.mjs +25 -11
  78. package/scripts/dev-pr-delivery-warrant.mjs +44 -0
  79. package/scripts/dev-pr-prequeue-guard.mjs +0 -18
  80. package/scripts/dispatch-artifact-signing-authority.mjs +1 -1
  81. package/scripts/generate-agent-change-map.mjs +118 -0
  82. package/scripts/generate-release-candidate-passport.mjs +26 -1
  83. package/scripts/generate-site-bundle.mjs +6 -0
  84. package/scripts/maintainability-domain-metrics.mjs +237 -0
  85. package/scripts/maintainability-governance.mjs +473 -0
  86. package/scripts/maintainability-metrics.mjs +28 -6
  87. package/scripts/project-cut-merge-queue-admission.mjs +394 -0
  88. package/scripts/promotion-routing-evidence.mjs +35 -6
  89. package/scripts/release-candidate-resolver.mjs +44 -0
  90. package/scripts/release-line-policy.mjs +25 -15
  91. package/scripts/release-tail.mjs +19 -2
  92. package/scripts/resume-from-candidate-run.mjs +106 -103
  93. package/scripts/run-lifecycle-core.mjs +341 -376
  94. package/scripts/site-capability-metadata.mjs +4 -0
  95. package/scripts/stable-candidate-qualification.mjs +9 -10
  96. package/scripts/v3-v4-capability-catalog.mjs +439 -0
  97. package/scripts/v4-cross-platform-adopter-qualification.mjs +228 -0
  98. package/scripts/v4-declarative-promotion-admission.mjs +42 -0
@@ -408,476 +408,441 @@ export function verifyBuildLifecycleCompilerCacheActivity({
408
408
  return activity;
409
409
  }
410
410
 
411
- export function runLifecycle({
412
- cwd = process.cwd(),
413
- stageName = "",
414
- command = "",
415
- required = false,
416
- timeoutMinutes,
417
- manifestPath = ".buildchain/artifacts/manifest.json",
418
- summaryPath = ".buildchain/artifacts/summary.json",
419
- diagnosticsPath = "",
420
- artifactName = "buildchain-artifact",
421
- manifestArtifactName = "",
422
- diagnosticsArtifactName = "",
423
- platformId = os.platform(),
424
- platformName = platformId,
425
- artifactPaths = [],
426
- expectedArtifactsJson = "",
427
- workspace = process.cwd(),
428
- logPath = process.env.BUILDCHAIN_LOG_PATH || ".buildchain/logs/events.jsonl",
429
- processSummaryPath = "",
430
- processSamplesPath = ".buildchain/diagnostics/process-samples.jsonl",
431
- sampleProcessTree = false,
432
- processSampleIntervalMs = 15000,
433
- requestedParallelism = 0,
434
- processSummaryRequired = true,
435
- substageEvidencePath = "",
436
- } = {}) {
437
- if (timeoutMinutes !== undefined && (!Number.isFinite(timeoutMinutes) || timeoutMinutes <= 0)) {
411
+ function normalizeLifecycleOptions(options) {
412
+ const normalized = { ...options };
413
+ const defaults = {
414
+ cwd: process.cwd(), stageName: "", command: "", required: false,
415
+ manifestPath: ".buildchain/artifacts/manifest.json",
416
+ summaryPath: ".buildchain/artifacts/summary.json", diagnosticsPath: "",
417
+ artifactName: "buildchain-artifact", manifestArtifactName: "",
418
+ diagnosticsArtifactName: "", platformId: os.platform(), artifactPaths: [],
419
+ expectedArtifactsJson: "", workspace: process.cwd(),
420
+ logPath: process.env.BUILDCHAIN_LOG_PATH || ".buildchain/logs/events.jsonl",
421
+ processSummaryPath: "", processSamplesPath: ".buildchain/diagnostics/process-samples.jsonl",
422
+ sampleProcessTree: false, processSampleIntervalMs: 15000, requestedParallelism: 0,
423
+ processSummaryRequired: true, substageEvidencePath: "",
424
+ };
425
+ for (const [key, value] of Object.entries(defaults)) {
426
+ if (normalized[key] === undefined) normalized[key] = value;
427
+ }
428
+ if (normalized.platformName === undefined) normalized.platformName = normalized.platformId;
429
+ return normalized;
430
+ }
431
+
432
+ function resolveLifecyclePaths(options) {
433
+ if (options.timeoutMinutes !== undefined && (!Number.isFinite(options.timeoutMinutes) || options.timeoutMinutes <= 0)) {
438
434
  throw new Error("lifecycle timeoutMinutes must be a positive number");
439
435
  }
440
- const resolvedCwd = path.resolve(cwd);
441
- const resolvedWorkspace = path.resolve(workspace);
442
- const resolvedManifestPath = path.resolve(resolvedWorkspace, manifestPath);
443
- const resolvedSummaryPath = path.resolve(resolvedWorkspace, summaryPath);
436
+ const resolvedCwd = path.resolve(options.cwd);
437
+ const resolvedWorkspace = path.resolve(options.workspace);
438
+ const resolvedManifestPath = path.resolve(resolvedWorkspace, options.manifestPath);
439
+ const resolvedSummaryPath = path.resolve(resolvedWorkspace, options.summaryPath);
444
440
  const resolvedDiagnosticsPath = path.resolve(
445
441
  resolvedWorkspace,
446
- diagnosticsPath || path.join(path.dirname(manifestPath), "diagnostics.json"),
442
+ options.diagnosticsPath || path.join(path.dirname(options.manifestPath), "diagnostics.json"),
447
443
  );
448
- const resolvedLogPath = logPath ? path.resolve(resolvedWorkspace, logPath) : "";
449
- const resolvedProcessSummaryPath = processSummaryPath || sampleProcessTree
450
- ? path.resolve(resolvedWorkspace, processSummaryPath || ".buildchain/diagnostics/process-summary.json")
444
+ const resolvedLogPath = options.logPath ? path.resolve(resolvedWorkspace, options.logPath) : "";
445
+ const resolvedProcessSummaryPath = options.processSummaryPath || options.sampleProcessTree
446
+ ? path.resolve(resolvedWorkspace, options.processSummaryPath || ".buildchain/diagnostics/process-summary.json")
451
447
  : "";
452
- const resolvedProcessSamplesPath = processSamplesPath
453
- ? path.resolve(resolvedWorkspace, processSamplesPath)
448
+ const resolvedProcessSamplesPath = options.processSamplesPath
449
+ ? path.resolve(resolvedWorkspace, options.processSamplesPath)
454
450
  : path.resolve(resolvedWorkspace, ".buildchain/diagnostics/process-samples.jsonl");
455
- const relativeLogPath = resolvedLogPath ? toPosix(path.relative(resolvedWorkspace, resolvedLogPath)) : "";
456
- const relativeProcessSummaryPath = resolvedProcessSummaryPath
457
- ? toPosix(path.relative(resolvedWorkspace, resolvedProcessSummaryPath))
458
- : "";
459
- const relativeDiagnosticsPath = toPosix(path.relative(resolvedWorkspace, resolvedDiagnosticsPath));
460
451
  const diagnosticsDir = path.dirname(resolvedDiagnosticsPath);
461
- const resolvedDiagnosticsEventsPath = path.join(diagnosticsDir, "events.jsonl");
462
- const resolvedDiagnosticsProcessSummaryPath = path.join(diagnosticsDir, "process-summary.json");
463
- const resolvedDiagnosticsProcessSamplesPath = path.join(diagnosticsDir, "process-samples.jsonl");
464
- const resolvedSourceCheckoutPath = path.resolve(resolvedWorkspace, ".buildchain/diagnostics/source-checkout.json");
465
- const resolvedDiagnosticsSourceCheckoutPath = path.join(diagnosticsDir, "source-checkout.json");
466
452
  const resolvedCompilerCachePreparationPath = path.resolve(
467
453
  resolvedWorkspace,
468
454
  process.env.BUILDCHAIN_COMPILER_CACHE_PREPARATION_PATH ||
469
455
  ".buildchain/diagnostics/compiler-cache-preparation.json",
470
456
  );
471
- const compilerCachePreparationRelative = path.relative(
472
- resolvedWorkspace,
473
- resolvedCompilerCachePreparationPath,
474
- );
475
- if (
476
- compilerCachePreparationRelative.startsWith("..") ||
477
- path.isAbsolute(compilerCachePreparationRelative)
478
- ) {
479
- throw new Error(
480
- "BUILDCHAIN_COMPILER_CACHE_PREPARATION_PATH must remain inside the workflow workspace",
481
- );
457
+ const compilerCachePreparationRelative = path.relative(resolvedWorkspace, resolvedCompilerCachePreparationPath);
458
+ if (compilerCachePreparationRelative.startsWith("..") || path.isAbsolute(compilerCachePreparationRelative)) {
459
+ throw new Error("BUILDCHAIN_COMPILER_CACHE_PREPARATION_PATH must remain inside the workflow workspace");
482
460
  }
483
- const resolvedDiagnosticsCompilerCachePreparationPath = path.join(
461
+ return {
462
+ resolvedCwd, resolvedWorkspace, resolvedManifestPath, resolvedSummaryPath,
463
+ resolvedDiagnosticsPath, resolvedLogPath, resolvedProcessSummaryPath, resolvedProcessSamplesPath,
464
+ relativeLogPath: resolvedLogPath ? toPosix(path.relative(resolvedWorkspace, resolvedLogPath)) : "",
465
+ relativeProcessSummaryPath: resolvedProcessSummaryPath ? toPosix(path.relative(resolvedWorkspace, resolvedProcessSummaryPath)) : "",
466
+ relativeDiagnosticsPath: toPosix(path.relative(resolvedWorkspace, resolvedDiagnosticsPath)),
484
467
  diagnosticsDir,
485
- "compiler-cache-preparation.json",
486
- );
487
- const resolvedDiagnosticsManifestPath = path.join(diagnosticsDir, "diagnostics-manifest.json");
488
- const relativeDiagnosticsEventsPath = toPosix(path.relative(resolvedWorkspace, resolvedDiagnosticsEventsPath));
489
- const relativeDiagnosticsProcessSummaryPath = toPosix(path.relative(resolvedWorkspace, resolvedDiagnosticsProcessSummaryPath));
490
- const relativeDiagnosticsProcessSamplesPath = toPosix(path.relative(resolvedWorkspace, resolvedDiagnosticsProcessSamplesPath));
491
- const relativeDiagnosticsSourceCheckoutPath = toPosix(path.relative(resolvedWorkspace, resolvedDiagnosticsSourceCheckoutPath));
492
- const relativeDiagnosticsCompilerCachePreparationPath = toPosix(
493
- path.relative(resolvedWorkspace, resolvedDiagnosticsCompilerCachePreparationPath),
494
- );
495
- const relativeDiagnosticsManifestPath = toPosix(path.relative(resolvedWorkspace, resolvedDiagnosticsManifestPath));
468
+ resolvedDiagnosticsEventsPath: path.join(diagnosticsDir, "events.jsonl"),
469
+ resolvedDiagnosticsProcessSummaryPath: path.join(diagnosticsDir, "process-summary.json"),
470
+ resolvedDiagnosticsProcessSamplesPath: path.join(diagnosticsDir, "process-samples.jsonl"),
471
+ resolvedSourceCheckoutPath: path.resolve(resolvedWorkspace, ".buildchain/diagnostics/source-checkout.json"),
472
+ resolvedDiagnosticsSourceCheckoutPath: path.join(diagnosticsDir, "source-checkout.json"),
473
+ resolvedCompilerCachePreparationPath,
474
+ resolvedDiagnosticsCompilerCachePreparationPath: path.join(diagnosticsDir, "compiler-cache-preparation.json"),
475
+ resolvedDiagnosticsManifestPath: path.join(diagnosticsDir, "diagnostics-manifest.json"),
476
+ };
477
+ }
478
+
479
+ function addRelativeLifecyclePaths(paths) {
480
+ const relative = (target) => toPosix(path.relative(paths.resolvedWorkspace, target));
481
+ return {
482
+ ...paths,
483
+ relativeDiagnosticsEventsPath: relative(paths.resolvedDiagnosticsEventsPath),
484
+ relativeDiagnosticsProcessSummaryPath: relative(paths.resolvedDiagnosticsProcessSummaryPath),
485
+ relativeDiagnosticsProcessSamplesPath: relative(paths.resolvedDiagnosticsProcessSamplesPath),
486
+ relativeDiagnosticsSourceCheckoutPath: relative(paths.resolvedDiagnosticsSourceCheckoutPath),
487
+ relativeDiagnosticsCompilerCachePreparationPath:
488
+ relative(paths.resolvedDiagnosticsCompilerCachePreparationPath),
489
+ relativeDiagnosticsManifestPath: relative(paths.resolvedDiagnosticsManifestPath),
490
+ };
491
+ }
492
+
493
+ function createLifecycleContext(options) {
494
+ const paths = addRelativeLifecyclePaths(resolveLifecyclePaths(options));
496
495
  const logRunId = crypto.randomUUID();
497
- const frameworkLog = createBuildchainLogger({
498
- cwd: resolvedWorkspace,
499
- path: resolvedLogPath || false,
500
- console: false,
501
- source: "buildchain",
502
- component: "lifecycle",
503
- phase: stageName || "lifecycle",
504
- attributes: { buildchainLogRunId: logRunId },
505
- });
506
- const userLog = createBuildchainLogger({
507
- cwd: resolvedWorkspace,
508
- path: resolvedLogPath || false,
496
+ const loggerOptions = {
497
+ cwd: paths.resolvedWorkspace,
498
+ path: paths.resolvedLogPath || false,
509
499
  console: false,
510
- source: "user",
511
500
  component: "lifecycle",
512
- phase: stageName || "lifecycle",
501
+ phase: options.stageName || "lifecycle",
513
502
  attributes: { buildchainLogRunId: logRunId },
514
- });
515
- const loadedConfig = loadBuildchainConfig(resolvedCwd);
516
- let commandSource = "none";
517
- let executed = false;
503
+ };
504
+ return {
505
+ ...options, ...paths, logRunId,
506
+ frameworkLog: createBuildchainLogger({ ...loggerOptions, source: "buildchain" }),
507
+ userLog: createBuildchainLogger({ ...loggerOptions, source: "user" }),
508
+ loadedConfig: loadBuildchainConfig(paths.resolvedCwd),
509
+ commandSource: "none",
510
+ executed: false,
511
+ };
512
+ }
518
513
 
519
- frameworkLog.info("lifecycle.start", {
520
- attributes: {
521
- stage: stageName,
522
- artifactName,
523
- platformId,
524
- },
514
+ function executeWorkflowLifecycleCommand(context) {
515
+ const {
516
+ command, stageName, sampleProcessTree, processSampleIntervalMs, requestedParallelism,
517
+ timeoutMinutes, resolvedCwd, resolvedLogPath, resolvedProcessSummaryPath,
518
+ resolvedProcessSamplesPath, logRunId, loadedConfig, userLog, platformId, platformName,
519
+ } = context;
520
+ context.commandSource = "workflow-input";
521
+ const lifecycle = loadedConfig?.config?.lifecycle || {};
522
+ const configuredStage = stageName ? lifecycle[stageName] : undefined;
523
+ const commandShell = configuredStage?.shell || true;
524
+ const effectiveCommandTimeoutMinutes = configuredStage?.timeoutMinutes ?? timeoutMinutes;
525
+ const startedAt = Date.now();
526
+ userLog.info("lifecycle.command.start", {
527
+ attributes: { commandSource: context.commandSource, stage: stageName || "command", sampleProcessTree },
525
528
  });
526
-
527
- if (command.trim()) {
528
- commandSource = "workflow-input";
529
- const lifecycle = loadedConfig?.config?.lifecycle || {};
530
- const configuredStage = stageName ? lifecycle[stageName] : undefined;
531
- const commandShell = configuredStage?.shell || true;
532
- const effectiveCommandTimeoutMinutes = configuredStage?.timeoutMinutes ?? timeoutMinutes;
533
- const startedAt = Date.now();
534
- userLog.info("lifecycle.command.start", {
535
- attributes: {
536
- commandSource,
537
- stage: stageName || "command",
538
- sampleProcessTree,
539
- },
540
- });
541
- try {
542
- const commandEnv = {
543
- ...process.env,
544
- ...(lifecycle.env || {}),
545
- ...(configuredStage?.env || {}),
546
- ...(resolvedLogPath
547
- ? {
548
- BUILDCHAIN_LOG_PATH: resolvedLogPath,
549
- BUILDCHAIN_LOG_RUN_ID: logRunId,
550
- }
551
- : {}),
552
- };
553
- if (sampleProcessTree) {
554
- executeSampledShellCommand({
555
- command,
556
- cwd: resolvedCwd,
557
- env: commandEnv,
558
- shell: commandShell,
559
- label: `lifecycle-${stageName || "command"}`,
560
- processSummaryPath: resolvedProcessSummaryPath,
561
- processSamplesPath: resolvedProcessSamplesPath,
562
- processSampleIntervalMs,
563
- requestedParallelism,
564
- timeout: effectiveCommandTimeoutMinutes ? effectiveCommandTimeoutMinutes * 60_000 : undefined,
565
- });
566
- } else {
567
- runShellCommandSync(command, {
568
- cwd: resolvedCwd,
569
- env: commandEnv,
570
- shell: commandShell,
571
- stdio: "inherit",
572
- timeout: effectiveCommandTimeoutMinutes ? effectiveCommandTimeoutMinutes * 60_000 : undefined,
573
- });
574
- }
575
- executed = true;
576
- userLog.info("lifecycle.command.end", {
577
- durationMs: Date.now() - startedAt,
578
- attributes: {
579
- commandSource,
580
- stage: stageName || "command",
581
- },
582
- });
583
- } catch (error) {
584
- const lifecycleError = describeLifecycleTimeout(error, {
585
- timeoutMinutes: effectiveCommandTimeoutMinutes,
586
- stageName,
587
- platformId,
588
- platformName,
589
- });
590
- userLog.error("lifecycle.command.error", {
591
- durationMs: Date.now() - startedAt,
592
- message: "lifecycle command failed",
593
- attributes: lifecycleErrorAttributes(lifecycleError, {
594
- commandSource,
595
- stage: stageName || "command",
596
- sampleProcessTree,
597
- }),
598
- });
599
- throw lifecycleError;
600
- }
601
- } else if (stageName) {
602
- commandSource = "buildchain.toml";
603
- const startedAt = Date.now();
604
- userLog.info("lifecycle.stage.start", {
605
- attributes: {
606
- commandSource,
607
- stage: stageName,
608
- sampleProcessTree,
609
- },
610
- });
611
- try {
612
- executed = runLifecycleStageWithSampler({
613
- cwd: resolvedCwd,
614
- loadedConfig,
615
- name: stageName,
616
- env: resolvedLogPath
617
- ? {
618
- BUILDCHAIN_LOG_PATH: resolvedLogPath,
619
- BUILDCHAIN_LOG_RUN_ID: logRunId,
620
- }
621
- : {},
622
- sampleProcessTree,
529
+ try {
530
+ const commandEnv = {
531
+ ...process.env, ...(lifecycle.env || {}), ...(configuredStage?.env || {}),
532
+ ...(resolvedLogPath ? { BUILDCHAIN_LOG_PATH: resolvedLogPath, BUILDCHAIN_LOG_RUN_ID: logRunId } : {}),
533
+ };
534
+ const timeout = effectiveCommandTimeoutMinutes ? effectiveCommandTimeoutMinutes * 60_000 : undefined;
535
+ if (sampleProcessTree) {
536
+ executeSampledShellCommand({
537
+ command, cwd: resolvedCwd, env: commandEnv, shell: commandShell,
538
+ label: `lifecycle-${stageName || "command"}`,
623
539
  processSummaryPath: resolvedProcessSummaryPath,
624
540
  processSamplesPath: resolvedProcessSamplesPath,
625
- processSampleIntervalMs,
626
- requestedParallelism,
627
- timeoutMinutes,
541
+ processSampleIntervalMs, requestedParallelism, timeout,
628
542
  });
629
- userLog.info("lifecycle.stage.end", {
630
- durationMs: Date.now() - startedAt,
631
- attributes: {
632
- commandSource,
633
- stage: stageName,
634
- executed,
635
- },
543
+ } else {
544
+ runShellCommandSync(command, {
545
+ cwd: resolvedCwd, env: commandEnv, shell: commandShell, stdio: "inherit", timeout,
636
546
  });
637
- } catch (error) {
638
- const lifecycleError = describeLifecycleTimeout(error, {
639
- timeoutMinutes: loadedConfig?.config?.lifecycle?.[stageName]?.timeoutMinutes ?? timeoutMinutes,
640
- stageName,
641
- platformId,
642
- platformName,
643
- });
644
- userLog.error("lifecycle.stage.error", {
645
- durationMs: Date.now() - startedAt,
646
- message: "lifecycle stage failed",
647
- attributes: lifecycleErrorAttributes(lifecycleError, {
648
- commandSource,
649
- stage: stageName,
650
- sampleProcessTree,
651
- }),
652
- });
653
- throw lifecycleError;
654
547
  }
548
+ context.executed = true;
549
+ userLog.info("lifecycle.command.end", {
550
+ durationMs: Date.now() - startedAt,
551
+ attributes: { commandSource: context.commandSource, stage: stageName || "command" },
552
+ });
553
+ } catch (error) {
554
+ const lifecycleError = describeLifecycleTimeout(error, {
555
+ timeoutMinutes: effectiveCommandTimeoutMinutes, stageName, platformId, platformName,
556
+ });
557
+ userLog.error("lifecycle.command.error", {
558
+ durationMs: Date.now() - startedAt, message: "lifecycle command failed",
559
+ attributes: lifecycleErrorAttributes(lifecycleError, {
560
+ commandSource: context.commandSource, stage: stageName || "command", sampleProcessTree,
561
+ }),
562
+ });
563
+ throw lifecycleError;
655
564
  }
656
- if (required && !executed) {
565
+ }
566
+
567
+ function executeConfiguredLifecycleStage(context) {
568
+ const {
569
+ stageName, sampleProcessTree, timeoutMinutes, processSampleIntervalMs,
570
+ requestedParallelism, resolvedCwd, resolvedLogPath, resolvedProcessSummaryPath,
571
+ resolvedProcessSamplesPath, logRunId, loadedConfig, userLog, platformId, platformName,
572
+ } = context;
573
+ context.commandSource = "buildchain.toml";
574
+ const startedAt = Date.now();
575
+ userLog.info("lifecycle.stage.start", {
576
+ attributes: { commandSource: context.commandSource, stage: stageName, sampleProcessTree },
577
+ });
578
+ try {
579
+ context.executed = runLifecycleStageWithSampler({
580
+ cwd: resolvedCwd, loadedConfig, name: stageName,
581
+ env: resolvedLogPath ? { BUILDCHAIN_LOG_PATH: resolvedLogPath, BUILDCHAIN_LOG_RUN_ID: logRunId } : {},
582
+ sampleProcessTree, processSummaryPath: resolvedProcessSummaryPath,
583
+ processSamplesPath: resolvedProcessSamplesPath, processSampleIntervalMs,
584
+ requestedParallelism, timeoutMinutes,
585
+ });
586
+ userLog.info("lifecycle.stage.end", {
587
+ durationMs: Date.now() - startedAt,
588
+ attributes: { commandSource: context.commandSource, stage: stageName, executed: context.executed },
589
+ });
590
+ } catch (error) {
591
+ const lifecycleError = describeLifecycleTimeout(error, {
592
+ timeoutMinutes: loadedConfig?.config?.lifecycle?.[stageName]?.timeoutMinutes ?? timeoutMinutes,
593
+ stageName, platformId, platformName,
594
+ });
595
+ userLog.error("lifecycle.stage.error", {
596
+ durationMs: Date.now() - startedAt, message: "lifecycle stage failed",
597
+ attributes: lifecycleErrorAttributes(lifecycleError, {
598
+ commandSource: context.commandSource, stage: stageName, sampleProcessTree,
599
+ }),
600
+ });
601
+ throw lifecycleError;
602
+ }
603
+ }
604
+
605
+ function executeLifecycle(context) {
606
+ const { stageName, artifactName, platformId, command, required, frameworkLog } = context;
607
+ frameworkLog.info("lifecycle.start", { attributes: { stage: stageName, artifactName, platformId } });
608
+ if (command.trim()) executeWorkflowLifecycleCommand(context);
609
+ else if (stageName) executeConfiguredLifecycleStage(context);
610
+ if (required && !context.executed) {
657
611
  frameworkLog.error("lifecycle.required-missing", {
658
- attributes: {
659
- stage: stageName || "command",
660
- commandSource,
661
- },
612
+ attributes: { stage: stageName || "command", commandSource: context.commandSource },
662
613
  });
663
614
  throw new Error(`required lifecycle stage did not run: ${stageName || "command"}`);
664
615
  }
616
+ }
665
617
 
666
- const compilerCacheActivity = verifyBuildLifecycleCompilerCacheActivity({ stageName, executed, cwd: resolvedCwd, frameworkLog });
667
- const substages = lifecycleSubstageEvidenceContext({ substageEvidencePath, cwd: resolvedCwd, workspace: resolvedWorkspace, diagnosticsDir, lifecycleStage: stageName, platformId });
618
+ function readLifecycleSupportArtifacts(context) {
668
619
  const shouldReadProcessSummary = Boolean(
669
- resolvedProcessSummaryPath
670
- && (fs.existsSync(resolvedProcessSummaryPath) || processSummaryRequired),
620
+ context.resolvedProcessSummaryPath &&
621
+ (fs.existsSync(context.resolvedProcessSummaryPath) || context.processSummaryRequired),
671
622
  );
672
- const processSummaryArtifact = shouldReadProcessSummary
673
- ? readProcessSummaryArtifact(resolvedProcessSummaryPath)
674
- : undefined;
675
- const sourceCheckoutArtifact = fs.existsSync(resolvedSourceCheckoutPath)
676
- ? JSON.parse(fs.readFileSync(resolvedSourceCheckoutPath, "utf8"))
677
- : undefined;
678
- const compilerCachePreparationArtifact = fs.existsSync(resolvedCompilerCachePreparationPath)
679
- ? JSON.parse(fs.readFileSync(resolvedCompilerCachePreparationPath, "utf8"))
680
- : undefined;
681
- fs.mkdirSync(path.dirname(resolvedManifestPath), { recursive: true });
623
+ return {
624
+ processSummaryArtifact: shouldReadProcessSummary
625
+ ? readProcessSummaryArtifact(context.resolvedProcessSummaryPath)
626
+ : undefined,
627
+ sourceCheckoutArtifact: fs.existsSync(context.resolvedSourceCheckoutPath)
628
+ ? JSON.parse(fs.readFileSync(context.resolvedSourceCheckoutPath, "utf8"))
629
+ : undefined,
630
+ compilerCachePreparationArtifact: fs.existsSync(context.resolvedCompilerCachePreparationPath)
631
+ ? JSON.parse(fs.readFileSync(context.resolvedCompilerCachePreparationPath, "utf8"))
632
+ : undefined,
633
+ };
634
+ }
635
+
636
+ function collectLifecycleArtifacts(context) {
637
+ const compilerCacheActivity = verifyBuildLifecycleCompilerCacheActivity({
638
+ stageName: context.stageName, executed: context.executed,
639
+ cwd: context.resolvedCwd, frameworkLog: context.frameworkLog,
640
+ });
641
+ const substages = lifecycleSubstageEvidenceContext({
642
+ substageEvidencePath: context.substageEvidencePath, cwd: context.resolvedCwd,
643
+ workspace: context.resolvedWorkspace, diagnosticsDir: context.diagnosticsDir,
644
+ lifecycleStage: context.stageName, platformId: context.platformId,
645
+ });
646
+ const support = readLifecycleSupportArtifacts(context);
647
+ fs.mkdirSync(path.dirname(context.resolvedManifestPath), { recursive: true });
682
648
  const scanStartedAt = Date.now();
683
- const signingArtifactPaths = stageName === "build"
649
+ const signingArtifactPaths = context.stageName === "build"
684
650
  ? signingArtifactPathsForPlatform({
685
- loadedConfig,
686
- cwd: resolvedCwd,
687
- platformId,
651
+ loadedConfig: context.loadedConfig, cwd: context.resolvedCwd, platformId: context.platformId,
688
652
  })
689
653
  : [];
690
- const files = collectArtifactFiles(resolvedWorkspace, [
691
- ...artifactPaths,
692
- ...signingArtifactPaths,
654
+ const files = collectArtifactFiles(context.resolvedWorkspace, [
655
+ ...context.artifactPaths, ...signingArtifactPaths,
693
656
  ]);
694
657
  const manifestFiles = files.map((file) => {
695
658
  const stat = fs.statSync(file);
696
659
  return {
697
- path: manifestPathFor(resolvedWorkspace, file),
660
+ path: manifestPathFor(context.resolvedWorkspace, file),
698
661
  size: stat.size,
699
662
  sha256: sha256File(file),
700
663
  };
701
664
  });
702
665
  const artifactScanDurationMs = Date.now() - scanStartedAt;
703
- frameworkLog.info("artifact.scan", {
704
- durationMs: artifactScanDurationMs,
705
- attributes: {
706
- fileCount: manifestFiles.length,
707
- },
666
+ context.frameworkLog.info("artifact.scan", {
667
+ durationMs: artifactScanDurationMs, attributes: { fileCount: manifestFiles.length },
708
668
  });
709
669
  const platform = {
710
- id: platformId,
711
- name: platformName,
712
- os: process.env.RUNNER_OS || os.platform(),
713
- arch: process.env.RUNNER_ARCH || os.arch(),
670
+ id: context.platformId, name: context.platformName,
671
+ os: process.env.RUNNER_OS || os.platform(), arch: process.env.RUNNER_ARCH || os.arch(),
714
672
  };
715
673
  const summary = createArtifactSummary({
716
- artifactName,
717
- platform,
718
- files: manifestFiles,
674
+ artifactName: context.artifactName, platform, files: manifestFiles,
719
675
  });
720
- const expected = parseExpectedArtifactsJson(expectedArtifactsJson);
721
676
  const expectedArtifacts = validateExpectedArtifacts({
722
- expected,
723
- files: manifestFiles,
724
- summary,
677
+ expected: parseExpectedArtifactsJson(context.expectedArtifactsJson),
678
+ files: manifestFiles, summary,
725
679
  });
680
+ return {
681
+ compilerCacheActivity, substages, ...support, manifestFiles,
682
+ artifactScanDurationMs, platform, summary, expectedArtifacts,
683
+ };
684
+ }
685
+
686
+ function createLifecycleManifest(context, artifacts) {
687
+ const { frameworkLog, userLog } = context;
688
+ const { manifestFiles, summary, artifactScanDurationMs, compilerCacheActivity, substages } = artifacts;
726
689
  frameworkLog.info("artifact.manifest.write", {
727
690
  attributes: {
728
- manifestPath: toPosix(path.relative(resolvedWorkspace, resolvedManifestPath)),
729
- summaryPath: toPosix(path.relative(resolvedWorkspace, resolvedSummaryPath)),
691
+ manifestPath: toPosix(path.relative(context.resolvedWorkspace, context.resolvedManifestPath)),
692
+ summaryPath: toPosix(path.relative(context.resolvedWorkspace, context.resolvedSummaryPath)),
730
693
  },
731
694
  });
732
695
  frameworkLog.info("lifecycle.end", {
733
- attributes: {
734
- stage: stageName,
735
- executed,
736
- fileCount: manifestFiles.length,
737
- },
696
+ attributes: { stage: context.stageName, executed: context.executed, fileCount: manifestFiles.length },
738
697
  });
698
+ const events = context.resolvedLogPath
699
+ ? readBuildchainLogEvents(context.resolvedLogPath)
700
+ : [...frameworkLog.events, ...userLog.events];
739
701
  const observability = {
740
702
  log: {
741
- contract: "kungfu-buildchain-log-event",
742
- runId: logRunId,
743
- path: relativeLogPath,
744
- summary: resolvedLogPath
745
- ? summarizeBuildchainLogEvents(
746
- readBuildchainLogEvents(resolvedLogPath).filter(
747
- (event) => event.attributes?.buildchainLogRunId === logRunId,
748
- ),
749
- )
750
- : summarizeBuildchainLogEvents([...frameworkLog.events, ...userLog.events]),
703
+ contract: "kungfu-buildchain-log-event", runId: context.logRunId,
704
+ path: context.relativeLogPath,
705
+ summary: context.resolvedLogPath
706
+ ? summarizeBuildchainLogEvents(events.filter((event) => event.attributes?.buildchainLogRunId === context.logRunId))
707
+ : summarizeBuildchainLogEvents(events),
751
708
  },
752
709
  };
753
710
  const lifecycleObservability = summarizeLifecycleObservability({
754
- events: resolvedLogPath ? readBuildchainLogEvents(resolvedLogPath) : [...frameworkLog.events, ...userLog.events],
755
- logPath: relativeLogPath,
756
- artifactScanDurationMs,
757
- totalBytes: summary.totalBytes,
758
- fileCount: summary.fileCount,
711
+ events, logPath: context.relativeLogPath, artifactScanDurationMs,
712
+ totalBytes: summary.totalBytes, fileCount: summary.fileCount,
759
713
  });
760
714
  observability.lifecycle = lifecycleObservability;
761
715
  Object.assign(observability, { compilerCacheActivity }, substages.observability);
762
716
  observability.diagnostics = {
763
717
  contract: BUILDCHAIN_DIAGNOSTICS_CONTRACT,
764
- path: relativeDiagnosticsPath,
765
- manifestPath: relativeDiagnosticsManifestPath,
766
- eventsPath: relativeDiagnosticsEventsPath,
718
+ path: context.relativeDiagnosticsPath,
719
+ manifestPath: context.relativeDiagnosticsManifestPath,
720
+ eventsPath: context.relativeDiagnosticsEventsPath,
767
721
  };
768
- if (relativeProcessSummaryPath) {
722
+ if (context.relativeProcessSummaryPath) {
769
723
  observability.process = {
770
724
  contract: BUILDCHAIN_PROCESS_SAMPLE_SUMMARY_CONTRACT,
771
- path: relativeProcessSummaryPath,
725
+ path: context.relativeProcessSummaryPath,
772
726
  };
773
727
  }
774
- const summaryWithObservability = {
775
- ...summary,
776
- observability,
777
- };
778
- const manifest = {
779
- schemaVersion: 1,
780
- contract: "kungfu-buildchain-artifact",
781
- artifactName,
782
- platform,
783
- git: {
784
- repository: process.env.GITHUB_REPOSITORY || "",
785
- sha: process.env.BUILDCHAIN_SOURCE_SHA || process.env.GITHUB_SHA || "",
786
- ref: process.env.BUILDCHAIN_SOURCE_REF || process.env.GITHUB_REF || "",
787
- runId: process.env.GITHUB_RUN_ID || "",
788
- runAttempt: process.env.GITHUB_RUN_ATTEMPT || "",
789
- },
790
- lifecycle: {
791
- stage: stageName,
792
- commandSource,
793
- executed,
794
- ...substages.lifecycle,
728
+ const summaryWithObservability = { ...summary, observability };
729
+ return {
730
+ lifecycleObservability, summaryWithObservability,
731
+ manifest: {
732
+ schemaVersion: 1, contract: "kungfu-buildchain-artifact",
733
+ artifactName: context.artifactName, platform: artifacts.platform,
734
+ git: {
735
+ repository: process.env.GITHUB_REPOSITORY || "",
736
+ sha: process.env.BUILDCHAIN_SOURCE_SHA || process.env.GITHUB_SHA || "",
737
+ ref: process.env.BUILDCHAIN_SOURCE_REF || process.env.GITHUB_REF || "",
738
+ runId: process.env.GITHUB_RUN_ID || "",
739
+ runAttempt: process.env.GITHUB_RUN_ATTEMPT || "",
740
+ },
741
+ lifecycle: {
742
+ stage: context.stageName, commandSource: context.commandSource,
743
+ executed: context.executed, ...substages.lifecycle,
744
+ },
745
+ observability, summary: summaryWithObservability,
746
+ expectedArtifacts: artifacts.expectedArtifacts, files: manifestFiles,
795
747
  },
796
- observability,
797
- summary: summaryWithObservability,
798
- expectedArtifacts,
799
- files: manifestFiles,
800
748
  };
749
+ }
801
750
 
802
- fs.writeFileSync(resolvedManifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
803
- fs.mkdirSync(path.dirname(resolvedSummaryPath), { recursive: true });
804
- fs.writeFileSync(resolvedSummaryPath, `${JSON.stringify(summaryWithObservability, null, 2)}\n`);
751
+ function diagnosticsLinks(context, artifacts) {
752
+ const { processSummaryArtifact, sourceCheckoutArtifact, compilerCachePreparationArtifact, substages } = artifacts;
753
+ return {
754
+ artifactName: context.artifactName, platformId: context.platformId,
755
+ ...(context.manifestArtifactName ? { manifestArtifactName: context.manifestArtifactName } : {}),
756
+ ...(context.diagnosticsArtifactName ? { diagnosticsArtifactName: context.diagnosticsArtifactName } : {}),
757
+ manifest: toPosix(path.relative(context.resolvedWorkspace, context.resolvedManifestPath)),
758
+ summary: toPosix(path.relative(context.resolvedWorkspace, context.resolvedSummaryPath)),
759
+ log: context.relativeLogPath,
760
+ diagnosticsManifest: context.relativeDiagnosticsManifestPath,
761
+ diagnosticsEvents: context.relativeDiagnosticsEventsPath,
762
+ ...(context.relativeProcessSummaryPath ? { processSummary: context.relativeProcessSummaryPath } : {}),
763
+ ...(processSummaryArtifact ? { diagnosticsProcessSummary: context.relativeDiagnosticsProcessSummaryPath } : {}),
764
+ ...(processSummaryArtifact?.samplesPath ? { diagnosticsProcessSamples: context.relativeDiagnosticsProcessSamplesPath } : {}),
765
+ ...substages.links,
766
+ ...(sourceCheckoutArtifact ? { sourceCheckout: context.relativeDiagnosticsSourceCheckoutPath } : {}),
767
+ ...(compilerCachePreparationArtifact
768
+ ? { compilerCachePreparation: context.relativeDiagnosticsCompilerCachePreparationPath }
769
+ : {}),
770
+ };
771
+ }
772
+
773
+ function persistLifecycleDiagnostics(context, artifacts, product) {
774
+ fs.writeFileSync(context.resolvedManifestPath, `${JSON.stringify(product.manifest, null, 2)}\n`);
775
+ fs.mkdirSync(path.dirname(context.resolvedSummaryPath), { recursive: true });
776
+ fs.writeFileSync(
777
+ context.resolvedSummaryPath,
778
+ `${JSON.stringify(product.summaryWithObservability, null, 2)}\n`,
779
+ );
805
780
  writeDiagnosticsArtifact(
806
- resolvedDiagnosticsPath,
781
+ context.resolvedDiagnosticsPath,
807
782
  createDiagnosticsArtifact({
808
- cwd: resolvedCwd,
809
- logPath: resolvedLogPath,
810
- artifactPaths,
811
- lifecycleObservability,
812
- processSummary: processSummaryArtifact?.summary,
813
- sourceCheckout: sourceCheckoutArtifact,
814
- compilerCachePreparation: compilerCachePreparationArtifact,
815
- links: {
816
- artifactName,
817
- platformId,
818
- ...(manifestArtifactName ? { manifestArtifactName } : {}),
819
- ...(diagnosticsArtifactName ? { diagnosticsArtifactName } : {}),
820
- manifest: toPosix(path.relative(resolvedWorkspace, resolvedManifestPath)),
821
- summary: toPosix(path.relative(resolvedWorkspace, resolvedSummaryPath)),
822
- log: relativeLogPath,
823
- diagnosticsManifest: relativeDiagnosticsManifestPath,
824
- diagnosticsEvents: relativeDiagnosticsEventsPath,
825
- ...(relativeProcessSummaryPath ? { processSummary: relativeProcessSummaryPath } : {}),
826
- ...(processSummaryArtifact ? { diagnosticsProcessSummary: relativeDiagnosticsProcessSummaryPath } : {}),
827
- ...(processSummaryArtifact?.samplesPath ? { diagnosticsProcessSamples: relativeDiagnosticsProcessSamplesPath } : {}),
828
- ...substages.links,
829
- ...(sourceCheckoutArtifact ? { sourceCheckout: relativeDiagnosticsSourceCheckoutPath } : {}),
830
- ...(compilerCachePreparationArtifact
831
- ? { compilerCachePreparation: relativeDiagnosticsCompilerCachePreparationPath }
832
- : {}),
833
- },
783
+ cwd: context.resolvedCwd,
784
+ logPath: context.resolvedLogPath,
785
+ artifactPaths: context.artifactPaths,
786
+ lifecycleObservability: product.lifecycleObservability,
787
+ processSummary: artifacts.processSummaryArtifact?.summary,
788
+ sourceCheckout: artifacts.sourceCheckoutArtifact,
789
+ compilerCachePreparation: artifacts.compilerCachePreparationArtifact,
790
+ links: diagnosticsLinks(context, artifacts),
834
791
  }),
835
792
  );
836
- if (resolvedLogPath && fs.existsSync(resolvedLogPath)) {
837
- copyIfExists(resolvedLogPath, resolvedDiagnosticsEventsPath);
793
+ if (context.resolvedLogPath && fs.existsSync(context.resolvedLogPath)) {
794
+ copyIfExists(context.resolvedLogPath, context.resolvedDiagnosticsEventsPath);
838
795
  } else {
839
- writeJsonlEvents(resolvedDiagnosticsEventsPath, [...frameworkLog.events, ...userLog.events]);
796
+ writeJsonlEvents(
797
+ context.resolvedDiagnosticsEventsPath,
798
+ [...context.frameworkLog.events, ...context.userLog.events],
799
+ );
840
800
  }
841
- if (processSummaryArtifact) {
842
- copyIfExists(resolvedProcessSummaryPath, resolvedDiagnosticsProcessSummaryPath);
801
+ if (artifacts.processSummaryArtifact) {
802
+ copyIfExists(context.resolvedProcessSummaryPath, context.resolvedDiagnosticsProcessSummaryPath);
843
803
  const resolvedSamplesPath = resolveLinkedFilePath({
844
- linkedPath: processSummaryArtifact.samplesPath,
845
- workspace: resolvedWorkspace,
846
- cwd: resolvedCwd,
847
- fallbackDir: path.dirname(resolvedProcessSummaryPath),
804
+ linkedPath: artifacts.processSummaryArtifact.samplesPath,
805
+ workspace: context.resolvedWorkspace,
806
+ cwd: context.resolvedCwd,
807
+ fallbackDir: path.dirname(context.resolvedProcessSummaryPath),
848
808
  });
849
- copyIfExists(resolvedSamplesPath, resolvedDiagnosticsProcessSamplesPath);
809
+ copyIfExists(resolvedSamplesPath, context.resolvedDiagnosticsProcessSamplesPath);
850
810
  }
851
- copyIfExists(substages.sourcePath, substages.targetPath);
852
- if (sourceCheckoutArtifact) {
853
- copyIfExists(resolvedSourceCheckoutPath, resolvedDiagnosticsSourceCheckoutPath);
811
+ copyIfExists(artifacts.substages.sourcePath, artifacts.substages.targetPath);
812
+ if (artifacts.sourceCheckoutArtifact) {
813
+ copyIfExists(context.resolvedSourceCheckoutPath, context.resolvedDiagnosticsSourceCheckoutPath);
854
814
  }
855
- if (compilerCachePreparationArtifact) {
815
+ if (artifacts.compilerCachePreparationArtifact) {
856
816
  copyIfExists(
857
- resolvedCompilerCachePreparationPath,
858
- resolvedDiagnosticsCompilerCachePreparationPath,
817
+ context.resolvedCompilerCachePreparationPath,
818
+ context.resolvedDiagnosticsCompilerCachePreparationPath,
859
819
  );
860
820
  }
861
- writeDiagnosticsSidecarManifest(resolvedDiagnosticsManifestPath, {
862
- workspace: resolvedWorkspace,
863
- artifactName,
864
- platformId,
865
- diagnosticsArtifactName,
821
+ writeDiagnosticsSidecarManifest(context.resolvedDiagnosticsManifestPath, {
822
+ workspace: context.resolvedWorkspace,
823
+ artifactName: context.artifactName,
824
+ platformId: context.platformId,
825
+ diagnosticsArtifactName: context.diagnosticsArtifactName,
866
826
  files: [
867
- { kind: "diagnostics", filePath: resolvedDiagnosticsPath, required: true },
868
- { kind: "events", filePath: resolvedDiagnosticsEventsPath, required: true },
869
- { kind: "process-summary", filePath: resolvedDiagnosticsProcessSummaryPath },
870
- { kind: "process-samples", filePath: resolvedDiagnosticsProcessSamplesPath },
871
- substages.sidecar,
872
- { kind: "source-checkout", filePath: resolvedDiagnosticsSourceCheckoutPath },
873
- {
874
- kind: "compiler-cache-preparation",
875
- filePath: resolvedDiagnosticsCompilerCachePreparationPath,
876
- },
827
+ { kind: "diagnostics", filePath: context.resolvedDiagnosticsPath, required: true },
828
+ { kind: "events", filePath: context.resolvedDiagnosticsEventsPath, required: true },
829
+ { kind: "process-summary", filePath: context.resolvedDiagnosticsProcessSummaryPath },
830
+ { kind: "process-samples", filePath: context.resolvedDiagnosticsProcessSamplesPath },
831
+ artifacts.substages.sidecar,
832
+ { kind: "source-checkout", filePath: context.resolvedDiagnosticsSourceCheckoutPath },
833
+ { kind: "compiler-cache-preparation", filePath: context.resolvedDiagnosticsCompilerCachePreparationPath },
877
834
  ],
878
835
  });
879
- console.log(`buildchain_manifest=${path.relative(resolvedWorkspace, resolvedManifestPath)}`);
880
- return manifest;
836
+ console.log(`buildchain_manifest=${path.relative(context.resolvedWorkspace, context.resolvedManifestPath)}`);
837
+ return product.manifest;
838
+ }
839
+
840
+ export function runLifecycle(options = {}) {
841
+ const context = createLifecycleContext(normalizeLifecycleOptions(options));
842
+ executeLifecycle(context);
843
+ const artifacts = collectLifecycleArtifacts(context);
844
+ const product = createLifecycleManifest(context, artifacts);
845
+ return persistLifecycleDiagnostics(context, artifacts, product);
881
846
  }
882
847
 
883
848
  export function normalizeCommandStage(commandText) {