@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.
- package/dist/control-plane-client.d.ts +60 -1
- package/dist/control-plane-client.js +59 -0
- package/dist/control-plane.d.ts +1 -1
- package/dist/control-plane.js +11 -4
- package/dist/d1-store.d.ts +58 -0
- package/dist/d1-store.js +64 -0
- package/dist/dispatch.js +6 -0
- package/dist/graph/schema.js +4 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +32 -0
- package/dist/knowledge-coop.d.ts +223 -0
- package/dist/knowledge-coop.js +82 -0
- package/dist/model-registry.js +79 -0
- package/dist/operations/providers/default.js +126 -7
- package/dist/operations/services/config-runtime.d.ts +102 -24
- package/dist/operations/services/config-runtime.js +896 -160
- package/dist/operations/services/deploy.d.ts +223 -15
- package/dist/operations/services/deploy.js +626 -55
- package/dist/operations/services/github-automation.d.ts +60 -0
- package/dist/operations/services/github-automation.js +138 -0
- package/dist/operations/services/key-agent.d.ts +118 -0
- package/dist/operations/services/key-agent.js +476 -0
- package/dist/operations/services/knowledge-coop-launch.d.ts +90 -0
- package/dist/operations/services/knowledge-coop-launch.js +753 -0
- package/dist/operations/services/knowledge-coop-packaging.d.ts +59 -0
- package/dist/operations/services/knowledge-coop-packaging.js +234 -0
- package/dist/operations/services/local-dev.d.ts +0 -1
- package/dist/operations/services/local-dev.js +1 -14
- package/dist/operations/services/project-platform.d.ts +42 -182
- package/dist/operations/services/project-platform.js +162 -59
- package/dist/operations/services/railway-deploy.d.ts +1 -0
- package/dist/operations/services/railway-deploy.js +31 -13
- package/dist/operations/services/runtime-tools.d.ts +52 -5
- package/dist/operations/services/runtime-tools.js +186 -26
- package/dist/operations/services/watch-dev.js +2 -4
- package/dist/operations/services/workspace-preflight.d.ts +4 -4
- package/dist/operations/services/workspace-preflight.js +22 -20
- package/dist/operations-registry.js +7 -2
- package/dist/platform/contracts.d.ts +39 -3
- package/dist/platform/deploy-config.d.ts +12 -1
- package/dist/platform/deploy-config.js +214 -15
- package/dist/platform/deploy-runtime.d.ts +1 -0
- package/dist/platform/deploy-runtime.js +10 -2
- package/dist/platform/env.yaml +93 -61
- package/dist/platform/environment.d.ts +13 -2
- package/dist/platform/environment.js +90 -20
- package/dist/platform/plugins/constants.d.ts +1 -0
- package/dist/platform/plugins/constants.js +7 -6
- package/dist/platform/tenant/runtime-config.js +8 -1
- package/dist/platform/tenant-config.js +4 -0
- package/dist/platform/utils/site-config-schema.js +18 -0
- package/dist/plugin-default.js +2 -2
- package/dist/scripts/key-agent.js +165 -0
- package/dist/scripts/tenant-build.js +4 -1
- package/dist/scripts/tenant-check.js +4 -1
- package/dist/scripts/tenant-deploy.js +43 -4
- package/dist/scripts/tenant-dev.js +0 -1
- package/dist/sdk-types.d.ts +2 -2
- package/dist/sdk-types.js +2 -0
- package/dist/sdk.d.ts +13 -0
- package/dist/sdk.js +40 -0
- package/dist/stores/knowledge-coop-store.d.ts +56 -0
- package/dist/stores/knowledge-coop-store.js +482 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +6 -2
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/api/server.js +4 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +25 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/decisions/adopt-initial-proposal-loop.mdx +22 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/people/starter-steward.mdx +11 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/proposals/establish-initial-proposal-loop.mdx +17 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +17 -10
- package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +69 -7
- package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +1 -0
- package/dist/verification.js +90 -2
- package/dist/workflow/operations.d.ts +98 -0
- package/dist/workflow/operations.js +229 -7
- package/dist/workflow-state.d.ts +54 -2
- package/dist/workflow-state.js +170 -24
- package/dist/workflow-support.d.ts +1 -1
- package/dist/workflow-support.js +32 -2
- package/dist/workflow.d.ts +29 -0
- package/package.json +1 -1
- package/templates/github/deploy.workflow.yml +11 -1
- package/dist/scripts/sync-dev-vars.js +0 -6
package/dist/workflow-state.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import {
|
|
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 (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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(
|
|
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
|
-
|
|
189
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
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';
|
package/dist/workflow-support.js
CHANGED
|
@@ -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
|
-
|
|
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
|
};
|
package/dist/workflow.d.ts
CHANGED
|
@@ -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
|
@@ -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/*|
|
|
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}`);
|