@empire-builder-kit/nx 1.0.0-rc.43 → 1.0.0-rc.45

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 (88) hide show
  1. package/package.json +3 -3
  2. package/src/blueprints/external-sandbox.d.ts +1 -1
  3. package/src/cli/main.d.ts +11 -5
  4. package/src/cli/main.js +88 -29
  5. package/src/container-images.d.ts +1 -1
  6. package/src/container-images.js +1 -1
  7. package/src/executors/deployment-plan/deployment-plan.js +5 -1
  8. package/src/executors/deployment-plan/schema.json +1 -1
  9. package/src/executors/fleet/fleet.js +4 -0
  10. package/src/executors/fleet/schema.json +1 -1
  11. package/src/executors/local-deploy/federated-credential-transport.d.ts +4 -3
  12. package/src/executors/local-deploy/federated-credential-transport.js +15 -5
  13. package/src/foundation/cost-estimate.d.ts +8 -3
  14. package/src/foundation/cost-estimate.js +42 -19
  15. package/src/foundation/index.d.ts +1 -0
  16. package/src/foundation/index.js +1 -0
  17. package/src/foundation/local-private-smoke-access.js +6 -0
  18. package/src/foundation/logging.d.ts +3 -1
  19. package/src/foundation/logging.js +8 -1
  20. package/src/foundation/observability.d.ts +42 -0
  21. package/src/foundation/observability.js +181 -0
  22. package/src/foundation/preflight.js +1 -1
  23. package/src/generators/function/function.js +5 -2
  24. package/src/generators/observability-infrastructure.d.ts +2 -0
  25. package/src/generators/observability-infrastructure.js +31 -0
  26. package/src/generators/observability-policy.d.ts +4 -0
  27. package/src/generators/observability-policy.js +23 -0
  28. package/src/generators/preset/dependency-overrides.d.ts +34 -0
  29. package/src/generators/preset/dependency-overrides.js +35 -1
  30. package/src/generators/preset/tool-versions.d.ts +2 -2
  31. package/src/generators/preset/tool-versions.js +2 -2
  32. package/src/generators/preset/workspace-files-adopter-skills.js +28 -17
  33. package/src/generators/preset/workspace-files-agent-development.d.ts +9 -0
  34. package/src/generators/preset/workspace-files-agent-development.js +42 -0
  35. package/src/generators/preset/workspace-files-thin-deploy.js +12 -3
  36. package/src/generators/preset/workspace-files-thin-docs.js +10 -22
  37. package/src/generators/preset/workspace-files.d.ts +3 -0
  38. package/src/generators/preset/workspace-files.js +93 -8
  39. package/src/generators/slice/built-in-plan-alarm-identity.d.ts +173 -0
  40. package/src/generators/slice/built-in-plan-alarm-identity.js +202 -0
  41. package/src/generators/slice/built-in-plan-api-contract-files.js +136 -0
  42. package/src/generators/slice/built-in-plan-database-lifecycle-files.js +1 -1
  43. package/src/generators/slice/built-in-plan-event-contract-literal.d.ts +6 -0
  44. package/src/generators/slice/built-in-plan-event-contract-literal.js +52 -0
  45. package/src/generators/slice/built-in-plan-infrastructure-files.js +304 -144
  46. package/src/generators/slice/built-in-plan-key-value-retention-infrastructure.js +2 -2
  47. package/src/generators/slice/built-in-plan-metadata-files.js +33 -1
  48. package/src/generators/slice/built-in-plan-operations-files.js +106 -6
  49. package/src/generators/slice/built-in-plan-project-files.js +1 -0
  50. package/src/generators/slice/built-in-plan-release-files.js +2 -43
  51. package/src/generators/slice/built-in-plan-reliability-files.js +222 -236
  52. package/src/generators/slice/built-in-plan-shared.d.ts +29 -3
  53. package/src/generators/slice/built-in-plan-shared.js +29 -2
  54. package/src/generators/slice/built-in-plan-web-files.js +18 -1
  55. package/src/generators/slice/built-in-plan.js +1 -0
  56. package/src/generators/slice/slice.js +2 -0
  57. package/src/generators/upgrade/upgrade.d.ts +4 -3
  58. package/src/generators/upgrade/upgrade.js +50 -26
  59. package/src/generators/workload/frozen-container.d.ts +1 -1
  60. package/src/generators/workload/service-performance-files.js +22 -5
  61. package/src/generators/workload/workload.js +5 -1
  62. package/src/local-dev/dev-command-core.d.ts +24 -3
  63. package/src/local-dev/dev-command-core.js +124 -12
  64. package/src/local-dev/errors.d.ts +19 -1
  65. package/src/local-dev/errors.js +18 -1
  66. package/src/local-dev/fleet-client.d.ts +64 -6
  67. package/src/local-dev/fleet-client.js +189 -15
  68. package/src/local-dev/fleet-process.d.ts +47 -2
  69. package/src/local-dev/fleet-process.js +248 -31
  70. package/src/local-dev/fleet-runtime.d.ts +37 -0
  71. package/src/local-dev/fleet-runtime.js +127 -69
  72. package/src/local-dev/fleet-session.d.ts +1 -0
  73. package/src/local-dev/fleet-session.js +42 -3
  74. package/src/local-dev/fleet-state.d.ts +5 -0
  75. package/src/local-dev/fleet-state.js +11 -2
  76. package/src/local-dev/fleet-supervisor.d.ts +6 -0
  77. package/src/local-dev/fleet-supervisor.js +49 -1
  78. package/src/local-dev/ports.d.ts +11 -1
  79. package/src/local-dev/ports.js +78 -38
  80. package/src/local-dev/slice-runner.d.ts +19 -1
  81. package/src/local-dev/slice-runner.js +290 -91
  82. package/src/repository-policy/deployment-plan.d.ts +1 -1
  83. package/src/repository-policy/deployment-plan.js +16 -1
  84. package/src/secrets/generated-aws-control-plane.d.ts +11 -1
  85. package/src/secrets/generated-aws-control-plane.js +92 -29
  86. package/src/secrets/operator.d.ts +3 -2
  87. package/src/secrets/operator.js +27 -5
  88. package/src/supply-chain/generated-files.js +9 -0
@@ -17,7 +17,7 @@ export declare const PRODUCT_VERSIONS: {
17
17
  readonly awsSts: "^3.700.0";
18
18
  readonly drizzle: "^0.45.2";
19
19
  readonly drizzleKit: "^0.31.4";
20
- readonly next: "16.3.6";
20
+ readonly next: "16.4.2";
21
21
  readonly pg: "^8.22.0";
22
22
  readonly playwright: "^1.59.1";
23
23
  readonly react: "19.2.8";
@@ -27,9 +27,35 @@ export declare const PRODUCT_VERSIONS: {
27
27
  readonly typesPg: "^8.15.5";
28
28
  readonly typesReact: "19.2.17";
29
29
  readonly typesReactDom: "19.2.3";
30
- readonly vitest: "4.1.4";
30
+ readonly vitest: "4.1.12";
31
31
  };
32
- export declare const PRODUCT_PACKAGE_MANAGED_JSON_POINTERS: readonly ["/name", "/version", "/private", "/dependencies/@aws-sdk~1client-appconfigdata", "/dependencies/@aws-sdk~1client-cloudwatch", "/dependencies/@aws-sdk~1client-cloudwatch-logs", "/dependencies/@aws-sdk~1client-cost-explorer", "/dependencies/@aws-sdk~1client-cognito-identity-provider", "/dependencies/@aws-sdk~1client-dynamodb", "/dependencies/@aws-sdk~1client-ecs", "/dependencies/@aws-sdk~1client-eventbridge", "/dependencies/@aws-sdk~1client-s3", "/dependencies/@aws-sdk~1client-secrets-manager", "/dependencies/@aws-sdk~1client-sfn", "/dependencies/@aws-sdk~1client-sqs", "/dependencies/@aws-sdk~1rds-signer", "/dependencies/@aws-sdk~1client-ssm", "/dependencies/@aws-sdk~1client-sts", "/dependencies/@empire-builder-kit~1runtime", "/dependencies/drizzle-orm", "/dependencies/next", "/dependencies/pg", "/dependencies/react", "/dependencies/react-dom", "/dependencies/server-only", "/devDependencies/@axe-core~1playwright", "/devDependencies/@playwright~1test", "/devDependencies/@types~1node", "/devDependencies/@types~1pg", "/devDependencies/@types~1react", "/devDependencies/@types~1react-dom", "/devDependencies/drizzle-kit", "/devDependencies/vitest", "/exports/.~1api-client", "/exports/.~1api-contract", "/exports/.~1contracts"];
32
+ /**
33
+ * Exact managed builder: declared as a Slice devDependency and run from the
34
+ * Slice's installed node_modules slot after its package metadata matches. The
35
+ * wrapper does not read the lockfile; the frozen pnpm install governs what is
36
+ * installed in that slot.
37
+ */
38
+ export declare const OPEN_NEXT_AWS_VERSION = "4.1.12";
39
+ /**
40
+ * The sharp release OpenNext installs into the image-optimization Function.
41
+ * OpenNext installs that Function's packages with npm during its build,
42
+ * outside the Slice lockfile and every lockfile gate. Without
43
+ * `imageOptimization.install` it selects its own Sharp release with
44
+ * `--arch=arm64` (OpenNext createImageOptimizationBundle and installDeps), and
45
+ * npm 10 and 11 ignore `--arch` when they select sharp's native package, so
46
+ * the build host's CPU wins. The generated web/open-next.config.ts therefore
47
+ * sets `imageOptimization.install` with this release and `--cpu=arm64`.
48
+ */
49
+ export declare const OPEN_NEXT_IMAGE_OPTIMIZATION_SHARP_VERSION = "0.35.5";
50
+ /**
51
+ * The libvips package and library that sharp 0.35.5 requires for Linux arm64:
52
+ * it pins `@img/sharp-libvips-linux-arm64` 1.3.4 exactly, which exports
53
+ * `./binary` as `./lib/libvips-cpp.so.8.18.7`. The build wrapper's native
54
+ * check requires both, so they move with the sharp pin above.
55
+ */
56
+ export declare const OPEN_NEXT_IMAGE_OPTIMIZATION_LIBVIPS_VERSION = "1.3.4";
57
+ export declare const OPEN_NEXT_IMAGE_OPTIMIZATION_LIBVIPS_LIBRARY = "libvips-cpp.so.8.18.7";
58
+ export declare const PRODUCT_PACKAGE_MANAGED_JSON_POINTERS: readonly ["/name", "/version", "/private", "/dependencies/@aws-sdk~1client-appconfigdata", "/dependencies/@aws-sdk~1client-cloudwatch", "/dependencies/@aws-sdk~1client-cloudwatch-logs", "/dependencies/@aws-sdk~1client-cost-explorer", "/dependencies/@aws-sdk~1client-cognito-identity-provider", "/dependencies/@aws-sdk~1client-dynamodb", "/dependencies/@aws-sdk~1client-ecs", "/dependencies/@aws-sdk~1client-eventbridge", "/dependencies/@aws-sdk~1client-s3", "/dependencies/@aws-sdk~1client-secrets-manager", "/dependencies/@aws-sdk~1client-sfn", "/dependencies/@aws-sdk~1client-sqs", "/dependencies/@aws-sdk~1rds-signer", "/dependencies/@aws-sdk~1client-ssm", "/dependencies/@aws-sdk~1client-sts", "/dependencies/@empire-builder-kit~1runtime", "/dependencies/drizzle-orm", "/dependencies/next", "/dependencies/pg", "/dependencies/react", "/dependencies/react-dom", "/dependencies/server-only", "/devDependencies/@axe-core~1playwright", "/devDependencies/@playwright~1test", "/devDependencies/@opennextjs~1aws", "/devDependencies/@types~1node", "/devDependencies/@types~1pg", "/devDependencies/@types~1react", "/devDependencies/@types~1react-dom", "/devDependencies/drizzle-kit", "/devDependencies/vitest", "/exports/.~1api-client", "/exports/.~1api-contract", "/exports/.~1contracts"];
33
59
  export declare function standardPackageManagedJsonPointers(sql: boolean): string[];
34
60
  export declare const STANDARD_LOCAL_DEV_ADAPTER: (name: string, dependencySlices?: unknown, sql?: boolean) => {
35
61
  dependencySlices: string[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.STANDARD_LOCAL_DEV_ADAPTER = exports.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS = exports.PRODUCT_VERSIONS = void 0;
3
+ exports.STANDARD_LOCAL_DEV_ADAPTER = exports.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS = exports.OPEN_NEXT_IMAGE_OPTIMIZATION_LIBVIPS_LIBRARY = exports.OPEN_NEXT_IMAGE_OPTIMIZATION_LIBVIPS_VERSION = exports.OPEN_NEXT_IMAGE_OPTIMIZATION_SHARP_VERSION = exports.OPEN_NEXT_AWS_VERSION = exports.PRODUCT_VERSIONS = void 0;
4
4
  exports.standardPackageManagedJsonPointers = standardPackageManagedJsonPointers;
5
5
  exports.json = json;
6
6
  exports.lowerCamelIdentifier = lowerCamelIdentifier;
@@ -27,7 +27,7 @@ exports.PRODUCT_VERSIONS = {
27
27
  awsSts: '^3.700.0',
28
28
  drizzle: '^0.45.2',
29
29
  drizzleKit: '^0.31.4',
30
- next: '16.3.6',
30
+ next: '16.4.2',
31
31
  pg: '^8.22.0',
32
32
  playwright: '^1.59.1',
33
33
  react: '19.2.8',
@@ -39,6 +39,32 @@ exports.PRODUCT_VERSIONS = {
39
39
  typesReactDom: '19.2.3',
40
40
  vitest: tool_versions_js_1.WORKSPACE_VITEST_VERSION,
41
41
  };
42
+ /**
43
+ * Exact managed builder: declared as a Slice devDependency and run from the
44
+ * Slice's installed node_modules slot after its package metadata matches. The
45
+ * wrapper does not read the lockfile; the frozen pnpm install governs what is
46
+ * installed in that slot.
47
+ */
48
+ exports.OPEN_NEXT_AWS_VERSION = '4.1.12';
49
+ /**
50
+ * The sharp release OpenNext installs into the image-optimization Function.
51
+ * OpenNext installs that Function's packages with npm during its build,
52
+ * outside the Slice lockfile and every lockfile gate. Without
53
+ * `imageOptimization.install` it selects its own Sharp release with
54
+ * `--arch=arm64` (OpenNext createImageOptimizationBundle and installDeps), and
55
+ * npm 10 and 11 ignore `--arch` when they select sharp's native package, so
56
+ * the build host's CPU wins. The generated web/open-next.config.ts therefore
57
+ * sets `imageOptimization.install` with this release and `--cpu=arm64`.
58
+ */
59
+ exports.OPEN_NEXT_IMAGE_OPTIMIZATION_SHARP_VERSION = '0.35.5';
60
+ /**
61
+ * The libvips package and library that sharp 0.35.5 requires for Linux arm64:
62
+ * it pins `@img/sharp-libvips-linux-arm64` 1.3.4 exactly, which exports
63
+ * `./binary` as `./lib/libvips-cpp.so.8.18.7`. The build wrapper's native
64
+ * check requires both, so they move with the sharp pin above.
65
+ */
66
+ exports.OPEN_NEXT_IMAGE_OPTIMIZATION_LIBVIPS_VERSION = '1.3.4';
67
+ exports.OPEN_NEXT_IMAGE_OPTIMIZATION_LIBVIPS_LIBRARY = 'libvips-cpp.so.8.18.7';
42
68
  exports.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS = [
43
69
  '/name',
44
70
  '/version',
@@ -67,6 +93,7 @@ exports.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS = [
67
93
  '/dependencies/server-only',
68
94
  '/devDependencies/@axe-core~1playwright',
69
95
  '/devDependencies/@playwright~1test',
96
+ '/devDependencies/@opennextjs~1aws',
70
97
  '/devDependencies/@types~1node',
71
98
  '/devDependencies/@types~1pg',
72
99
  '/devDependencies/@types~1react',
@@ -131,6 +131,7 @@ export function proxy(request: NextRequest): NextResponse {
131
131
  }
132
132
  `,
133
133
  'web/src/lib/server-logging.ts': `import 'server-only';
134
+ import { randomUUID } from 'node:crypto';
134
135
  import { createLogger, type Logger } from '@empire-builder-kit/runtime/logging';
135
136
  import { createNextServerContext, type RequestContext } from '@empire-builder-kit/runtime/request-context';
136
137
  import { recordReliabilityOperation } from '../../../reliability/metrics';
@@ -167,6 +168,7 @@ export async function observeNextOperation({
167
168
  context,
168
169
  feature,
169
170
  operation,
171
+ routineSamplingId: randomUUID(),
170
172
  slice: '${name}',
171
173
  stage,
172
174
  workspace: '${workspace}',
@@ -189,13 +191,16 @@ export async function observeNextOperation({
189
191
  outcome,
190
192
  });
191
193
  };
192
- logger.info('${name} Next.js operation received');
193
194
  try {
195
+ logger.info('${name} Next.js operation started', {
196
+ routineRequestStart: true,
197
+ });
194
198
  const response = await handle(logger, context);
195
199
  recordOutcome(response.status < 400 ? 'success' : 'failure');
196
200
  logger.info('${name} Next.js operation completed', {
197
201
  attributes: { httpStatus: response.status },
198
202
  outcome: response.status < 400 ? 'success' : 'failure',
203
+ routineSuccess: response.status < 400 ? true : undefined,
199
204
  });
200
205
  return response;
201
206
  } catch (error) {
@@ -213,6 +218,18 @@ export async function observeNextOperation({
213
218
  // builds only this application instead of recursively invoking the Nx root.
214
219
  buildCommand: 'pnpm exec next build --webpack web',
215
220
  default: {},
221
+ // OpenNext installs the image-optimization Function's sharp with npm during
222
+ // the build, outside the lockfile. The Function runs on arm64 Linux (glibc).
223
+ // npm selects sharp's native package by --cpu and ignores OpenNext's --arch,
224
+ // so name the CPU here instead of inheriting the build host's.
225
+ imageOptimization: {
226
+ install: {
227
+ additionalArgs: '--cpu=arm64',
228
+ libc: 'glibc',
229
+ os: 'linux',
230
+ packages: ['sharp@${built_in_plan_shared_js_1.OPEN_NEXT_IMAGE_OPTIMIZATION_SHARP_VERSION}'],
231
+ },
232
+ },
216
233
  packageJsonPath: '../package.json',
217
234
  };
218
235
 
@@ -175,6 +175,7 @@ function renderSliceFiles(name, scope, runtimeVersion, ownership, dataPolicyRevi
175
175
  function classifyPaths(files, sql) {
176
176
  const seededPaths = new Set([
177
177
  'operations/background-work.json',
178
+ 'reliability/metric-declarations.ts',
178
179
  'README.md',
179
180
  'api/data-retention.ts',
180
181
  'async/recovery-adapters.ts',
@@ -21,6 +21,7 @@ const workspace_files_js_1 = require("../preset/workspace-files.js");
21
21
  const built_in_plan_js_1 = require("./built-in-plan.js");
22
22
  const data_policy_review_seed_js_1 = require("./data-policy-review-seed.js");
23
23
  const tree_policy_js_1 = require("../repository-policy/tree-policy.js");
24
+ const observability_policy_js_1 = require("../observability-policy.js");
24
25
  var built_in_plan_js_2 = require("./built-in-plan.js");
25
26
  Object.defineProperty(exports, "PRODUCT_PACKAGE_MANAGED_JSON_POINTERS", { enumerable: true, get: function () { return built_in_plan_js_2.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS; } });
26
27
  Object.defineProperty(exports, "STANDARD_LOCAL_DEV_ADAPTER", { enumerable: true, get: function () { return built_in_plan_js_2.STANDARD_LOCAL_DEV_ADAPTER; } });
@@ -176,6 +177,7 @@ function parseBlueprintInputs(inputs) {
176
177
  }
177
178
  async function sliceGenerator(tree, options) {
178
179
  const name = requireSliceName(options.name);
180
+ (0, observability_policy_js_1.requireObservabilityPolicyFromTree)(tree);
179
181
  const root = node_path_1.posix.join('packages', name);
180
182
  const blueprintReference = options.blueprint ?? 'standard';
181
183
  const parsedInputs = parseBlueprintInputs(options.inputs);
@@ -54,13 +54,14 @@ export interface UpgradeReport {
54
54
  unchanged: string[];
55
55
  }
56
56
  export interface SeededReconciliationWork {
57
- adopterContentSha256: string;
58
- category: 'async-adapter' | 'async-settings' | 'configuration-contract' | 'configuration-values' | 'feature-controls' | 'frontend-contract' | 'frontend-security' | 'performance-aggregate-provider' | 'performance-policy' | 'reliability-operations' | 'reliability-slo' | 'release-controls' | 'secret-contract';
57
+ adopterContentSha256: string | null;
58
+ category: 'async-adapter' | 'async-settings' | 'configuration-contract' | 'configuration-values' | 'feature-controls' | 'frontend-contract' | 'frontend-security' | 'performance-aggregate-provider' | 'performance-policy' | 'reliability-metrics' | 'reliability-operations' | 'reliability-slo' | 'release-controls' | 'secret-contract';
59
59
  currentFrameworkSha256: string | null;
60
+ guidance?: string;
60
61
  implications: string[];
61
62
  markerReference: 'PLAN:5.6/seeded-upgrade-reconciliation';
62
63
  path: string;
63
- requiredAction: 'review-and-reconcile-preserving-adopter-content';
64
+ requiredAction: 'declare-existing-custom-metric-series-before-promotion' | 'review-and-reconcile-preserving-adopter-content';
64
65
  targetFrameworkSha256: string;
65
66
  }
66
67
  interface JsonOwnershipChanges {
@@ -11,7 +11,9 @@ exports.upgradeGenerator = upgradeGenerator;
11
11
  const deterministic_order_js_1 = require("../../deterministic-order.js");
12
12
  const capacity_migration_js_1 = require("../../repository-policy/capacity-migration.js");
13
13
  const dependency_overrides_js_1 = require("../preset/dependency-overrides.js");
14
+ const observability_js_1 = require("../../foundation/observability.js");
14
15
  const workspace_files_adopter_skills_js_1 = require("../preset/workspace-files-adopter-skills.js");
16
+ const observability_policy_js_1 = require("../observability-policy.js");
15
17
  const sql_seeded_reconciliation_js_1 = require("./sql-seeded-reconciliation.js");
16
18
  const devkit_1 = require("@nx/devkit");
17
19
  const node_buffer_1 = require("node:buffer");
@@ -25,7 +27,8 @@ const index_js_2 = require("../../api-contract/index.js");
25
27
  const index_js_3 = require("../../foundation/index.js");
26
28
  const capability_plan_js_1 = require("../../foundation/capability-plan.js");
27
29
  const persistence_contract_js_1 = require("../slice/persistence-contract.js");
28
- const index_js_4 = require("../../ownership/index.js");
30
+ const index_js_4 = require("../../repository-policy/index.js");
31
+ const index_js_5 = require("../../ownership/index.js");
29
32
  const function_js_1 = require("../function/function.js");
30
33
  const logging_registry_js_1 = require("../logging-registry.js");
31
34
  const feature_registry_js_1 = require("../feature-registry.js");
@@ -380,6 +383,15 @@ const SEEDED_RECONCILIATION = {
380
383
  'journey-authority',
381
384
  ],
382
385
  },
386
+ 'reliability/metric-declarations.ts': {
387
+ category: 'reliability-metrics',
388
+ guidance: 'Review existing custom recordReliabilityOperation calls and declare each finite deployment-owned component/feature/operation tuple in reliability/metric-declarations.ts. Undeclared custom series are dropped by the managed recorder. Never derive declarations from request, user, resource, or correlation IDs. Preserve existing declarations, verify custom metric emission, retain evidence, and resolve the seeded reconciliation marker before protected promotion.',
389
+ implications: [
390
+ 'custom-metric-series-allowlist',
391
+ 'finite-deployment-owned-dimensions',
392
+ 'undeclared-custom-series-are-dropped',
393
+ ],
394
+ },
383
395
  'secrets/declarations.ts': {
384
396
  category: 'secret-contract',
385
397
  implications: [
@@ -667,7 +679,7 @@ function preserveBuiltInDerivedApiArtifacts(tree, root, currentOwnership, target
667
679
  entry?.mode === 'managed' &&
668
680
  entry.origin === 'blueprint' &&
669
681
  entry.managedJsonPointers === undefined &&
670
- (0, index_js_4.hashOwnedContent)(current, entry) === entry.sha256);
682
+ (0, index_js_5.hashOwnedContent)(current, entry) === entry.sha256);
671
683
  if (!completeCleanPair)
672
684
  return targetFiles;
673
685
  const retained = { ...targetFiles };
@@ -821,16 +833,17 @@ function ownershipValidationMessage(label, issues) {
821
833
  }
822
834
  function requireUpgradePrerequisites(tree, target) {
823
835
  const installedVersion = (0, generator_js_1.frameworkPackageVersion)();
824
- const workspaceResult = (0, index_js_4.validateWorkspaceOwnershipRecord)(readJson(tree, '.ebk/ownership.json', 'Workspace ownership metadata'));
836
+ const workspaceResult = (0, index_js_5.validateWorkspaceOwnershipRecord)(readJson(tree, '.ebk/ownership.json', 'Workspace ownership metadata'));
825
837
  if (!workspaceResult.valid) {
826
838
  throw new Error(ownershipValidationMessage('Workspace ownership metadata', workspaceResult.issues));
827
839
  }
828
840
  if (workspaceResult.value.frameworkVersion !== installedVersion) {
829
841
  throw new Error(`Workspace tooling is recorded at ${workspaceResult.value.frameworkVersion}, but the installed @empire-builder-kit/nx version is ${installedVersion}. Report and apply the workspace upgrade before upgrading the ${target === 'foundation' ? 'Standard Foundation' : 'Product Slice'}.`);
830
842
  }
843
+ (0, observability_policy_js_1.requireObservabilityPolicyFromTree)(tree);
831
844
  if (target === 'foundation')
832
845
  return;
833
- const foundationResult = (0, index_js_4.validateFoundationOwnershipRecord)(readJson(tree, 'packages/foundation/.ebk/ownership.json', 'Standard Foundation ownership metadata'));
846
+ const foundationResult = (0, index_js_5.validateFoundationOwnershipRecord)(readJson(tree, 'packages/foundation/.ebk/ownership.json', 'Standard Foundation ownership metadata'));
834
847
  if (!foundationResult.valid) {
835
848
  throw new Error(ownershipValidationMessage('Standard Foundation ownership metadata', foundationResult.issues));
836
849
  }
@@ -959,21 +972,29 @@ function createUpgradeReport(currentFiles, currentOwnership, targetFiles, target
959
972
  path.startsWith('database/migrations/')) {
960
973
  report.incompatibleSeededMigrations.push(path);
961
974
  }
962
- else if (current !== null &&
963
- currentEntry?.sha256 !== targetSha256 &&
975
+ else if (((current !== null && currentEntry?.sha256 !== targetSha256) ||
976
+ (current === null &&
977
+ path === 'reliability/metric-declarations.ts')) &&
964
978
  seededReconciliationDefinition(path) !== null) {
965
979
  const reconciliation = seededReconciliationDefinition(path);
966
980
  if (reconciliation === null) {
967
981
  throw new Error(`Missing seeded reconciliation definition for ${path}.`);
968
982
  }
969
983
  report.seededReconciliation.push({
970
- adopterContentSha256: (0, index_js_4.hashOwnedContent)(current, currentEntry ?? targetEntry),
984
+ adopterContentSha256: current === null
985
+ ? null
986
+ : (0, index_js_5.hashOwnedContent)(current, currentEntry ?? targetEntry),
971
987
  category: reconciliation.category,
972
988
  currentFrameworkSha256: currentEntry?.sha256 ?? null,
989
+ ...('guidance' in reconciliation
990
+ ? { guidance: reconciliation.guidance }
991
+ : {}),
973
992
  implications: [...reconciliation.implications],
974
993
  markerReference: SEEDED_RECONCILIATION_MARKER_REFERENCE,
975
994
  path,
976
- requiredAction: 'review-and-reconcile-preserving-adopter-content',
995
+ requiredAction: current === null
996
+ ? 'declare-existing-custom-metric-series-before-promotion'
997
+ : 'review-and-reconcile-preserving-adopter-content',
977
998
  targetFrameworkSha256: targetSha256,
978
999
  });
979
1000
  }
@@ -982,7 +1003,7 @@ function createUpgradeReport(currentFiles, currentOwnership, targetFiles, target
982
1003
  report.missing.push(path);
983
1004
  }
984
1005
  else if (currentEntry !== undefined &&
985
- (0, index_js_4.hashOwnedContent)(current, currentEntry) !== currentEntry.sha256) {
1006
+ (0, index_js_5.hashOwnedContent)(current, currentEntry) !== currentEntry.sha256) {
986
1007
  report.conflicting.push(path);
987
1008
  }
988
1009
  else if (current === target) {
@@ -1005,7 +1026,7 @@ function createUpgradeReport(currentFiles, currentOwnership, targetFiles, target
1005
1026
  const current = currentFiles.get(path) ?? null;
1006
1027
  if (current === null)
1007
1028
  continue;
1008
- if ((0, index_js_4.hashOwnedContent)(current, entry) === sha256) {
1029
+ if ((0, index_js_5.hashOwnedContent)(current, entry) === sha256) {
1009
1030
  report.obsolete.push(path);
1010
1031
  }
1011
1032
  else if (!report.conflicting.includes(path)) {
@@ -1060,7 +1081,7 @@ function mergeStructuredTargetFiles(currentFiles, currentOwnership, targetFiles,
1060
1081
  if (!targetEntry.managedJsonPointers)
1061
1082
  continue;
1062
1083
  if (currentEntry?.managedJsonPointers) {
1063
- const transition = (0, index_js_4.analyzeManagedJsonPointerTransition)(current, target, currentEntry.managedJsonPointers, targetEntry.managedJsonPointers);
1084
+ const transition = (0, index_js_5.analyzeManagedJsonPointerTransition)(current, target, currentEntry.managedJsonPointers, targetEntry.managedJsonPointers);
1064
1085
  changes.claimedJsonMembers.push(...transition.claimed.map((pointer) => `${targetEntry.path}#${pointer}`));
1065
1086
  changes.conflictingJsonMembers.push(...transition.conflictingClaims.map((pointer) => `${targetEntry.path}#${pointer}`));
1066
1087
  changes.releasedJsonMembers.push(...transition.released.map((pointer) => `${targetEntry.path}#${pointer}`));
@@ -1069,7 +1090,7 @@ function mergeStructuredTargetFiles(currentFiles, currentOwnership, targetFiles,
1069
1090
  continue;
1070
1091
  }
1071
1092
  }
1072
- files.set(targetEntry.path, (0, index_js_4.mergeManagedJsonContents)(current, target, targetEntry.managedJsonPointers));
1093
+ files.set(targetEntry.path, (0, index_js_5.mergeManagedJsonContents)(current, target, targetEntry.managedJsonPointers));
1073
1094
  }
1074
1095
  return { files, ...changes };
1075
1096
  }
@@ -1107,7 +1128,7 @@ function renderCompositionUpgradePlan(ownership, workspace, runtimeVersion, serv
1107
1128
  mode: entry.mode ?? 'managed',
1108
1129
  origin: 'composition',
1109
1130
  path: entry.path,
1110
- sha256: (0, index_js_4.hashOwnedContent)(contents, entry),
1131
+ sha256: (0, index_js_5.hashOwnedContent)(contents, entry),
1111
1132
  });
1112
1133
  }
1113
1134
  };
@@ -1251,7 +1272,7 @@ async function upgradeFoundation(tree, options, packageJson, output, foundationR
1251
1272
  throw new Error('Standard Foundation upgrades do not accept Blueprint or input options.');
1252
1273
  }
1253
1274
  const root = 'packages/foundation';
1254
- const ownershipResult = (0, index_js_4.validateFoundationOwnershipRecord)(readJson(tree, node_path_1.posix.join(root, '.ebk/ownership.json'), 'Standard Foundation ownership metadata'));
1275
+ const ownershipResult = (0, index_js_5.validateFoundationOwnershipRecord)(readJson(tree, node_path_1.posix.join(root, '.ebk/ownership.json'), 'Standard Foundation ownership metadata'));
1255
1276
  if (!ownershipResult.valid) {
1256
1277
  throw new Error(ownershipValidationMessage('Standard Foundation ownership metadata', ownershipResult.issues));
1257
1278
  }
@@ -1271,7 +1292,7 @@ async function upgradeFoundation(tree, options, packageJson, output, foundationR
1271
1292
  ...renderedTarget,
1272
1293
  files: await formatRenderedFiles(tree, renderedTarget.files, root),
1273
1294
  };
1274
- const targetValidation = (0, index_js_4.validateFoundationOwnershipRecord)(target.ownership);
1295
+ const targetValidation = (0, index_js_5.validateFoundationOwnershipRecord)(target.ownership);
1275
1296
  if (!targetValidation.valid) {
1276
1297
  throw new Error(`Target Standard Foundation ownership metadata is invalid:\n${targetValidation.issues
1277
1298
  .map((issue) => `- ${issue.path}: ${issue.message}`)
@@ -1312,7 +1333,7 @@ async function upgradeFoundation(tree, options, packageJson, output, foundationR
1312
1333
  }
1313
1334
  tree.write(node_path_1.posix.join(root, path), contents);
1314
1335
  }
1315
- (0, index_js_4.restampFoundationOwnership)(tree);
1336
+ (0, index_js_5.restampFoundationOwnership)(tree);
1316
1337
  // Ownership bytes are part of the upgrade result, including agent previews
1317
1338
  // that skip workspace formatting. Canonicalize before binding those bytes.
1318
1339
  await formatOwnershipRecord(tree, node_path_1.posix.join(root, '.ebk/ownership.json'), 'Standard Foundation');
@@ -1339,7 +1360,7 @@ async function upgradeWorkspace(tree, options, packageJson, output) {
1339
1360
  if (options.blueprint !== undefined || options.inputs !== undefined) {
1340
1361
  throw new Error('Workspace upgrades do not accept Blueprint or input options.');
1341
1362
  }
1342
- const ownershipResult = (0, index_js_4.validateWorkspaceOwnershipRecord)(readJson(tree, '.ebk/ownership.json', 'Workspace ownership metadata'));
1363
+ const ownershipResult = (0, index_js_5.validateWorkspaceOwnershipRecord)(readJson(tree, '.ebk/ownership.json', 'Workspace ownership metadata'));
1343
1364
  if (!ownershipResult.valid) {
1344
1365
  throw new Error(ownershipValidationMessage('Workspace ownership metadata', ownershipResult.issues));
1345
1366
  }
@@ -1354,6 +1375,9 @@ async function upgradeWorkspace(tree, options, packageJson, output) {
1354
1375
  dependencyOverrides: tree.exists(dependency_overrides_js_1.DEPENDENCY_OVERRIDES_PATH)
1355
1376
  ? readJson(tree, dependency_overrides_js_1.DEPENDENCY_OVERRIDES_PATH, 'Dependency overrides')
1356
1377
  : undefined,
1378
+ observabilityPolicy: tree.exists(observability_js_1.OBSERVABILITY_POLICY_PATH)
1379
+ ? readJson(tree, observability_js_1.OBSERVABILITY_POLICY_PATH, 'Observability policy')
1380
+ : (0, observability_js_1.defaultObservabilityPolicy)((0, index_js_4.activeDeploymentStages)(deployment.deploymentProfile ?? 'starter'), { preserveLegacy: true }),
1357
1381
  frameworkVersion: (0, generator_js_1.frameworkPackageVersion)(),
1358
1382
  name: packageJson.name,
1359
1383
  });
@@ -1361,7 +1385,7 @@ async function upgradeWorkspace(tree, options, packageJson, output) {
1361
1385
  ...renderedTarget,
1362
1386
  files: await formatRenderedFiles(tree, renderedTarget.files),
1363
1387
  };
1364
- const targetValidation = (0, index_js_4.validateWorkspaceOwnershipRecord)(target.ownership);
1388
+ const targetValidation = (0, index_js_5.validateWorkspaceOwnershipRecord)(target.ownership);
1365
1389
  if (!targetValidation.valid) {
1366
1390
  throw new Error('Target workspace ownership metadata is invalid.');
1367
1391
  }
@@ -1417,7 +1441,7 @@ async function upgradeWorkspace(tree, options, packageJson, output) {
1417
1441
  if (developerAgentInstructionAppend !== null) {
1418
1442
  tree.write(developerAgentInstructionAppend.path, developerAgentInstructionAppend.contents);
1419
1443
  }
1420
- (0, index_js_4.restampWorkspaceOwnership)(tree);
1444
+ (0, index_js_5.restampWorkspaceOwnership)(tree);
1421
1445
  await formatOwnershipRecord(tree, '.ebk/ownership.json', 'Workspace');
1422
1446
  }
1423
1447
  async function executeUpgradeGenerator(tree, options, output = devkit_1.logger, executionOptions = {}) {
@@ -1445,7 +1469,7 @@ async function executeUpgradeGenerator(tree, options, output = devkit_1.logger,
1445
1469
  if (recorded?.blueprint
1446
1470
  ?.name !== index_js_1.BUILTIN_BLUEPRINT_NAME)
1447
1471
  continue;
1448
- const parsed = (0, index_js_4.validateGeneratedOwnershipRecord)(recorded);
1472
+ const parsed = (0, index_js_5.validateGeneratedOwnershipRecord)(recorded);
1449
1473
  if (!parsed.valid)
1450
1474
  throw new Error(ownershipValidationMessage('Product Slice ownership metadata', parsed.issues));
1451
1475
  (0, persistence_contract_js_1.standardPersistenceContract)({
@@ -1462,7 +1486,7 @@ async function executeUpgradeGenerator(tree, options, output = devkit_1.logger,
1462
1486
  }
1463
1487
  requireUpgradePrerequisites(tree, 'product-slice');
1464
1488
  const root = node_path_1.posix.join('packages', name);
1465
- const ownershipResult = (0, index_js_4.validateGeneratedOwnershipRecord)(readJson(tree, node_path_1.posix.join(root, '.ebk/ownership.json'), 'Product Slice ownership metadata'));
1489
+ const ownershipResult = (0, index_js_5.validateGeneratedOwnershipRecord)(readJson(tree, node_path_1.posix.join(root, '.ebk/ownership.json'), 'Product Slice ownership metadata'));
1466
1490
  if (!ownershipResult.valid) {
1467
1491
  throw new Error(ownershipValidationMessage('Product Slice ownership metadata', ownershipResult.issues));
1468
1492
  }
@@ -1609,7 +1633,7 @@ async function executeUpgradeGenerator(tree, options, output = devkit_1.logger,
1609
1633
  mode,
1610
1634
  origin: 'blueprint',
1611
1635
  path,
1612
- sha256: (0, index_js_4.hashOwnedContent)(contents, { managedJsonPointers }),
1636
+ sha256: (0, index_js_5.hashOwnedContent)(contents, { managedJsonPointers }),
1613
1637
  }));
1614
1638
  paths.sort((left, right) => (0, deterministic_order_js_1.compareUtf16)(left.path, right.path));
1615
1639
  targetOwnership = {
@@ -1623,7 +1647,7 @@ async function executeUpgradeGenerator(tree, options, output = devkit_1.logger,
1623
1647
  inputs: inputResult.value,
1624
1648
  paths,
1625
1649
  projects: generated.projects,
1626
- schemaVersion: index_js_4.GENERATED_OWNERSHIP_SCHEMA_VERSION,
1650
+ schemaVersion: index_js_5.GENERATED_OWNERSHIP_SCHEMA_VERSION,
1627
1651
  slice: name,
1628
1652
  verification: blueprint.manifest.verification,
1629
1653
  };
@@ -1677,7 +1701,7 @@ async function executeUpgradeGenerator(tree, options, output = devkit_1.logger,
1677
1701
  if (contents === undefined) {
1678
1702
  throw new Error(`Target Blueprint did not render ${entry.path}.`);
1679
1703
  }
1680
- return { ...entry, sha256: (0, index_js_4.hashOwnedContent)(contents, entry) };
1704
+ return { ...entry, sha256: (0, index_js_5.hashOwnedContent)(contents, entry) };
1681
1705
  }),
1682
1706
  projects: [
1683
1707
  ...new Set([...targetOwnership.projects, ...currentOwnership.projects]),
@@ -1687,7 +1711,7 @@ async function executeUpgradeGenerator(tree, options, output = devkit_1.logger,
1687
1711
  ...targetFiles,
1688
1712
  '.ebk/ownership.json': json(targetOwnership),
1689
1713
  };
1690
- const targetValidation = (0, index_js_4.validateGeneratedOwnershipRecord)(targetOwnership);
1714
+ const targetValidation = (0, index_js_5.validateGeneratedOwnershipRecord)(targetOwnership);
1691
1715
  if (!targetValidation.valid) {
1692
1716
  throw new Error(`Target ownership metadata is invalid:\n${targetValidation.issues
1693
1717
  .map((issue) => `- ${issue.path}: ${issue.message}`)
@@ -1774,7 +1798,7 @@ async function executeUpgradeGenerator(tree, options, output = devkit_1.logger,
1774
1798
  await (0, formatting_js_1.formatTreeFileToFixedPoint)(tree, path);
1775
1799
  }
1776
1800
  }
1777
- (0, index_js_4.restampProductSliceOwnership)(tree, name, { preserveSeeded: true });
1801
+ (0, index_js_5.restampProductSliceOwnership)(tree, name, { preserveSeeded: true });
1778
1802
  await formatOwnershipRecord(tree, node_path_1.posix.join(root, '.ebk/ownership.json'), 'Product Slice');
1779
1803
  return options.skipInstall
1780
1804
  ? undefined
@@ -1,4 +1,4 @@
1
- export declare const WORKLOAD_CONTAINER_NODE_IMAGE: "node:22-alpine@sha256:0a7108bf6c7bf5de370ffb1a3ed6be93d405b43ff159f681a8d18c0e2bc2e402";
1
+ export declare const WORKLOAD_CONTAINER_NODE_IMAGE: "node:22-alpine@sha256:fe4f6d74e20370acb04ad889077d14d0f64a9c8ea6a42bc60cddf1e844699914";
2
2
  export declare const WORKLOAD_CONTAINER_PNPM_VERSION: "11.20.0";
3
3
  export declare const WORKLOAD_CONTAINER_PNPM_DESCRIPTOR: "pnpm@11.20.0+sha512.9a6f330a95b66446ea088faf1521405a8a01f07fde7124cc9958dfed52d4bb436737e65b08f85f37b46fcba375092558ac51262b816844b22f63406ed166bfee";
4
4
  export declare const WORKLOAD_CONTAINER_PNPM_STORE = "/workspace/.ebk/cache/pnpm-store";
@@ -1654,9 +1654,21 @@ describe('${input.workload} protected Service performance runtime', () => {
1654
1654
  );
1655
1655
  try {
1656
1656
  if (!server.listening) await once(server, 'listening');
1657
+ // start() keeps the production dual-stack wildcard bind. A wildcard
1658
+ // port can coincide with a foreign 127.0.0.1 listener that the loopback
1659
+ // probe would reach instead, so rebind this test server on 127.0.0.1.
1660
+ await new Promise<void>((resolve, reject) =>
1661
+ server.close((error) => (error ? reject(error) : resolve())),
1662
+ );
1663
+ server.listen({ host: '127.0.0.1', port: 0 });
1664
+ await once(server, 'listening');
1657
1665
  const address = server.address();
1658
- if (!address || typeof address === 'string') {
1659
- throw new Error('Generated Service did not bind a TCP port.');
1666
+ if (
1667
+ !address ||
1668
+ typeof address === 'string' ||
1669
+ address.address !== '127.0.0.1'
1670
+ ) {
1671
+ throw new Error('Generated Service did not bind a loopback TCP port.');
1660
1672
  }
1661
1673
  process.env.PORT = String(address.port);
1662
1674
  await expect(
@@ -1699,9 +1711,14 @@ describe('${input.workload} protected Service performance runtime', () => {
1699
1711
  saturation: { percent: 25 },
1700
1712
  });
1701
1713
  } finally {
1702
- await new Promise<void>((resolve, reject) =>
1703
- server.close((error) => (error ? reject(error) : resolve())),
1704
- );
1714
+ // A failed rebind (for example EADDRNOTAVAIL on a host without IPv4
1715
+ // loopback) leaves the server closed; closing it again would reject with
1716
+ // ERR_SERVER_NOT_RUNNING and hide the original error.
1717
+ if (server.listening) {
1718
+ await new Promise<void>((resolve, reject) =>
1719
+ server.close((error) => (error ? reject(error) : resolve())),
1720
+ );
1721
+ }
1705
1722
  if (previousPort === undefined) delete process.env.PORT;
1706
1723
  else process.env.PORT = previousPort;
1707
1724
  if (previousIngressProof === undefined) {
@@ -4,6 +4,8 @@ exports.SERVICE_WORKLOAD_PACKAGE_MANAGED_JSON_POINTERS = exports.WORKLOAD_PACKAG
4
4
  exports.createWorkloadFilePlan = createWorkloadFilePlan;
5
5
  exports.workloadGenerator = workloadGenerator;
6
6
  const deterministic_order_js_1 = require("../../deterministic-order.js");
7
+ const observability_infrastructure_js_1 = require("../observability-infrastructure.js");
8
+ const observability_policy_js_1 = require("../observability-policy.js");
7
9
  const node_path_1 = require("node:path");
8
10
  const index_js_1 = require("../../ownership/index.js");
9
11
  const capability_plan_js_1 = require("../../foundation/capability-plan.js");
@@ -539,7 +541,8 @@ ${kind !== 'service' || ownsProtectedLoadAdapter
539
541
  }
540
542
  const dataProtection = new aws.cloudwatch.LogDataProtectionPolicy(`);
541
543
  }
542
- files[infrastructurePath] = infrastructureSource;
544
+ files[infrastructurePath] =
545
+ (0, observability_infrastructure_js_1.renderExtensionObservability)(infrastructureSource);
543
546
  files[`${relativeRoot}/RUNBOOK.md`] = `# ${workload} ${kind} recovery
544
547
 
545
548
  Confirm the exact Slice, stage, release, configuration, alarm, and workload
@@ -1038,6 +1041,7 @@ async function executeWorkloadGenerator(tree, options, kind) {
1038
1041
  const slice = name(options.slice, 'Product Slice name');
1039
1042
  const workload = name(options.name, kind === 'service' ? 'Service name' : 'Job name');
1040
1043
  const requestedFeature = name(options.feature, 'Feature');
1044
+ (0, observability_policy_js_1.requireObservabilityPolicyFromTree)(tree);
1041
1045
  const plural = kind === 'service' ? 'services' : 'jobs';
1042
1046
  const sliceRoot = node_path_1.posix.join('packages', slice);
1043
1047
  const root = node_path_1.posix.join(sliceRoot, plural, workload);
@@ -1,4 +1,5 @@
1
1
  import { inspectDevelopmentEnvironment } from './environment-inspector.js';
2
+ import type { FleetOperationProgress, FleetOperationWaitOptions } from './fleet-client.js';
2
3
  import type { FleetOperationStateRecord, FleetStateRecord } from './fleet-state.js';
3
4
  import { type FleetLaunchInput } from './fleet-launcher.js';
4
5
  import type { LocalDevContext } from './local-context.js';
@@ -22,9 +23,8 @@ export interface FleetUpCoreClient {
22
23
  operationId: string;
23
24
  state: 'accepted';
24
25
  }>;
25
- waitForOperation(operationId: string, options?: {
26
- timeoutMs?: number;
27
- }): Promise<FleetOperationStateRecord>;
26
+ /** Resolves on the terminal record, `succeeded` or `failed`. */
27
+ waitForOperationOutcome(operationId: string, options?: FleetOperationWaitOptions): Promise<FleetOperationStateRecord>;
28
28
  }
29
29
  export interface FleetUpCoreLaunchResult {
30
30
  attached: boolean;
@@ -48,7 +48,28 @@ export interface FleetUpCoreEffects {
48
48
  inspectEnvironment?: typeof inspectDevelopmentEnvironment;
49
49
  launchFleet?: (input: FleetLaunchInput) => Promise<FleetUpCoreLaunchResult>;
50
50
  reportCleanupFailure?: (message: string) => void;
51
+ /** One human progress line while an operation is observed (stderr). */
52
+ reportProgress?: (line: string) => void;
51
53
  }
54
+ /** Aspirational duration targets per Fleet command, taken from the measured
55
+ * two-Slice figures in docs/local-development.md (fresh up 334-442 s, down
56
+ * 242-345 s, restart about 70-85 s). Exceeding one prints a "slower than
57
+ * target" line; it never fails or stops observing an operation. */
58
+ export declare const FLEET_OPERATION_TARGET_MS: Readonly<{
59
+ down: 350000;
60
+ restart: 90000;
61
+ up: 450000;
62
+ }>;
63
+ /** Progress lines for a watched Fleet operation; the first report past the
64
+ * command's target says so once, and observation continues. */
65
+ export declare function fleetOperationProgressReporter(command: keyof typeof FLEET_OPERATION_TARGET_MS, report: (line: string) => void): (progress: FleetOperationProgress) => void;
66
+ /** Human cause for a terminal failed operation record. */
67
+ export declare function fleetOperationFailureDetail(operation: FleetOperationStateRecord): string;
68
+ /** Owned-cleanup settlement attached to an error from a foreground `up` whose
69
+ * in-process supervisor can outlive the failure. Callers report the error
70
+ * first, then keep interrupt handling installed until this settles, exactly as
71
+ * they do with `afterWrite` after a successful foreground `up`. */
72
+ export declare function foregroundUpSettlement(error: unknown): Promise<void> | undefined;
52
73
  export declare function executeFleetUpCore(command: FleetUpCoreCommand, input: {
53
74
  appData: string;
54
75
  context: LocalDevContext;