@treeseed/sdk 0.4.13 → 0.5.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 (83) hide show
  1. package/dist/control-plane-client.d.ts +60 -1
  2. package/dist/control-plane-client.js +59 -0
  3. package/dist/control-plane.d.ts +1 -1
  4. package/dist/control-plane.js +11 -4
  5. package/dist/d1-store.d.ts +58 -0
  6. package/dist/d1-store.js +64 -0
  7. package/dist/dispatch.js +6 -0
  8. package/dist/graph/schema.js +4 -0
  9. package/dist/index.d.ts +5 -1
  10. package/dist/index.js +32 -0
  11. package/dist/knowledge-coop.d.ts +223 -0
  12. package/dist/knowledge-coop.js +82 -0
  13. package/dist/model-registry.js +79 -0
  14. package/dist/operations/providers/default.js +126 -7
  15. package/dist/operations/services/config-runtime.d.ts +102 -24
  16. package/dist/operations/services/config-runtime.js +896 -160
  17. package/dist/operations/services/deploy.d.ts +223 -15
  18. package/dist/operations/services/deploy.js +626 -55
  19. package/dist/operations/services/github-automation.d.ts +60 -0
  20. package/dist/operations/services/github-automation.js +138 -0
  21. package/dist/operations/services/key-agent.d.ts +118 -0
  22. package/dist/operations/services/key-agent.js +476 -0
  23. package/dist/operations/services/knowledge-coop-launch.d.ts +90 -0
  24. package/dist/operations/services/knowledge-coop-launch.js +753 -0
  25. package/dist/operations/services/knowledge-coop-packaging.d.ts +59 -0
  26. package/dist/operations/services/knowledge-coop-packaging.js +234 -0
  27. package/dist/operations/services/local-dev.d.ts +0 -1
  28. package/dist/operations/services/local-dev.js +1 -14
  29. package/dist/operations/services/project-platform.d.ts +42 -182
  30. package/dist/operations/services/project-platform.js +162 -59
  31. package/dist/operations/services/railway-deploy.d.ts +1 -0
  32. package/dist/operations/services/railway-deploy.js +31 -13
  33. package/dist/operations/services/runtime-tools.d.ts +52 -5
  34. package/dist/operations/services/runtime-tools.js +186 -26
  35. package/dist/operations/services/watch-dev.js +2 -4
  36. package/dist/operations/services/workspace-preflight.d.ts +4 -4
  37. package/dist/operations/services/workspace-preflight.js +22 -20
  38. package/dist/operations-registry.js +7 -2
  39. package/dist/platform/contracts.d.ts +39 -3
  40. package/dist/platform/deploy-config.d.ts +12 -1
  41. package/dist/platform/deploy-config.js +214 -15
  42. package/dist/platform/deploy-runtime.d.ts +1 -0
  43. package/dist/platform/deploy-runtime.js +10 -2
  44. package/dist/platform/env.yaml +93 -61
  45. package/dist/platform/environment.d.ts +13 -2
  46. package/dist/platform/environment.js +90 -20
  47. package/dist/platform/plugins/constants.d.ts +1 -0
  48. package/dist/platform/plugins/constants.js +7 -6
  49. package/dist/platform/tenant/runtime-config.js +8 -1
  50. package/dist/platform/tenant-config.js +4 -0
  51. package/dist/platform/utils/site-config-schema.js +18 -0
  52. package/dist/plugin-default.js +2 -2
  53. package/dist/scripts/key-agent.js +165 -0
  54. package/dist/scripts/tenant-build.js +4 -1
  55. package/dist/scripts/tenant-check.js +4 -1
  56. package/dist/scripts/tenant-deploy.js +43 -4
  57. package/dist/scripts/tenant-dev.js +0 -1
  58. package/dist/sdk-types.d.ts +2 -2
  59. package/dist/sdk-types.js +2 -0
  60. package/dist/sdk.d.ts +13 -0
  61. package/dist/sdk.js +40 -0
  62. package/dist/stores/knowledge-coop-store.d.ts +56 -0
  63. package/dist/stores/knowledge-coop-store.js +482 -0
  64. package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +6 -2
  65. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/api/server.js +4 -0
  66. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +25 -0
  67. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/decisions/adopt-initial-proposal-loop.mdx +22 -0
  68. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/people/starter-steward.mdx +11 -0
  69. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/proposals/establish-initial-proposal-loop.mdx +17 -0
  70. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +17 -10
  71. package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +69 -7
  72. package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +1 -0
  73. package/dist/verification.js +90 -2
  74. package/dist/workflow/operations.d.ts +98 -0
  75. package/dist/workflow/operations.js +229 -7
  76. package/dist/workflow-state.d.ts +54 -2
  77. package/dist/workflow-state.js +170 -24
  78. package/dist/workflow-support.d.ts +1 -1
  79. package/dist/workflow-support.js +32 -2
  80. package/dist/workflow.d.ts +29 -0
  81. package/package.json +1 -1
  82. package/templates/github/deploy.workflow.yml +11 -1
  83. package/dist/scripts/sync-dev-vars.js +0 -6
@@ -9,12 +9,20 @@ import {
9
9
  checkTreeseedProviderConnections,
10
10
  collectTreeseedConfigContext,
11
11
  collectTreeseedPrintEnvReport,
12
+ ensureTreeseedSecretSessionForConfig,
12
13
  ensureTreeseedActVerificationTooling,
13
14
  ensureTreeseedGitignoreEntries,
14
15
  finalizeTreeseedConfig,
15
16
  getTreeseedMachineConfigPaths,
16
- rotateTreeseedMachineKey
17
+ inspectTreeseedKeyAgentStatus,
18
+ loadTreeseedMachineConfig,
19
+ resolveTreeseedLaunchEnvironment,
20
+ resolveTreeseedRemoteSession,
21
+ rotateTreeseedMachineKey,
22
+ setTreeseedRemoteSession,
23
+ writeTreeseedMachineConfig
17
24
  } from "../operations/services/config-runtime.js";
25
+ import { ControlPlaneClient } from "../control-plane-client.js";
18
26
  import { exportTreeseedCodebase } from "../operations/services/export-runtime.js";
19
27
  import {
20
28
  assertDeploymentInitialized,
@@ -338,7 +346,175 @@ function createTasksResult(cwd) {
338
346
  packages
339
347
  };
340
348
  });
341
- return buildWorkflowResult("tasks", cwd, { tasks }, { includeFinalState: false });
349
+ const workstreams = tasks.map((task) => ({
350
+ id: task.name,
351
+ title: task.name.replace(/^task\//u, "").replace(/[-_]+/gu, " "),
352
+ linkedDirectRefs: [],
353
+ branch: task.name,
354
+ local: task.local,
355
+ remote: task.remote,
356
+ current: task.current,
357
+ previewUrl: task.preview.url,
358
+ lastSaveAt: task.lastCommitDate ?? null,
359
+ verificationResult: task.dirtyCurrent ? "needs_attention" : task.head ? "ready" : "unknown",
360
+ stagingCandidate: task.name === STAGING_BRANCH,
361
+ archived: false
362
+ }));
363
+ return buildWorkflowResult("tasks", cwd, { tasks, workstreams }, { includeFinalState: false });
364
+ }
365
+ function normalizeOptionalString(value) {
366
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
367
+ }
368
+ async function connectTreeseedMarketProject(helpers, tenantRoot, input, context) {
369
+ const machineConfig = loadTreeseedMachineConfig(tenantRoot);
370
+ const marketSettings = machineConfig.settings?.market && typeof machineConfig.settings.market === "object" ? machineConfig.settings.market : {};
371
+ const remoteSettings = machineConfig.settings?.remote && typeof machineConfig.settings.remote === "object" ? machineConfig.settings.remote : { activeHostId: "official", executionMode: "prefer-local", hosts: [] };
372
+ const baseUrl = normalizeOptionalString(input.marketBaseUrl) ?? normalizeOptionalString(marketSettings.baseUrl) ?? normalizeOptionalString(remoteSettings.hosts?.find?.((entry) => entry?.official === true)?.baseUrl) ?? normalizeOptionalString(remoteSettings.hosts?.find?.((entry) => entry?.id === remoteSettings.activeHostId)?.baseUrl);
373
+ if (!baseUrl) {
374
+ workflowError(
375
+ "config",
376
+ "validation_failed",
377
+ "Treeseed config --connect-market requires a market base URL. Pass --market-base-url or configure an authenticated remote host first."
378
+ );
379
+ }
380
+ const hostId = normalizeOptionalString(marketSettings.hostId) ?? "knowledge-coop";
381
+ const activeRemoteSession = resolveTreeseedRemoteSession(tenantRoot, hostId) ?? resolveTreeseedRemoteSession(tenantRoot, remoteSettings.activeHostId) ?? resolveTreeseedRemoteSession(tenantRoot, "official");
382
+ const accessToken = normalizeOptionalString(input.marketAccessToken) ?? normalizeOptionalString(activeRemoteSession?.accessToken);
383
+ if (!accessToken) {
384
+ workflowError(
385
+ "config",
386
+ "validation_failed",
387
+ "Treeseed config --connect-market requires a market access token. Authenticate to the Knowledge Coop control-plane first or pass --market-access-token."
388
+ );
389
+ }
390
+ const projectId = normalizeOptionalString(input.marketProjectId) ?? normalizeOptionalString(marketSettings.projectId);
391
+ if (!projectId) {
392
+ workflowError(
393
+ "config",
394
+ "validation_failed",
395
+ "Treeseed config --connect-market requires --market-project-id or an existing settings.market.projectId value."
396
+ );
397
+ }
398
+ const teamId = normalizeOptionalString(input.marketTeamId) ?? normalizeOptionalString(marketSettings.teamId);
399
+ const projectSlug = normalizeOptionalString(input.marketProjectSlug) ?? normalizeOptionalString(marketSettings.projectSlug) ?? normalizeOptionalString(machineConfig.project?.slug) ?? projectId;
400
+ const teamSlug = normalizeOptionalString(input.marketTeamSlug) ?? normalizeOptionalString(marketSettings.teamSlug);
401
+ const projectApiBaseUrl = normalizeOptionalString(input.marketProjectApiBaseUrl) ?? normalizeOptionalString(marketSettings.projectApiBaseUrl);
402
+ const client = new ControlPlaneClient({
403
+ baseUrl,
404
+ accessToken
405
+ });
406
+ const connectionResult = await client.upsertProjectConnection(projectId, {
407
+ mode: "hybrid",
408
+ projectApiBaseUrl,
409
+ executionOwner: "project_runner",
410
+ metadata: {
411
+ pairingSource: "treeseed_config_connect_market",
412
+ tenantRoot,
413
+ tenantSlug: normalizeOptionalString(machineConfig.project?.slug),
414
+ repoSlug: normalizeOptionalString(machineConfig.project?.slug),
415
+ teamId,
416
+ teamSlug,
417
+ projectSlug,
418
+ connectedAt: (/* @__PURE__ */ new Date()).toISOString()
419
+ },
420
+ rotateRunnerToken: input.rotateRunnerToken === true
421
+ });
422
+ const hosts = Array.isArray(remoteSettings.hosts) ? [...remoteSettings.hosts] : [];
423
+ const updatedHost = {
424
+ id: hostId,
425
+ label: "Knowledge Coop",
426
+ baseUrl,
427
+ official: false
428
+ };
429
+ const existingHostIndex = hosts.findIndex(
430
+ (entry) => String(entry?.id ?? "") === hostId || String(entry?.baseUrl ?? "").replace(/\/+$/u, "") === baseUrl.replace(/\/+$/u, "")
431
+ );
432
+ if (existingHostIndex >= 0) {
433
+ hosts.splice(existingHostIndex, 1, {
434
+ ...hosts[existingHostIndex],
435
+ ...updatedHost
436
+ });
437
+ } else {
438
+ hosts.unshift(updatedHost);
439
+ }
440
+ if (normalizeOptionalString(input.marketAccessToken)) {
441
+ setTreeseedRemoteSession(tenantRoot, {
442
+ hostId,
443
+ accessToken,
444
+ refreshToken: activeRemoteSession?.refreshToken ?? "",
445
+ expiresAt: activeRemoteSession?.expiresAt ?? "",
446
+ principal: activeRemoteSession?.principal ?? null
447
+ });
448
+ }
449
+ const runnerHostId = `market-runner:${projectId}`;
450
+ if (connectionResult.runnerToken) {
451
+ setTreeseedRemoteSession(tenantRoot, {
452
+ hostId: runnerHostId,
453
+ accessToken: connectionResult.runnerToken,
454
+ refreshToken: "",
455
+ expiresAt: "",
456
+ principal: {
457
+ id: `runner:${projectId}`,
458
+ displayName: "Knowledge Coop Project Runner",
459
+ scopes: [],
460
+ roles: ["project_runner"],
461
+ permissions: [],
462
+ metadata: { projectId }
463
+ }
464
+ });
465
+ }
466
+ machineConfig.settings.remote = {
467
+ ...remoteSettings,
468
+ activeHostId: hostId,
469
+ hosts
470
+ };
471
+ machineConfig.settings.market = {
472
+ baseUrl,
473
+ hostId,
474
+ teamId,
475
+ teamSlug,
476
+ projectId,
477
+ projectSlug,
478
+ projectApiBaseUrl: connectionResult.connection?.projectApiBaseUrl ?? projectApiBaseUrl ?? null,
479
+ connectionMode: connectionResult.connection?.mode ?? "hybrid",
480
+ executionOwner: connectionResult.connection?.executionOwner ?? "project_runner",
481
+ runnerHostId,
482
+ runnerReady: Boolean(connectionResult.runnerToken || resolveTreeseedRemoteSession(tenantRoot, runnerHostId)?.accessToken),
483
+ runnerRegisteredAt: connectionResult.connection?.runnerRegisteredAt ?? null,
484
+ runnerLastSeenAt: connectionResult.connection?.runnerLastSeenAt ?? null,
485
+ launchPhase: null,
486
+ lastSuccessfulPhase: null,
487
+ githubRepository: null,
488
+ workflowBootstrapReady: false,
489
+ approvalBlockers: [],
490
+ connectedAt: (/* @__PURE__ */ new Date()).toISOString()
491
+ };
492
+ writeTreeseedMachineConfig(tenantRoot, machineConfig);
493
+ const { configPath, keyPath } = getTreeseedMachineConfigPaths(tenantRoot);
494
+ return buildWorkflowResult(
495
+ "config",
496
+ tenantRoot,
497
+ {
498
+ mode: "connect-market",
499
+ scopes: context.scopes,
500
+ sync: context.sync,
501
+ configPath,
502
+ keyPath,
503
+ repairs: context.repairs,
504
+ preflight: context.preflight,
505
+ toolHealth: context.toolHealth,
506
+ market: machineConfig.settings.market,
507
+ connection: connectionResult.connection,
508
+ runnerTokenIssued: Boolean(connectionResult.runnerToken)
509
+ },
510
+ {
511
+ summary: "Knowledge Coop project pairing completed.",
512
+ nextSteps: createNextSteps([
513
+ { operation: "status", reason: "Confirm the new market connection, runner health, and current workstream posture." },
514
+ { operation: "tasks", reason: "Inspect the branch-backed workstreams that will now sync into the Knowledge Coop UI." }
515
+ ])
516
+ }
517
+ );
342
518
  }
343
519
  function maybePrint(write, line, stream = "stdout") {
344
520
  if (!line) return;
@@ -846,13 +1022,27 @@ async function workflowConfig(helpers, input = {}) {
846
1022
  const revealSecrets = input.showSecrets === true;
847
1023
  const printEnvOnly = input.printEnvOnly === true;
848
1024
  const rotateMachineKeyFlag = input.rotateMachineKey === true;
1025
+ const connectMarketFlag = input.connectMarket === true;
1026
+ const nonInteractive = input.nonInteractive === true;
849
1027
  const repairs = input.repair === false ? [] : resolveTreeseedWorkflowState(tenantRoot).deployConfigPresent ? applyTreeseedSafeRepairs(tenantRoot) : [];
850
1028
  const toolHealth = ensureTreeseedActVerificationTooling({
851
1029
  tenantRoot,
852
- installIfMissing: true,
1030
+ installIfMissing: input.installMissingTooling === true,
853
1031
  env: helpers.context.env,
854
1032
  write: (line) => maybePrint(helpers.write, line)
855
1033
  });
1034
+ const secretSession = printEnvOnly && !revealSecrets ? {
1035
+ status: inspectTreeseedKeyAgentStatus(tenantRoot),
1036
+ createdWrappedKey: false,
1037
+ migratedWrappedKey: false,
1038
+ unlockSource: "existing-session"
1039
+ } : await ensureTreeseedSecretSessionForConfig({
1040
+ tenantRoot,
1041
+ interactive: false,
1042
+ env: helpers.context.env,
1043
+ createIfMissing: true,
1044
+ allowMigration: true
1045
+ });
856
1046
  ensureTreeseedGitignoreEntries(tenantRoot);
857
1047
  const preflight = collectCliPreflight({ cwd: tenantRoot, requireAuth: false });
858
1048
  const contextSnapshot = collectTreeseedConfigContext({
@@ -882,7 +1072,9 @@ async function workflowConfig(helpers, input = {}) {
882
1072
  reports: reports2,
883
1073
  repairs,
884
1074
  preflight,
885
- toolHealth
1075
+ toolHealth,
1076
+ context: contextSnapshot,
1077
+ secretSession
886
1078
  },
887
1079
  {
888
1080
  nextSteps: createNextSteps([
@@ -903,7 +1095,9 @@ async function workflowConfig(helpers, input = {}) {
903
1095
  keyPath: result.keyPath,
904
1096
  repairs,
905
1097
  preflight,
906
- toolHealth
1098
+ toolHealth,
1099
+ context: contextSnapshot,
1100
+ secretSession
907
1101
  },
908
1102
  {
909
1103
  nextSteps: createNextSteps([
@@ -912,12 +1106,28 @@ async function workflowConfig(helpers, input = {}) {
912
1106
  }
913
1107
  );
914
1108
  }
1109
+ if (connectMarketFlag) {
1110
+ return connectTreeseedMarketProject(helpers, tenantRoot, input, {
1111
+ scopes,
1112
+ sync,
1113
+ repairs,
1114
+ preflight,
1115
+ toolHealth
1116
+ });
1117
+ }
915
1118
  const explicitUpdates = Array.isArray(input.updates) ? input.updates.map((update) => ({
916
1119
  scope: update.scope,
917
1120
  entryId: String(update.entryId ?? ""),
918
1121
  value: typeof update.value === "string" ? update.value : "",
919
1122
  reused: update.reused === true
920
1123
  })) : null;
1124
+ if (!explicitUpdates && !nonInteractive) {
1125
+ workflowError(
1126
+ "config",
1127
+ "validation_failed",
1128
+ "Treeseed config requires interactive input or explicit updates. Re-run in a TTY, or use --non-interactive/--json from the CLI when you want resolved values applied automatically."
1129
+ );
1130
+ }
921
1131
  const autoUpdates = scopes.flatMap(
922
1132
  (scope) => contextSnapshot.entriesByScope[scope].map((entry) => ({
923
1133
  scope,
@@ -926,6 +1136,7 @@ async function workflowConfig(helpers, input = {}) {
926
1136
  reused: entry.currentValue.length > 0 || entry.suggestedValue.length > 0
927
1137
  }))
928
1138
  );
1139
+ maybePrint(helpers.write, "Saving resolved configuration values to machine config...");
929
1140
  const applyResult = applyTreeseedConfigValues({
930
1141
  tenantRoot,
931
1142
  updates: explicitUpdates ?? autoUpdates
@@ -934,6 +1145,12 @@ async function workflowConfig(helpers, input = {}) {
934
1145
  tenantRoot,
935
1146
  scopes,
936
1147
  sync,
1148
+ env: helpers.context.env,
1149
+ onProgress: (line) => maybePrint(helpers.write, line)
1150
+ });
1151
+ const refreshedContext = collectTreeseedConfigContext({
1152
+ tenantRoot,
1153
+ scopes,
937
1154
  env: helpers.context.env
938
1155
  });
939
1156
  const reports = printEnv ? scopes.map((scope) => ({
@@ -960,7 +1177,8 @@ async function workflowConfig(helpers, input = {}) {
960
1177
  repairs,
961
1178
  preflight,
962
1179
  toolHealth,
963
- context: contextSnapshot,
1180
+ secretSession,
1181
+ context: refreshedContext,
964
1182
  result: {
965
1183
  ...applyResult,
966
1184
  ...finalizeResult
@@ -1170,7 +1388,11 @@ async function workflowDev(helpers, input = {}) {
1170
1388
  if (input.port !== void 0) {
1171
1389
  args.push("--port", String(input.port));
1172
1390
  }
1173
- const env = { ...process.env, ...helpers.context.env ?? {} };
1391
+ const env = resolveTreeseedLaunchEnvironment({
1392
+ tenantRoot,
1393
+ scope: "local",
1394
+ baseEnv: { ...process.env, ...helpers.context.env ?? {} }
1395
+ });
1174
1396
  if (input.background) {
1175
1397
  const child = spawn(process.execPath, args, {
1176
1398
  cwd: tenantRoot,
@@ -51,8 +51,26 @@ export type TreeseedWorkflowState = {
51
51
  url: string | null;
52
52
  lastDeploymentTimestamp: string | null;
53
53
  };
54
+ webCache: {
55
+ webHost: string | null;
56
+ contentHost: string | null;
57
+ sourcePagePolicy: string | null;
58
+ contentPagePolicy: string | null;
59
+ r2ObjectPolicy: string | null;
60
+ cloudflareRulesManaged: boolean;
61
+ lastDeployPurgeAt: string | null;
62
+ lastDeployPurgeCount: number | null;
63
+ lastContentPurgeAt: string | null;
64
+ lastContentPurgeCount: number | null;
65
+ };
54
66
  persistentEnvironments: Record<string, {
55
67
  initialized: boolean;
68
+ phase: string;
69
+ configured: boolean;
70
+ provisioned: boolean;
71
+ deployable: boolean;
72
+ blockers: string[];
73
+ warnings: string[];
56
74
  lastValidatedAt: string | null;
57
75
  lastDeploymentTimestamp: string | null;
58
76
  lastDeployedUrl: string | null;
@@ -64,6 +82,33 @@ export type TreeseedWorkflowState = {
64
82
  copilot: boolean;
65
83
  remoteApi: boolean;
66
84
  };
85
+ marketConnection: {
86
+ configured: boolean;
87
+ baseUrl: string | null;
88
+ hostId: string | null;
89
+ teamId: string | null;
90
+ teamSlug: string | null;
91
+ projectId: string | null;
92
+ projectSlug: string | null;
93
+ connectionMode: string | null;
94
+ projectApiBaseUrl: string | null;
95
+ hubMode: string | null;
96
+ runtimeMode: string | null;
97
+ runtimeRegistration: string | null;
98
+ runtimeAttached: boolean;
99
+ runtimeReady: boolean;
100
+ runnerHostId: string | null;
101
+ runnerReady: boolean;
102
+ runnerRegisteredAt: string | null;
103
+ runnerLastSeenAt: string | null;
104
+ launchPhase: string | null;
105
+ lastSuccessfulPhase: string | null;
106
+ githubRepository: string | null;
107
+ workflowBootstrapReady: boolean;
108
+ currentWorkstreamId: string | null;
109
+ verificationPosture: 'ready' | 'blocked' | 'pending';
110
+ approvalBlockers: string[];
111
+ };
67
112
  managedServices: Record<string, {
68
113
  enabled: boolean;
69
114
  initialized: boolean;
@@ -75,8 +120,15 @@ export type TreeseedWorkflowState = {
75
120
  treeseedConfig: boolean;
76
121
  machineConfig: boolean;
77
122
  machineKey: boolean;
78
- envLocal: boolean;
79
- devVars: boolean;
123
+ };
124
+ secrets: {
125
+ keyAgentRunning: boolean;
126
+ keyAgentUnlocked: boolean;
127
+ wrappedKeyPresent: boolean;
128
+ migrationRequired: boolean;
129
+ idleTimeoutMs: number;
130
+ idleRemainingMs: number;
131
+ startupPassphraseConfigured: boolean;
80
132
  };
81
133
  releaseReady: boolean;
82
134
  readiness: {