@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
@@ -1,6 +1,16 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
- import { getTreeseedMachineConfigPaths, resolveTreeseedRemoteSession } from "./operations/services/config-runtime.js";
3
+ import {
4
+ getTreeseedMachineConfigPaths,
5
+ inspectTreeseedKeyAgentStatus,
6
+ loadTreeseedMachineConfig,
7
+ resolveTreeseedMachineEnvironmentValues,
8
+ resolveTreeseedRemoteSession,
9
+ collectTreeseedEnvironmentContext,
10
+ withTreeseedKeyAgentAutopromptDisabled
11
+ } from "./operations/services/config-runtime.js";
12
+ import { validateTreeseedEnvironmentValues } from "./platform/environment.js";
13
+ import { resolveTreeseedWebCachePolicy } from "./platform/deploy-config.js";
4
14
  import {
5
15
  createBranchPreviewDeployTarget,
6
16
  createPersistentDeployTarget,
@@ -17,31 +27,33 @@ import {
17
27
  } from "./workflow/policy.js";
18
28
  function emptyPersistentEnvironments() {
19
29
  return {
20
- local: { initialized: false, lastValidatedAt: null, lastDeploymentTimestamp: null, lastDeployedUrl: null },
21
- staging: { initialized: false, lastValidatedAt: null, lastDeploymentTimestamp: null, lastDeployedUrl: null },
22
- prod: { initialized: false, lastValidatedAt: null, lastDeploymentTimestamp: null, lastDeployedUrl: null }
30
+ local: { initialized: false, phase: "pending", configured: false, provisioned: false, deployable: false, blockers: [], warnings: [], lastValidatedAt: null, lastDeploymentTimestamp: null, lastDeployedUrl: null },
31
+ staging: { initialized: false, phase: "pending", configured: false, provisioned: false, deployable: false, blockers: [], warnings: [], lastValidatedAt: null, lastDeploymentTimestamp: null, lastDeployedUrl: null },
32
+ prod: { initialized: false, phase: "pending", configured: false, provisioned: false, deployable: false, blockers: [], warnings: [], lastValidatedAt: null, lastDeploymentTimestamp: null, lastDeployedUrl: null }
23
33
  };
24
34
  }
25
35
  function readinessForEnvironment(state, scope) {
26
- const blockers = [];
27
- const warnings = [];
36
+ const blockers = [...state.persistentEnvironments[scope].blockers];
37
+ const warnings = [...state.persistentEnvironments[scope].warnings];
28
38
  if (!state.deployConfigPresent) {
29
39
  blockers.push("Missing treeseed.site.yaml.");
30
40
  }
31
41
  if (!state.files.machineConfig) {
32
42
  blockers.push("Missing Treeseed machine config.");
33
43
  }
34
- if (scope === "local") {
35
- if (!state.files.envLocal) {
36
- blockers.push("Missing .env.local.");
37
- }
38
- if (!state.files.devVars) {
39
- warnings.push("Missing .dev.vars.");
40
- }
41
- } else {
44
+ if (!state.secrets.wrappedKeyPresent) {
45
+ blockers.push("Missing wrapped Treeseed machine key.");
46
+ }
47
+ if (state.secrets.migrationRequired) {
48
+ blockers.push("Treeseed machine key migration is still required.");
49
+ }
50
+ if (scope !== "local") {
42
51
  if (!state.persistentEnvironments[scope].initialized) {
43
52
  blockers.push(`Environment ${scope} is not initialized.`);
44
53
  }
54
+ if (state.persistentEnvironments[scope].configured && !state.persistentEnvironments[scope].provisioned) {
55
+ warnings.push(`Environment ${scope} is configured but foundational infrastructure has not been provisioned yet.`);
56
+ }
45
57
  }
46
58
  return {
47
59
  ready: blockers.length === 0,
@@ -49,6 +61,20 @@ function readinessForEnvironment(state, scope) {
49
61
  warnings
50
62
  };
51
63
  }
64
+ function safeResolveRemoteSession(cwd, hostId) {
65
+ try {
66
+ return withTreeseedKeyAgentAutopromptDisabled(() => resolveTreeseedRemoteSession(cwd, hostId ?? void 0));
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+ function safeResolveMachineEnvironmentValues(cwd, scope) {
72
+ try {
73
+ return withTreeseedKeyAgentAutopromptDisabled(() => resolveTreeseedMachineEnvironmentValues(cwd, scope));
74
+ } catch {
75
+ return {};
76
+ }
77
+ }
52
78
  function knownRemoteTrackingBranchExists(repoDir, branchName) {
53
79
  try {
54
80
  run("git", ["show-ref", "--verify", "--quiet", `refs/remotes/origin/${branchName}`], { cwd: repoDir, capture: true });
@@ -111,6 +137,11 @@ function resolveTreeseedWorkflowState(cwd) {
111
137
  }
112
138
  const preflight = collectCliPreflight({ cwd: effectiveCwd, requireAuth: false });
113
139
  const { configPath, keyPath } = getTreeseedMachineConfigPaths(effectiveCwd);
140
+ const machineConfig = existsSync(configPath) ? loadTreeseedMachineConfig(effectiveCwd) : null;
141
+ const keyStatus = inspectTreeseedKeyAgentStatus(effectiveCwd);
142
+ const marketSettings = machineConfig?.settings?.market && typeof machineConfig.settings.market === "object" ? machineConfig.settings.market : null;
143
+ const runnerHostId = typeof marketSettings?.runnerHostId === "string" && marketSettings.runnerHostId.trim() ? marketSettings.runnerHostId.trim() : typeof marketSettings?.projectId === "string" && marketSettings.projectId.trim() ? `market-runner:${marketSettings.projectId.trim()}` : null;
144
+ const runnerSession = runnerHostId ? safeResolveRemoteSession(effectiveCwd, runnerHostId) : null;
114
145
  const workflowLock = inspectWorkflowLock(effectiveCwd);
115
146
  const interruptedRuns = listInterruptedWorkflowRuns(effectiveCwd).map((journal) => ({
116
147
  runId: journal.runId,
@@ -164,29 +195,75 @@ function resolveTreeseedWorkflowState(cwd) {
164
195
  url: null,
165
196
  lastDeploymentTimestamp: null
166
197
  },
198
+ webCache: {
199
+ webHost: null,
200
+ contentHost: null,
201
+ sourcePagePolicy: null,
202
+ contentPagePolicy: null,
203
+ r2ObjectPolicy: null,
204
+ cloudflareRulesManaged: false,
205
+ lastDeployPurgeAt: null,
206
+ lastDeployPurgeCount: null,
207
+ lastContentPurgeAt: null,
208
+ lastContentPurgeCount: null
209
+ },
167
210
  persistentEnvironments: emptyPersistentEnvironments(),
168
211
  auth: {
169
212
  gh: preflight.checks.auth.gh?.authenticated === true,
170
213
  wrangler: preflight.checks.auth.wrangler?.authenticated === true,
171
214
  railway: preflight.checks.auth.railway?.authenticated === true,
172
215
  copilot: preflight.checks.auth.copilot?.configured === true,
173
- remoteApi: Boolean(resolveTreeseedRemoteSession(cwd))
216
+ remoteApi: Boolean(safeResolveRemoteSession(cwd))
217
+ },
218
+ marketConnection: {
219
+ configured: Boolean(marketSettings?.baseUrl && marketSettings?.projectId),
220
+ baseUrl: typeof marketSettings?.baseUrl === "string" ? marketSettings.baseUrl : null,
221
+ hostId: typeof marketSettings?.hostId === "string" ? marketSettings.hostId : null,
222
+ teamId: typeof marketSettings?.teamId === "string" ? marketSettings.teamId : null,
223
+ teamSlug: typeof marketSettings?.teamSlug === "string" ? marketSettings.teamSlug : null,
224
+ projectId: typeof marketSettings?.projectId === "string" ? marketSettings.projectId : null,
225
+ projectSlug: typeof marketSettings?.projectSlug === "string" ? marketSettings.projectSlug : null,
226
+ connectionMode: typeof marketSettings?.connectionMode === "string" ? marketSettings.connectionMode : null,
227
+ projectApiBaseUrl: typeof marketSettings?.projectApiBaseUrl === "string" ? marketSettings.projectApiBaseUrl : null,
228
+ hubMode: null,
229
+ runtimeMode: null,
230
+ runtimeRegistration: null,
231
+ runtimeAttached: false,
232
+ runtimeReady: true,
233
+ runnerHostId,
234
+ runnerReady: Boolean(
235
+ marketSettings?.runnerReady === true || typeof runnerSession?.accessToken === "string" && runnerSession.accessToken.length > 0
236
+ ),
237
+ runnerRegisteredAt: typeof marketSettings?.runnerRegisteredAt === "string" ? marketSettings.runnerRegisteredAt : null,
238
+ runnerLastSeenAt: typeof marketSettings?.runnerLastSeenAt === "string" ? marketSettings.runnerLastSeenAt : null,
239
+ launchPhase: typeof marketSettings?.launchPhase === "string" ? marketSettings.launchPhase : null,
240
+ lastSuccessfulPhase: typeof marketSettings?.lastSuccessfulPhase === "string" ? marketSettings.lastSuccessfulPhase : null,
241
+ githubRepository: typeof marketSettings?.githubRepository === "string" ? marketSettings.githubRepository : null,
242
+ workflowBootstrapReady: marketSettings?.workflowBootstrapReady === true,
243
+ currentWorkstreamId: branchRole === "feature" ? branchName : null,
244
+ verificationPosture: typeof marketSettings?.launchPhase === "string" && marketSettings.launchPhase === "failed" ? "blocked" : "pending",
245
+ approvalBlockers: Array.isArray(marketSettings?.approvalBlockers) ? marketSettings.approvalBlockers.map(String) : []
174
246
  },
175
247
  managedServices: {
176
248
  api: { enabled: false, initialized: false, lastDeploymentTimestamp: null, lastDeployedUrl: null, provider: null },
177
- agents: { enabled: false, initialized: false, lastDeploymentTimestamp: null, lastDeployedUrl: null, provider: null },
178
249
  manager: { enabled: false, initialized: false, lastDeploymentTimestamp: null, lastDeployedUrl: null, provider: null },
179
250
  worker: { enabled: false, initialized: false, lastDeploymentTimestamp: null, lastDeployedUrl: null, provider: null },
180
- runner: { enabled: false, initialized: false, lastDeploymentTimestamp: null, lastDeployedUrl: null, provider: null },
181
251
  workdayStart: { enabled: false, initialized: false, lastDeploymentTimestamp: null, lastDeployedUrl: null, provider: null },
182
252
  workdayReport: { enabled: false, initialized: false, lastDeploymentTimestamp: null, lastDeployedUrl: null, provider: null }
183
253
  },
184
254
  files: {
185
255
  treeseedConfig: tenantRoot,
186
256
  machineConfig: existsSync(configPath),
187
- machineKey: existsSync(keyPath),
188
- envLocal: existsSync(resolve(cwd, ".env.local")),
189
- devVars: existsSync(resolve(cwd, ".dev.vars"))
257
+ machineKey: existsSync(keyPath)
258
+ },
259
+ secrets: {
260
+ keyAgentRunning: keyStatus.running,
261
+ keyAgentUnlocked: keyStatus.unlocked,
262
+ wrappedKeyPresent: keyStatus.wrappedKeyPresent,
263
+ migrationRequired: keyStatus.migrationRequired,
264
+ idleTimeoutMs: keyStatus.idleTimeoutMs,
265
+ idleRemainingMs: keyStatus.idleRemainingMs,
266
+ startupPassphraseConfigured: Boolean(process.env.TREESEED_KEY_PASSPHRASE?.trim())
190
267
  },
191
268
  releaseReady: branchRole === "staging" && !dirtyWorktree,
192
269
  readiness: {
@@ -200,10 +277,59 @@ function resolveTreeseedWorkflowState(cwd) {
200
277
  if (tenantRoot) {
201
278
  try {
202
279
  const deployConfig = loadCliDeployConfig(effectiveCwd);
280
+ const environmentContext = collectTreeseedEnvironmentContext(effectiveCwd);
281
+ const sharedConfigValues = safeResolveMachineEnvironmentValues(effectiveCwd, "prod");
282
+ const runtimeMode = deployConfig.runtime?.mode ?? "none";
283
+ const runtimeRegistration = deployConfig.runtime?.registration ?? "none";
284
+ const webCachePolicy = resolveTreeseedWebCachePolicy(deployConfig);
285
+ const registrationRequired2 = runtimeRegistration === "required";
286
+ const registrationEnabled = runtimeRegistration === "required" || runtimeRegistration === "optional";
287
+ const runtimeSessionReady = Boolean(
288
+ marketSettings?.runnerReady === true || typeof runnerSession?.accessToken === "string" && runnerSession.accessToken.length > 0
289
+ );
290
+ state.marketConnection.baseUrl = state.marketConnection.baseUrl ?? sharedConfigValues.TREESEED_MARKET_API_BASE_URL ?? deployConfig.runtime?.marketBaseUrl ?? deployConfig.hosting?.marketBaseUrl ?? null;
291
+ state.marketConnection.teamId = state.marketConnection.teamId ?? sharedConfigValues.TREESEED_HOSTING_TEAM_ID ?? deployConfig.runtime?.teamId ?? deployConfig.hosting?.teamId ?? null;
292
+ state.marketConnection.projectId = state.marketConnection.projectId ?? sharedConfigValues.TREESEED_PROJECT_ID ?? deployConfig.runtime?.projectId ?? deployConfig.hosting?.projectId ?? null;
293
+ state.marketConnection.hubMode = deployConfig.hub?.mode ?? null;
294
+ state.marketConnection.runtimeMode = runtimeMode;
295
+ state.marketConnection.runtimeRegistration = runtimeRegistration;
296
+ state.marketConnection.runtimeAttached = runtimeMode !== "none" && (!registrationEnabled || state.marketConnection.configured);
297
+ state.marketConnection.runtimeReady = runtimeMode === "none" || !registrationEnabled || runtimeSessionReady;
298
+ state.marketConnection.runnerReady = runtimeSessionReady;
299
+ state.webCache.webHost = deployConfig.surfaces?.web?.publicBaseUrl ?? deployConfig.siteUrl ?? null;
300
+ state.webCache.contentHost = sharedConfigValues.TREESEED_CONTENT_PUBLIC_BASE_URL ?? deployConfig.cloudflare.r2?.publicBaseUrl ?? null;
301
+ state.webCache.sourcePagePolicy = `browser=${webCachePolicy.sourcePages.browserTtlSeconds}s edge=${webCachePolicy.sourcePages.edgeTtlSeconds}s swr=${webCachePolicy.sourcePages.staleWhileRevalidateSeconds}s sie=${webCachePolicy.sourcePages.staleIfErrorSeconds}s`;
302
+ state.webCache.contentPagePolicy = `browser=${webCachePolicy.contentPages.browserTtlSeconds}s edge=${webCachePolicy.contentPages.edgeTtlSeconds}s swr=${webCachePolicy.contentPages.staleWhileRevalidateSeconds}s sie=${webCachePolicy.contentPages.staleIfErrorSeconds}s`;
303
+ state.webCache.r2ObjectPolicy = `browser=${webCachePolicy.r2PublishedObjects.browserTtlSeconds}s edge=${webCachePolicy.r2PublishedObjects.edgeTtlSeconds}s swr=${webCachePolicy.r2PublishedObjects.staleWhileRevalidateSeconds}s sie=${webCachePolicy.r2PublishedObjects.staleIfErrorSeconds}s`;
304
+ state.marketConnection.configured = registrationRequired2 ? Boolean(state.marketConnection.baseUrl && state.marketConnection.projectId) : state.marketConnection.configured;
203
305
  for (const scope of ["local", "staging", "prod"]) {
204
306
  const deployState = loadDeployState(effectiveCwd, deployConfig, { target: createPersistentDeployTarget(scope) });
307
+ const validation = validateTreeseedEnvironmentValues({
308
+ values: safeResolveMachineEnvironmentValues(effectiveCwd, scope),
309
+ scope,
310
+ purpose: "config",
311
+ deployConfig: environmentContext.context.deployConfig,
312
+ tenantConfig: environmentContext.context.tenantConfig,
313
+ plugins: environmentContext.context.plugins
314
+ });
315
+ const validationProblems = [...validation.missing, ...validation.invalid].map((problem) => problem.message);
316
+ const persistentBlockers = Array.isArray(deployState.readiness?.blockers) ? deployState.readiness.blockers.map(String) : [];
317
+ const persistentWarnings = Array.isArray(deployState.readiness?.warnings) ? deployState.readiness.warnings.map(String) : [];
318
+ const configured = scope === "local" ? validation.ok : deployState.readiness?.configured === true && validation.ok;
319
+ const provisioned = scope === "local" ? true : configured && deployState.readiness?.provisioned === true;
320
+ const deployable = scope === "local" ? validation.ok : configured && deployState.readiness?.deployable === true;
321
+ const initialized = deployState.readiness?.initialized === true || scope === "local";
205
322
  state.persistentEnvironments[scope] = {
206
- initialized: deployState.readiness?.initialized === true || scope === "local",
323
+ initialized,
324
+ phase: validation.ok ? scope === "local" ? "code_ready" : provisioned ? "provisioned" : configured ? "config_complete" : initialized ? "config_complete" : "pending" : "config_incomplete",
325
+ configured,
326
+ provisioned,
327
+ deployable,
328
+ blockers: [
329
+ ...validationProblems,
330
+ ...persistentBlockers
331
+ ],
332
+ warnings: persistentWarnings,
207
333
  lastValidatedAt: deployState.readiness?.lastValidatedAt ?? deployState.readiness?.initializedAt ?? null,
208
334
  lastDeploymentTimestamp: deployState.lastDeploymentTimestamp ?? null,
209
335
  lastDeployedUrl: deployState.lastDeployedUrl ?? null
@@ -218,7 +344,14 @@ function resolveTreeseedWorkflowState(cwd) {
218
344
  url: typeof latestHistory?.url === "string" ? latestHistory.url : deployState.lastDeployedUrl ?? null
219
345
  });
220
346
  }
221
- for (const serviceKey of ["api", "agents", "manager", "worker", "runner", "workdayStart", "workdayReport"]) {
347
+ if (scope === "prod") {
348
+ state.webCache.cloudflareRulesManaged = deployState.webCache?.rulesManaged === true;
349
+ state.webCache.lastDeployPurgeAt = deployState.webCache?.deployPurge?.lastPurgedAt ?? null;
350
+ state.webCache.lastDeployPurgeCount = deployState.webCache?.deployPurge?.purgeCount ?? null;
351
+ state.webCache.lastContentPurgeAt = deployState.webCache?.contentPurge?.lastPurgedAt ?? null;
352
+ state.webCache.lastContentPurgeCount = deployState.webCache?.contentPurge?.purgeCount ?? null;
353
+ }
354
+ for (const serviceKey of ["api", "manager", "worker", "workdayStart", "workdayReport"]) {
222
355
  const service = deployState.services?.[serviceKey];
223
356
  if (!service) continue;
224
357
  state.managedServices[serviceKey] = {
@@ -244,6 +377,12 @@ function resolveTreeseedWorkflowState(cwd) {
244
377
  state.readiness.local = readinessForEnvironment(state, "local");
245
378
  state.readiness.staging = readinessForEnvironment(state, "staging");
246
379
  state.readiness.prod = readinessForEnvironment(state, "prod");
380
+ state.marketConnection.verificationPosture = state.readiness.local.ready ? "ready" : state.files.machineConfig ? "blocked" : "pending";
381
+ const registrationRequired = state.marketConnection.runtimeRegistration === "required";
382
+ state.marketConnection.approvalBlockers = [
383
+ ...registrationRequired && !state.marketConnection.configured ? ["Knowledge Coop runtime attachment is not configured."] : [],
384
+ ...registrationRequired && !state.marketConnection.runtimeReady ? ["Knowledge Coop runtime credential is missing or not ready."] : []
385
+ ];
247
386
  state.recommendations = recommendTreeseedNextSteps(state);
248
387
  return state;
249
388
  }
@@ -257,7 +396,14 @@ function recommendTreeseedNextSteps(state) {
257
396
  }
258
397
  if (!state.files.machineConfig) {
259
398
  recommendations.push({ operation: "status", reason: "Validate tooling, auth, and repository readiness first." });
260
- recommendations.push({ operation: "config", reason: "Bootstrap the local machine config and local environment files." });
399
+ recommendations.push({ operation: "config", reason: "Bootstrap the local machine config and injected runtime environment." });
400
+ return recommendations;
401
+ }
402
+ if (!state.secrets.wrappedKeyPresent || state.secrets.migrationRequired) {
403
+ recommendations.push({
404
+ operation: state.secrets.migrationRequired ? "secrets:migrate-key" : "secrets:unlock",
405
+ reason: state.secrets.migrationRequired ? "Wrap the local machine key before running secret-backed commands." : "Create and unlock the local wrapped machine key before running secret-backed commands."
406
+ });
261
407
  return recommendations;
262
408
  }
263
409
  if (state.workflowControl.interruptedRuns.length > 0) {
@@ -303,7 +449,7 @@ function recommendTreeseedNextSteps(state) {
303
449
  recommendations.push({ operation: "config", reason: "Initialize the staging environment before releasing.", input: { environment: ["staging"] } });
304
450
  } else {
305
451
  recommendations.push({ operation: "release", reason: "Promote staging into main when the integration branch is ready for production.", input: { bump: "patch" } });
306
- if (state.managedServices.api.enabled || state.managedServices.agents.enabled) {
452
+ if (state.managedServices.api.enabled) {
307
453
  recommendations.push({ operation: "auth:login", reason: "Keep the local runtime authenticated to the remote API used by managed services." });
308
454
  }
309
455
  }
@@ -1,4 +1,4 @@
1
- export { applyTreeseedConfigValues, applyTreeseedEnvironmentToProcess, applyTreeseedSafeRepairs, assertTreeseedCommandEnvironment, checkTreeseedProviderConnections, clearTreeseedRemoteSession, collectTreeseedConfigContext, collectTreeseedPrintEnvReport, createDefaultTreeseedMachineConfig, ensureTreeseedGitignoreEntries, getTreeseedMachineConfigPaths, loadTreeseedMachineConfig, listRelevantTreeseedConfigEntries, finalizeTreeseedConfig, resolveTreeseedMachineEnvironmentValues, resolveTreeseedRemoteConfig, resolveTreeseedRemoteSession, rotateTreeseedMachineKey, setTreeseedRemoteSession, writeTreeseedLocalEnvironmentFiles, writeTreeseedMachineConfig, } from './operations/services/config-runtime.ts';
1
+ export { applyTreeseedConfigValues, applyTreeseedEnvironmentToProcess, applyTreeseedSafeRepairs, assertTreeseedCommandEnvironment, checkTreeseedProviderConnections, clearTreeseedRemoteSession, collectTreeseedConfigContext, collectTreeseedPrintEnvReport, createDefaultTreeseedMachineConfig, ensureTreeseedActVerificationTooling, ensureTreeseedSecretSessionForConfig, ensureTreeseedGitignoreEntries, getTreeseedMachineConfigPaths, loadTreeseedMachineConfig, listRelevantTreeseedConfigEntries, finalizeTreeseedConfig, listDeprecatedTreeseedLocalEnvFiles, inspectTreeseedKeyAgentStatus, lockTreeseedSecretSession, migrateTreeseedMachineKeyToWrapped, resolveTreeseedMachineEnvironmentValues, resolveTreeseedLaunchEnvironment, resolveTreeseedRemoteConfig, resolveTreeseedRemoteSession, rotateTreeseedMachineKey, rotateTreeseedMachineKeyPassphrase, setTreeseedRemoteSession, TREESEED_MACHINE_KEY_PASSPHRASE_ENV, TreeseedKeyAgentError, updateTreeseedDeployConfigFeatureToggles, unlockTreeseedSecretSessionFromEnv, unlockTreeseedSecretSessionInteractive, unlockTreeseedSecretSessionWithPassphrase, withTreeseedKeyAgentAutopromptDisabled, warnDeprecatedTreeseedLocalEnvFiles, writeTreeseedMachineConfig, } from './operations/services/config-runtime.ts';
2
2
  export { exportTreeseedCodebase } from './operations/services/export-runtime.ts';
3
3
  export { assertDeploymentInitialized, cleanupDestroyedState, createBranchPreviewDeployTarget, createPersistentDeployTarget, deployTargetLabel, destroyCloudflareResources, ensureGeneratedWranglerConfig, finalizeDeploymentState, loadDeployState, printDeploySummary, printDestroySummary, provisionCloudflareResources, runRemoteD1Migrations, syncCloudflareSecrets, validateDeployPrerequisites, validateDestroyPrerequisites, } from './operations/services/deploy.ts';
4
4
  export { assertCleanWorktree, assertFeatureBranch, branchExists, checkoutBranch, createDeprecatedTaskTag, createFeatureBranchFromStaging, currentManagedBranch, deleteLocalBranch, deleteRemoteBranch, ensureLocalBranchTracking, gitWorkflowRoot, listTaskBranches, mergeCurrentBranchIntoStaging, mergeStagingIntoMain, prepareReleaseBranches, PRODUCTION_BRANCH, pushBranch, remoteBranchExists, STAGING_BRANCH, syncBranchWithOrigin, waitForStagingAutomation, } from './operations/services/git-workflow.ts';
@@ -8,17 +8,32 @@ import {
8
8
  collectTreeseedConfigContext,
9
9
  collectTreeseedPrintEnvReport,
10
10
  createDefaultTreeseedMachineConfig,
11
+ ensureTreeseedActVerificationTooling,
12
+ ensureTreeseedSecretSessionForConfig,
11
13
  ensureTreeseedGitignoreEntries,
12
14
  getTreeseedMachineConfigPaths,
13
15
  loadTreeseedMachineConfig,
14
16
  listRelevantTreeseedConfigEntries,
15
17
  finalizeTreeseedConfig,
18
+ listDeprecatedTreeseedLocalEnvFiles,
19
+ inspectTreeseedKeyAgentStatus,
20
+ lockTreeseedSecretSession,
21
+ migrateTreeseedMachineKeyToWrapped,
16
22
  resolveTreeseedMachineEnvironmentValues,
23
+ resolveTreeseedLaunchEnvironment,
17
24
  resolveTreeseedRemoteConfig,
18
25
  resolveTreeseedRemoteSession,
19
26
  rotateTreeseedMachineKey,
27
+ rotateTreeseedMachineKeyPassphrase,
20
28
  setTreeseedRemoteSession,
21
- writeTreeseedLocalEnvironmentFiles,
29
+ TREESEED_MACHINE_KEY_PASSPHRASE_ENV,
30
+ TreeseedKeyAgentError,
31
+ updateTreeseedDeployConfigFeatureToggles,
32
+ unlockTreeseedSecretSessionFromEnv,
33
+ unlockTreeseedSecretSessionInteractive,
34
+ unlockTreeseedSecretSessionWithPassphrase,
35
+ withTreeseedKeyAgentAutopromptDisabled,
36
+ warnDeprecatedTreeseedLocalEnvFiles,
22
37
  writeTreeseedMachineConfig
23
38
  } from "./operations/services/config-runtime.js";
24
39
  import { exportTreeseedCodebase } from "./operations/services/export-runtime.js";
@@ -100,6 +115,8 @@ import {
100
115
  export {
101
116
  PRODUCTION_BRANCH,
102
117
  STAGING_BRANCH,
118
+ TREESEED_MACHINE_KEY_PASSPHRASE_ENV,
119
+ TreeseedKeyAgentError,
103
120
  applyTreeseedConfigValues,
104
121
  applyTreeseedEnvironmentToProcess,
105
122
  applyTreeseedSafeRepairs,
@@ -132,7 +149,9 @@ export {
132
149
  destroyCloudflareResources,
133
150
  ensureGeneratedWranglerConfig,
134
151
  ensureLocalBranchTracking,
152
+ ensureTreeseedActVerificationTooling,
135
153
  ensureTreeseedGitignoreEntries,
154
+ ensureTreeseedSecretSessionForConfig,
136
155
  exportTreeseedCodebase,
137
156
  finalizeDeploymentState,
138
157
  finalizeTreeseedConfig,
@@ -144,14 +163,18 @@ export {
144
163
  gitWorkflowRoot,
145
164
  hasMeaningfulChanges,
146
165
  incrementVersion,
166
+ inspectTreeseedKeyAgentStatus,
147
167
  isWorkspaceRoot,
168
+ listDeprecatedTreeseedLocalEnvFiles,
148
169
  listRelevantTreeseedConfigEntries,
149
170
  listTaskBranches,
150
171
  loadCliDeployConfig,
151
172
  loadDeployState,
152
173
  loadTreeseedMachineConfig,
174
+ lockTreeseedSecretSession,
153
175
  mergeCurrentBranchIntoStaging,
154
176
  mergeStagingIntoMain,
177
+ migrateTreeseedMachineKeyToWrapped,
155
178
  originRemoteUrl,
156
179
  packageScriptPath,
157
180
  planWorkspaceReleaseBump,
@@ -162,11 +185,13 @@ export {
162
185
  pushBranch,
163
186
  remoteBranchExists,
164
187
  repoRoot,
188
+ resolveTreeseedLaunchEnvironment,
165
189
  resolveTreeseedMachineEnvironmentValues,
166
190
  resolveTreeseedRemoteConfig,
167
191
  resolveTreeseedRemoteSession,
168
192
  resolveWranglerBin,
169
193
  rotateTreeseedMachineKey,
194
+ rotateTreeseedMachineKeyPassphrase,
170
195
  run,
171
196
  runRemoteD1Migrations,
172
197
  runTenantDeployPreflight,
@@ -174,11 +199,16 @@ export {
174
199
  setTreeseedRemoteSession,
175
200
  syncBranchWithOrigin,
176
201
  syncCloudflareSecrets,
202
+ unlockTreeseedSecretSessionFromEnv,
203
+ unlockTreeseedSecretSessionInteractive,
204
+ unlockTreeseedSecretSessionWithPassphrase,
205
+ updateTreeseedDeployConfigFeatureToggles,
177
206
  validateDeployPrerequisites,
178
207
  validateDestroyPrerequisites,
179
208
  validateRailwayDeployPrerequisites,
180
209
  waitForStagingAutomation,
210
+ warnDeprecatedTreeseedLocalEnvFiles,
211
+ withTreeseedKeyAgentAutopromptDisabled,
181
212
  workspaceRoot,
182
- writeTreeseedLocalEnvironmentFiles,
183
213
  writeTreeseedMachineConfig
184
214
  };
@@ -72,6 +72,23 @@ export type TreeseedTaskBranchMetadata = ReturnType<typeof listTaskBranches>[num
72
72
  aligned: boolean;
73
73
  }>;
74
74
  };
75
+ export type TreeseedWorkflowWorkstreamSummary = {
76
+ id: string;
77
+ title: string;
78
+ linkedDirectRefs: Array<{
79
+ model: 'objective' | 'question' | 'note';
80
+ id: string;
81
+ }>;
82
+ branch: string;
83
+ local: boolean;
84
+ remote: boolean;
85
+ current: boolean;
86
+ previewUrl: string | null;
87
+ lastSaveAt: string | null;
88
+ verificationResult: 'ready' | 'needs_attention' | 'unknown';
89
+ stagingCandidate: boolean;
90
+ archived: boolean;
91
+ };
75
92
  export type TreeseedSaveInput = {
76
93
  message: string;
77
94
  hotfix?: boolean;
@@ -125,6 +142,16 @@ export type TreeseedConfigInput = {
125
142
  printEnvOnly?: boolean;
126
143
  showSecrets?: boolean;
127
144
  rotateMachineKey?: boolean;
145
+ connectMarket?: boolean;
146
+ marketBaseUrl?: string;
147
+ marketTeamId?: string;
148
+ marketTeamSlug?: string;
149
+ marketProjectId?: string;
150
+ marketProjectSlug?: string;
151
+ marketProjectApiBaseUrl?: string;
152
+ marketAccessToken?: string;
153
+ rotateRunnerToken?: boolean;
154
+ installMissingTooling?: boolean;
128
155
  nonInteractive?: boolean;
129
156
  };
130
157
  export type TreeseedExportInput = {
@@ -166,10 +193,12 @@ export declare class TreeseedWorkflowSdk {
166
193
  private helpers;
167
194
  execute(operation: TreeseedWorkflowOperationId, input?: Record<string, unknown>): Promise<TreeseedWorkflowResult<import("./workflow-state.ts").TreeseedWorkflowState> | TreeseedWorkflowResult<{
168
195
  tasks: TreeseedTaskBranchMetadata[];
196
+ workstreams: TreeseedWorkflowWorkstreamSummary[];
169
197
  }> | TreeseedWorkflowResult<Record<string, unknown>>>;
170
198
  status(): Promise<TreeseedWorkflowResult<ReturnType<typeof resolveTreeseedWorkflowState>>>;
171
199
  tasks(): Promise<TreeseedWorkflowResult<{
172
200
  tasks: TreeseedTaskBranchMetadata[];
201
+ workstreams: TreeseedWorkflowWorkstreamSummary[];
173
202
  }>>;
174
203
  config(input?: TreeseedConfigInput): Promise<TreeseedWorkflowResult>;
175
204
  switchTask(input: TreeseedSwitchInput): Promise<TreeseedWorkflowResult>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeseed/sdk",
3
- "version": "0.4.13",
3
+ "version": "0.5.1",
4
4
  "description": "Shared Treeseed SDK for content-backed and D1-backed object models.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -98,7 +98,7 @@ jobs:
98
98
  while IFS= read -r path; do
99
99
  [[ -z "${path}" ]] && continue
100
100
  case "${path}" in
101
- src/content/*|content/*|books/*|docs/*|public/books/*|migrations/*)
101
+ src/content/*|content/*|books/*|docs/*|migrations/*)
102
102
  content_changed="true"
103
103
  ;;
104
104
  *)
@@ -287,6 +287,7 @@ __WORKING_DIRECTORY_BLOCK__
287
287
  TREESEED_RAILWAY_PROJECT_ID: ${{ vars.TREESEED_RAILWAY_PROJECT_ID }}
288
288
  TREESEED_RAILWAY_ENVIRONMENT_ID: ${{ vars.TREESEED_RAILWAY_ENVIRONMENT_ID }}
289
289
  TREESEED_RAILWAY_WORKER_SERVICE_ID: ${{ vars.TREESEED_RAILWAY_WORKER_SERVICE_ID }}
290
+ TREESEED_CONTENT_SERVING_MODE: published_runtime
290
291
  TREESEED_WORKFLOW_ACTION: deploy_code
291
292
  TREESEED_WORKFLOW_ENVIRONMENT: ${{ needs.classify.outputs.scope }}
292
293
  TREESEED_WORKFLOW_PROJECT: ${{ inputs.project_id || vars.TREESEED_PROJECT_ID }}
@@ -294,6 +295,15 @@ __WORKING_DIRECTORY_BLOCK__
294
295
  steps:
295
296
  - name: Checkout
296
297
  uses: actions/checkout@v4
298
+ with:
299
+ submodules: false
300
+ sparse-checkout: |
301
+ /*
302
+ !/src/content/
303
+ !/src/content/**
304
+ !/public/books/
305
+ !/public/books/**
306
+ sparse-checkout-cone-mode: false
297
307
 
298
308
  - name: Setup Node
299
309
  uses: actions/setup-node@v4
@@ -1,6 +0,0 @@
1
- import { applyTreeseedEnvironmentToProcess, writeTreeseedLocalEnvironmentFiles } from '../operations/services/config-runtime.js';
2
- const tenantRoot = process.cwd();
3
- applyTreeseedEnvironmentToProcess({ tenantRoot, scope: 'local', override: true });
4
- const result = writeTreeseedLocalEnvironmentFiles(tenantRoot);
5
- console.log(`Wrote ${result.envLocalPath}`);
6
- console.log(`Wrote ${result.devVarsPath}`);