@treeseed/sdk 0.4.13 → 0.5.0
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/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
|
@@ -0,0 +1,753 @@
|
|
|
1
|
+
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
6
|
+
import { checkTreeseedProviderConnections, collectTreeseedConfigSeedValues } from "./config-runtime.js";
|
|
7
|
+
import { provisionCloudflareResources, runRemoteD1Migrations, syncCloudflareSecrets, verifyProvisionedCloudflareResources, markDeploymentInitialized, finalizeDeploymentState } from "./deploy.js";
|
|
8
|
+
import {
|
|
9
|
+
createGitHubRepository,
|
|
10
|
+
ensureGitHubDeployAutomation,
|
|
11
|
+
initializeGitHubRepositoryWorkingTree,
|
|
12
|
+
resolveDefaultGitHubOwner
|
|
13
|
+
} from "./github-automation.js";
|
|
14
|
+
import { configuredRailwayServices, deployRailwayService, ensureRailwayScheduledJobs, validateRailwayDeployPrerequisites, verifyRailwayScheduledJobs } from "./railway-deploy.js";
|
|
15
|
+
import { loadCliDeployConfig } from "./runtime-tools.js";
|
|
16
|
+
import { templateCatalogRoot } from "./runtime-paths.js";
|
|
17
|
+
import { scaffoldTemplateProject } from "./template-registry.js";
|
|
18
|
+
import { buildKnowledgeCoopKnowledgePackPackage, buildKnowledgeCoopTemplatePackage, importKnowledgeCoopKnowledgePack } from "./knowledge-coop-packaging.js";
|
|
19
|
+
class KnowledgeCoopLaunchError extends Error {
|
|
20
|
+
phase;
|
|
21
|
+
phases;
|
|
22
|
+
constructor(phase, message, phases = []) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = "KnowledgeCoopLaunchError";
|
|
25
|
+
this.phase = phase;
|
|
26
|
+
this.phases = [...phases];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function nowIso() {
|
|
30
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
31
|
+
}
|
|
32
|
+
function slugify(value, fallback = "project") {
|
|
33
|
+
return String(value ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-").slice(0, 96) || fallback;
|
|
34
|
+
}
|
|
35
|
+
function envOrNull(name) {
|
|
36
|
+
const value = process.env[name];
|
|
37
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
38
|
+
}
|
|
39
|
+
function normalizeBaseUrl(value) {
|
|
40
|
+
return String(value ?? "").trim().replace(/\/+$/u, "");
|
|
41
|
+
}
|
|
42
|
+
function resolveManagedWebUrl(slug) {
|
|
43
|
+
const baseDomain = envOrNull("TREESEED_MANAGED_WEB_BASE_DOMAIN");
|
|
44
|
+
if (baseDomain) {
|
|
45
|
+
return `https://${slug}.${baseDomain.replace(/^https?:\/\//u, "").replace(/^\.|\/+$/gu, "")}`;
|
|
46
|
+
}
|
|
47
|
+
return `https://${slug}.pages.dev`;
|
|
48
|
+
}
|
|
49
|
+
function resolveManagedApiUrl(slug) {
|
|
50
|
+
const baseDomain = envOrNull("TREESEED_MANAGED_API_BASE_DOMAIN");
|
|
51
|
+
if (baseDomain) {
|
|
52
|
+
return `https://${slug}-api.${baseDomain.replace(/^https?:\/\//u, "").replace(/^\.|\/+$/gu, "")}`;
|
|
53
|
+
}
|
|
54
|
+
return `https://${slug}-api.up.railway.app`;
|
|
55
|
+
}
|
|
56
|
+
function ensureDir(path) {
|
|
57
|
+
mkdirSync(path, { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
function runGit(cwd, args, capture = true) {
|
|
60
|
+
const result = spawnSync("git", args, {
|
|
61
|
+
cwd,
|
|
62
|
+
stdio: capture ? "pipe" : "inherit",
|
|
63
|
+
encoding: "utf8"
|
|
64
|
+
});
|
|
65
|
+
if (result.status !== 0) {
|
|
66
|
+
throw new Error(result.stderr?.trim() || result.stdout?.trim() || `git ${args.join(" ")} failed`);
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
function writeText(path, body) {
|
|
71
|
+
ensureDir(dirname(path));
|
|
72
|
+
writeFileSync(path, body, "utf8");
|
|
73
|
+
}
|
|
74
|
+
function updateYamlFile(path, updater) {
|
|
75
|
+
const parsed = parseYaml(readFileSync(path, "utf8"));
|
|
76
|
+
const next = updater(parsed ?? {});
|
|
77
|
+
writeText(path, stringifyYaml(next));
|
|
78
|
+
}
|
|
79
|
+
function currentTemplateCatalogUrl() {
|
|
80
|
+
return `file:${resolve(templateCatalogRoot, "catalog.fixture.json")}`;
|
|
81
|
+
}
|
|
82
|
+
function seedKnowledgeCoopContent(projectRoot, input) {
|
|
83
|
+
const objectiveId = `objective:launch-${slugify(input.projectSlug, "hub")}`;
|
|
84
|
+
const questionId = `question:operating-${slugify(input.projectSlug, "hub")}`;
|
|
85
|
+
const proposalId = `proposal:operating-${slugify(input.projectSlug, "hub")}`;
|
|
86
|
+
const decisionId = `decision:launch-${slugify(input.projectSlug, "hub")}`;
|
|
87
|
+
const stewardSlug = "launch-steward";
|
|
88
|
+
const noteSlug = `${slugify(input.projectSlug, "hub")}-operating-model`;
|
|
89
|
+
writeText(resolve(projectRoot, "src/content/people", `${stewardSlug}.mdx`), `---
|
|
90
|
+
name: Launch Steward
|
|
91
|
+
role: Team steward
|
|
92
|
+
affiliation: ${input.projectName}
|
|
93
|
+
status: live
|
|
94
|
+
tags:
|
|
95
|
+
- launch
|
|
96
|
+
- stewardship
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
The launch steward keeps the first operating cycle legible while the hub moves from setup into active use.
|
|
100
|
+
`);
|
|
101
|
+
writeText(resolve(projectRoot, "src/content/objectives", "launch-knowledge-hub.mdx"), `---
|
|
102
|
+
id: ${objectiveId}
|
|
103
|
+
title: Launch ${input.projectName}
|
|
104
|
+
description: Bring the initial knowledge hub online with live managed infrastructure and a clear operating direction.
|
|
105
|
+
date: ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
|
|
106
|
+
summary: Stand up the hub, connect the runtime, and make the first workstream visible to the team.
|
|
107
|
+
status: live
|
|
108
|
+
timeHorizon: near-term
|
|
109
|
+
motivation: Knowledge Coop launches should create immediately usable hubs instead of leaving teams in setup limbo.
|
|
110
|
+
primaryContributor: ${stewardSlug}
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
Launch ${input.projectName} as a living knowledge hub with real GitHub, Cloudflare, and Railway infrastructure.
|
|
114
|
+
`);
|
|
115
|
+
writeText(resolve(projectRoot, "src/content/questions", "what-should-the-first-release-cover.mdx"), `---
|
|
116
|
+
id: ${questionId}
|
|
117
|
+
title: What Should The First Release Cover?
|
|
118
|
+
description: Scope the first release around the foundation of the hub and the initial operating routines.
|
|
119
|
+
date: ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
|
|
120
|
+
summary: Define the first release around setup completion, clear direction, and baseline operating visibility.
|
|
121
|
+
status: live
|
|
122
|
+
questionType: strategy
|
|
123
|
+
motivation: The first release should make the new hub usable without burying the team under setup debt.
|
|
124
|
+
primaryContributor: ${stewardSlug}
|
|
125
|
+
relatedObjectives:
|
|
126
|
+
- launch-knowledge-hub
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
The first release should verify that the hub is live, the core direction is visible, and the team can move from Direct into Workstreams without setup debt.
|
|
130
|
+
`);
|
|
131
|
+
writeText(resolve(projectRoot, "src/content/notes", `${noteSlug}.mdx`), `---
|
|
132
|
+
title: ${input.projectName} Operating Model
|
|
133
|
+
description: The initial working agreements for this Knowledge Coop hub.
|
|
134
|
+
date: ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
|
|
135
|
+
summary: Managed launch created the default branches, runtime wiring, and first operational checkpoints.
|
|
136
|
+
status: live
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
This hub starts with a managed launch, a seeded objective, and a visible first workstream so the team can continue from a known baseline.
|
|
140
|
+
`);
|
|
141
|
+
writeText(resolve(projectRoot, "src/content/proposals", "establish-initial-operating-routine.mdx"), `---
|
|
142
|
+
id: ${proposalId}
|
|
143
|
+
title: Establish The Initial Operating Routine
|
|
144
|
+
description: Turn the seeded objective and question into a concrete launch proposal for the first team cycle.
|
|
145
|
+
date: ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
|
|
146
|
+
summary: Make the launch posture explicit so the team can move from setup into a concrete operating loop.
|
|
147
|
+
status: live
|
|
148
|
+
proposalType: strategy
|
|
149
|
+
motivation: Managed launches work better when the first suggested operating pattern is visible in the content model.
|
|
150
|
+
primaryContributor: ${stewardSlug}
|
|
151
|
+
relatedObjectives:
|
|
152
|
+
- launch-knowledge-hub
|
|
153
|
+
relatedQuestions:
|
|
154
|
+
- what-should-the-first-release-cover
|
|
155
|
+
relatedNotes:
|
|
156
|
+
- ${noteSlug}
|
|
157
|
+
decision: adopt-initial-launch-posture
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
Adopt a simple first operating routine: keep direction visible, keep the first release narrow, and use notes to capture implementation reality as the hub stabilizes.
|
|
161
|
+
`);
|
|
162
|
+
writeText(resolve(projectRoot, "src/content/decisions", "adopt-initial-launch-posture.mdx"), `---
|
|
163
|
+
id: ${decisionId}
|
|
164
|
+
title: Adopt The Initial Launch Posture
|
|
165
|
+
description: Record the launch decision for the first operating cycle of the hub.
|
|
166
|
+
date: ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
|
|
167
|
+
summary: The managed launch will begin with a narrow first release and explicit direction artifacts.
|
|
168
|
+
status: live
|
|
169
|
+
decisionType: approved
|
|
170
|
+
rationale: The initial launch should bias toward clarity, setup completion, and a visible first release loop.
|
|
171
|
+
authority: Knowledge Coop managed launch
|
|
172
|
+
primaryContributor: ${stewardSlug}
|
|
173
|
+
relatedObjectives:
|
|
174
|
+
- launch-knowledge-hub
|
|
175
|
+
relatedQuestions:
|
|
176
|
+
- what-should-the-first-release-cover
|
|
177
|
+
relatedNotes:
|
|
178
|
+
- ${noteSlug}
|
|
179
|
+
relatedProposals:
|
|
180
|
+
- establish-initial-operating-routine
|
|
181
|
+
implements:
|
|
182
|
+
- direct
|
|
183
|
+
- workstreams
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
The first cycle will keep direction and execution tightly connected: one seeded objective, one seeded question, one proposal, one recorded launch decision, and a narrow release target.
|
|
187
|
+
`);
|
|
188
|
+
writeText(resolve(projectRoot, "src/content/knowledge", "handbook", "index.mdx"), `---
|
|
189
|
+
id: knowledge:${slugify(input.projectSlug, "hub")}-handbook
|
|
190
|
+
title: ${input.projectName} Handbook
|
|
191
|
+
description: Welcome guide for the first team working in this hub.
|
|
192
|
+
type: guide
|
|
193
|
+
status: canonical
|
|
194
|
+
tags:
|
|
195
|
+
- handbook
|
|
196
|
+
- launch
|
|
197
|
+
canonical: true
|
|
198
|
+
domain: product
|
|
199
|
+
audience:
|
|
200
|
+
- maintainer
|
|
201
|
+
- contributor
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
# ${input.projectName}
|
|
205
|
+
|
|
206
|
+
This knowledge hub was launched from Knowledge Coop and is ready for Direct, Workstreams, Releases, and Share workflows.
|
|
207
|
+
`);
|
|
208
|
+
writeText(resolve(projectRoot, "src/content/pages", "welcome.mdx"), `---
|
|
209
|
+
title: Welcome
|
|
210
|
+
description: ${input.projectName} is live.
|
|
211
|
+
pageLayout: article
|
|
212
|
+
stage: live
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
# ${input.projectName}
|
|
216
|
+
|
|
217
|
+
This hub is live and ready for the first team release cycle.
|
|
218
|
+
`);
|
|
219
|
+
return {
|
|
220
|
+
objectiveId,
|
|
221
|
+
questionId,
|
|
222
|
+
proposalId,
|
|
223
|
+
decisionId,
|
|
224
|
+
noteSlug
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function ensureHostedProjectFiles(projectRoot) {
|
|
228
|
+
const coreApiPackage = ["@treeseed", "core/api"].join("/");
|
|
229
|
+
writeText(resolve(projectRoot, "src/api/server.js"), `import { createRailwayTreeseedApiServer } from '${coreApiPackage}';
|
|
230
|
+
|
|
231
|
+
const server = await createRailwayTreeseedApiServer();
|
|
232
|
+
console.log(\`Treeseed project API listening on \${server.url}\`);
|
|
233
|
+
`);
|
|
234
|
+
}
|
|
235
|
+
function applyManagedProjectDefaults(projectRoot, input) {
|
|
236
|
+
const slug = slugify(input.projectSlug, "project");
|
|
237
|
+
const marketBaseUrl = normalizeBaseUrl(input.marketBaseUrl ?? envOrNull("TREESEED_MARKET_API_BASE_URL") ?? "https://knowledge.coop");
|
|
238
|
+
const siteUrl = resolveManagedWebUrl(slug);
|
|
239
|
+
const projectApiBaseUrl = normalizeBaseUrl(input.projectApiBaseUrl ?? resolveManagedApiUrl(slug));
|
|
240
|
+
const cloudflareAccountId = envOrNull("TREESEED_CLOUDFLARE_ACCOUNT_ID") ?? envOrNull("CLOUDFLARE_ACCOUNT_ID") ?? "replace-with-cloudflare-account-id";
|
|
241
|
+
const runtimeMode = input.hostingMode === "managed" ? "treeseed_managed" : input.hostingMode === "hybrid" ? "byo_attached" : "none";
|
|
242
|
+
const runtimeRegistration = input.hostingMode === "managed" ? "required" : input.hostingMode === "hybrid" ? "optional" : "none";
|
|
243
|
+
const hubMode = input.hostingMode === "self_hosted" ? "customer_hosted" : "treeseed_hosted";
|
|
244
|
+
const managedRuntime = runtimeMode === "treeseed_managed";
|
|
245
|
+
updateYamlFile(resolve(projectRoot, "treeseed.site.yaml"), (config) => ({
|
|
246
|
+
...config,
|
|
247
|
+
name: input.projectName,
|
|
248
|
+
slug,
|
|
249
|
+
siteUrl,
|
|
250
|
+
contactEmail: input.contactEmail ?? config.contactEmail ?? `hello+${slug}@knowledge.coop`,
|
|
251
|
+
hub: {
|
|
252
|
+
mode: hubMode
|
|
253
|
+
},
|
|
254
|
+
runtime: {
|
|
255
|
+
mode: runtimeMode,
|
|
256
|
+
registration: runtimeRegistration,
|
|
257
|
+
marketBaseUrl,
|
|
258
|
+
teamId: input.teamId,
|
|
259
|
+
projectId: input.projectId
|
|
260
|
+
},
|
|
261
|
+
hosting: {
|
|
262
|
+
kind: managedRuntime ? "hosted_project" : "self_hosted_project",
|
|
263
|
+
registration: runtimeRegistration === "required" ? "optional" : runtimeRegistration,
|
|
264
|
+
marketBaseUrl,
|
|
265
|
+
teamId: input.teamId,
|
|
266
|
+
projectId: input.projectId
|
|
267
|
+
},
|
|
268
|
+
cloudflare: {
|
|
269
|
+
...config.cloudflare ?? {},
|
|
270
|
+
accountId: cloudflareAccountId,
|
|
271
|
+
workerName: slug,
|
|
272
|
+
queueName: `${slug}-agent-work`,
|
|
273
|
+
dlqName: `${slug}-agent-work-dlq`,
|
|
274
|
+
pages: {
|
|
275
|
+
projectName: slug,
|
|
276
|
+
previewProjectName: `${slug}-staging`,
|
|
277
|
+
productionBranch: "main",
|
|
278
|
+
stagingBranch: "staging",
|
|
279
|
+
buildOutputDir: "dist",
|
|
280
|
+
...(config.cloudflare ?? {}).pages ?? {}
|
|
281
|
+
},
|
|
282
|
+
r2: {
|
|
283
|
+
binding: "TREESEED_CONTENT_BUCKET",
|
|
284
|
+
bucketName: `${slug}-content`,
|
|
285
|
+
manifestKeyTemplate: "teams/{teamId}/published/common.json",
|
|
286
|
+
previewRootTemplate: "teams/{teamId}/previews",
|
|
287
|
+
previewTtlHours: 168,
|
|
288
|
+
...(config.cloudflare ?? {}).r2 ?? {}
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
surfaces: {
|
|
292
|
+
web: {
|
|
293
|
+
enabled: true,
|
|
294
|
+
provider: "cloudflare",
|
|
295
|
+
rootDir: ".",
|
|
296
|
+
publicBaseUrl: siteUrl,
|
|
297
|
+
localBaseUrl: "http://127.0.0.1:4321",
|
|
298
|
+
...config.surfaces?.web ?? {}
|
|
299
|
+
},
|
|
300
|
+
api: {
|
|
301
|
+
enabled: managedRuntime,
|
|
302
|
+
provider: managedRuntime ? "railway" : "none",
|
|
303
|
+
rootDir: ".",
|
|
304
|
+
localBaseUrl: "http://127.0.0.1:3000",
|
|
305
|
+
...config.surfaces?.api ?? {}
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
services: {
|
|
309
|
+
api: {
|
|
310
|
+
enabled: managedRuntime,
|
|
311
|
+
provider: managedRuntime ? "railway" : "none",
|
|
312
|
+
rootDir: ".",
|
|
313
|
+
publicBaseUrl: projectApiBaseUrl,
|
|
314
|
+
railway: {
|
|
315
|
+
serviceName: `${slug}-api`,
|
|
316
|
+
buildCommand: "npm run build",
|
|
317
|
+
startCommand: "node ./src/api/server.js"
|
|
318
|
+
},
|
|
319
|
+
environments: {
|
|
320
|
+
local: {
|
|
321
|
+
baseUrl: "http://127.0.0.1:3000"
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
manager: {
|
|
326
|
+
enabled: managedRuntime,
|
|
327
|
+
provider: managedRuntime ? "railway" : "none",
|
|
328
|
+
railway: {
|
|
329
|
+
serviceName: `${slug}-manager`,
|
|
330
|
+
rootDir: ".",
|
|
331
|
+
buildCommand: "npm run build",
|
|
332
|
+
startCommand: "node ./node_modules/@treeseed/core/dist/services/manager.js",
|
|
333
|
+
schedule: "*/5 * * * *"
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
worker: {
|
|
337
|
+
enabled: managedRuntime,
|
|
338
|
+
provider: managedRuntime ? "railway" : "none",
|
|
339
|
+
railway: {
|
|
340
|
+
serviceName: `${slug}-worker`,
|
|
341
|
+
rootDir: ".",
|
|
342
|
+
buildCommand: "npm run build",
|
|
343
|
+
startCommand: "node ./node_modules/@treeseed/core/dist/services/worker.js"
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
workdayStart: {
|
|
347
|
+
enabled: managedRuntime,
|
|
348
|
+
provider: managedRuntime ? "railway" : "none",
|
|
349
|
+
railway: {
|
|
350
|
+
serviceName: `${slug}-workday-start`,
|
|
351
|
+
rootDir: ".",
|
|
352
|
+
buildCommand: "npm run build",
|
|
353
|
+
startCommand: "node ./node_modules/@treeseed/core/dist/services/workday-start.js",
|
|
354
|
+
schedule: "0 9 * * 1-5"
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
workdayReport: {
|
|
358
|
+
enabled: managedRuntime,
|
|
359
|
+
provider: managedRuntime ? "railway" : "none",
|
|
360
|
+
railway: {
|
|
361
|
+
serviceName: `${slug}-workday-report`,
|
|
362
|
+
rootDir: ".",
|
|
363
|
+
buildCommand: "npm run build",
|
|
364
|
+
startCommand: "node ./node_modules/@treeseed/core/dist/services/workday-report.js",
|
|
365
|
+
schedule: "5 17 * * 1-5"
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
...config.services ?? {}
|
|
369
|
+
},
|
|
370
|
+
plugins: [{ package: "@treeseed/core/plugin-default" }],
|
|
371
|
+
providers: {
|
|
372
|
+
...config.providers ?? {},
|
|
373
|
+
forms: config.providers?.forms ?? "store_only",
|
|
374
|
+
agents: {
|
|
375
|
+
execution: "copilot",
|
|
376
|
+
mutation: "local_branch",
|
|
377
|
+
repository: "git",
|
|
378
|
+
verification: "local",
|
|
379
|
+
notification: "sdk_message",
|
|
380
|
+
research: "project_graph",
|
|
381
|
+
...config.providers?.agents ?? {}
|
|
382
|
+
},
|
|
383
|
+
deploy: "cloudflare",
|
|
384
|
+
content: {
|
|
385
|
+
runtime: "team_scoped_r2_overlay",
|
|
386
|
+
publish: "team_scoped_r2_overlay",
|
|
387
|
+
docs: "default",
|
|
388
|
+
...config.providers?.content ?? {}
|
|
389
|
+
},
|
|
390
|
+
site: "default"
|
|
391
|
+
}
|
|
392
|
+
}));
|
|
393
|
+
updateYamlFile(resolve(projectRoot, "src/manifest.yaml"), (manifest) => ({
|
|
394
|
+
...manifest,
|
|
395
|
+
id: slug,
|
|
396
|
+
content: {
|
|
397
|
+
...manifest.content ?? {},
|
|
398
|
+
docs: "./src/content/knowledge",
|
|
399
|
+
pages: "./src/content/pages",
|
|
400
|
+
notes: "./src/content/notes",
|
|
401
|
+
questions: "./src/content/questions",
|
|
402
|
+
objectives: "./src/content/objectives",
|
|
403
|
+
proposals: "./src/content/proposals",
|
|
404
|
+
decisions: "./src/content/decisions",
|
|
405
|
+
people: "./src/content/people",
|
|
406
|
+
agents: "./src/content/agents",
|
|
407
|
+
books: "./src/content/books",
|
|
408
|
+
templates: "./src/content/templates",
|
|
409
|
+
knowledge_packs: "./src/content/knowledge-packs",
|
|
410
|
+
workdays: "./src/content/workdays"
|
|
411
|
+
},
|
|
412
|
+
features: {
|
|
413
|
+
docs: true,
|
|
414
|
+
books: false,
|
|
415
|
+
notes: true,
|
|
416
|
+
questions: true,
|
|
417
|
+
objectives: true,
|
|
418
|
+
proposals: true,
|
|
419
|
+
decisions: true,
|
|
420
|
+
agents: input.enableDefaultAgents !== false,
|
|
421
|
+
forms: false,
|
|
422
|
+
...manifest.features ?? {}
|
|
423
|
+
}
|
|
424
|
+
}));
|
|
425
|
+
return {
|
|
426
|
+
slug,
|
|
427
|
+
siteUrl,
|
|
428
|
+
projectApiBaseUrl,
|
|
429
|
+
marketBaseUrl,
|
|
430
|
+
cloudflareAccountId
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
function createDefaultWorkstream(projectId, input, seed) {
|
|
434
|
+
return {
|
|
435
|
+
id: `${projectId}:initial-launch`,
|
|
436
|
+
projectId,
|
|
437
|
+
title: "Initial launch",
|
|
438
|
+
summary: "Managed launch scaffolded the repo, seeded Direct, and prepared the first operating branch.",
|
|
439
|
+
state: "saved_remote",
|
|
440
|
+
branchName: "task/initial-launch",
|
|
441
|
+
branchRef: "refs/heads/task/initial-launch",
|
|
442
|
+
owner: "Knowledge Coop",
|
|
443
|
+
linkedItems: [
|
|
444
|
+
{ model: "objective", id: seed.objectiveId },
|
|
445
|
+
{ model: "question", id: seed.questionId },
|
|
446
|
+
{ model: "note", id: seed.noteSlug }
|
|
447
|
+
],
|
|
448
|
+
verificationStatus: null,
|
|
449
|
+
verificationSummary: null,
|
|
450
|
+
lastSaveAt: nowIso(),
|
|
451
|
+
lastStageAt: null,
|
|
452
|
+
archivedAt: null,
|
|
453
|
+
createdAt: nowIso(),
|
|
454
|
+
updatedAt: nowIso(),
|
|
455
|
+
metadata: {
|
|
456
|
+
launchedBy: "knowledge_coop_market"
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function pushDefaultWorkstreamBranch(projectRoot) {
|
|
461
|
+
runGit(projectRoot, ["checkout", "-B", "task/initial-launch"], false);
|
|
462
|
+
runGit(projectRoot, ["push", "-u", "origin", "task/initial-launch"], false);
|
|
463
|
+
runGit(projectRoot, ["checkout", "main"], false);
|
|
464
|
+
}
|
|
465
|
+
function loadProjectMetadata(projectId, input, seed, workstream, siteUrl, projectApiBaseUrl, repository) {
|
|
466
|
+
return {
|
|
467
|
+
publicSite: input.publicSite !== false,
|
|
468
|
+
sourceKind: input.sourceKind,
|
|
469
|
+
sourceRef: input.sourceRef ?? null,
|
|
470
|
+
enableDefaultAgents: input.enableDefaultAgents !== false,
|
|
471
|
+
objectiveCount: 1,
|
|
472
|
+
questionCount: 1,
|
|
473
|
+
noteCount: 1,
|
|
474
|
+
proposalCount: 1,
|
|
475
|
+
decisionCount: 1,
|
|
476
|
+
directViews: ["Now", "Blocked", "Ready for research", "Ready for build", "Release-linked"],
|
|
477
|
+
directItems: [
|
|
478
|
+
{
|
|
479
|
+
model: "objective",
|
|
480
|
+
id: seed.objectiveId,
|
|
481
|
+
title: `Launch ${input.projectName}`,
|
|
482
|
+
status: "live",
|
|
483
|
+
updatedAt: nowIso(),
|
|
484
|
+
linkedWorkstreamIds: [workstream.id],
|
|
485
|
+
linkedReleaseIds: []
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
model: "question",
|
|
489
|
+
id: seed.questionId,
|
|
490
|
+
title: "What Should The First Release Cover?",
|
|
491
|
+
status: "live",
|
|
492
|
+
updatedAt: nowIso(),
|
|
493
|
+
linkedWorkstreamIds: [workstream.id],
|
|
494
|
+
linkedReleaseIds: []
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
model: "note",
|
|
498
|
+
id: seed.noteSlug,
|
|
499
|
+
title: `${input.projectName} Operating Model`,
|
|
500
|
+
status: "live",
|
|
501
|
+
updatedAt: nowIso(),
|
|
502
|
+
linkedWorkstreamIds: [workstream.id],
|
|
503
|
+
linkedReleaseIds: []
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
model: "proposal",
|
|
507
|
+
id: seed.proposalId,
|
|
508
|
+
title: "Establish The Initial Operating Routine",
|
|
509
|
+
status: "live",
|
|
510
|
+
updatedAt: nowIso(),
|
|
511
|
+
linkedWorkstreamIds: [workstream.id],
|
|
512
|
+
linkedReleaseIds: []
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
model: "decision",
|
|
516
|
+
id: seed.decisionId,
|
|
517
|
+
title: "Adopt The Initial Launch Posture",
|
|
518
|
+
status: "live",
|
|
519
|
+
updatedAt: nowIso(),
|
|
520
|
+
linkedWorkstreamIds: [workstream.id],
|
|
521
|
+
linkedReleaseIds: []
|
|
522
|
+
}
|
|
523
|
+
],
|
|
524
|
+
workstreams: [workstream],
|
|
525
|
+
siteUrl,
|
|
526
|
+
projectApiBaseUrl,
|
|
527
|
+
repository,
|
|
528
|
+
launchPhase: "completed",
|
|
529
|
+
lastSuccessfulPhase: "runtime_connection"
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
function commandAvailable(command) {
|
|
533
|
+
return spawnSync("bash", ["-lc", `command -v ${command}`], { stdio: "ignore" }).status === 0;
|
|
534
|
+
}
|
|
535
|
+
function appendPhase(phases, phase, status, detail) {
|
|
536
|
+
phases.push({
|
|
537
|
+
phase,
|
|
538
|
+
status,
|
|
539
|
+
detail,
|
|
540
|
+
timestamp: nowIso()
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
function scaffoldKnowledgeCoopSource(projectRoot, input) {
|
|
544
|
+
const templateId = input.sourceKind === "template" ? slugify(input.sourceRef ?? "starter-basic", "starter-basic") : "starter-basic";
|
|
545
|
+
const templateCatalogEnv = { TREESEED_TEMPLATE_CATALOG_URL: currentTemplateCatalogUrl() };
|
|
546
|
+
if (input.sourceKind === "knowledge_pack") {
|
|
547
|
+
return scaffoldTemplateProject("starter-basic", projectRoot, {
|
|
548
|
+
target: input.projectSlug,
|
|
549
|
+
name: input.projectName,
|
|
550
|
+
slug: input.projectSlug,
|
|
551
|
+
siteUrl: resolveManagedWebUrl(slugify(input.projectSlug, "project")),
|
|
552
|
+
contactEmail: input.contactEmail ?? `hello+${slugify(input.projectSlug, "project")}@knowledge.coop`
|
|
553
|
+
}, {
|
|
554
|
+
cwd: projectRoot,
|
|
555
|
+
env: templateCatalogEnv
|
|
556
|
+
}).then(() => {
|
|
557
|
+
if (!input.sourceRef) {
|
|
558
|
+
throw new Error("Knowledge pack launch requires sourceRef to point to a package manifest or directory.");
|
|
559
|
+
}
|
|
560
|
+
return importKnowledgeCoopKnowledgePack(projectRoot, input.sourceRef);
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
return scaffoldTemplateProject(templateId, projectRoot, {
|
|
564
|
+
target: input.projectSlug,
|
|
565
|
+
name: input.projectName,
|
|
566
|
+
slug: input.projectSlug,
|
|
567
|
+
siteUrl: resolveManagedWebUrl(slugify(input.projectSlug, "project")),
|
|
568
|
+
contactEmail: input.contactEmail ?? `hello+${slugify(input.projectSlug, "project")}@knowledge.coop`,
|
|
569
|
+
repositoryUrl: `https://github.com/${slugify(input.repoOwner ?? resolveDefaultGitHubOwner(), "treeseed-ai")}/${slugify(input.projectSlug, "project")}`
|
|
570
|
+
}, {
|
|
571
|
+
cwd: projectRoot,
|
|
572
|
+
env: templateCatalogEnv
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
function validateKnowledgeCoopManagedLaunchPrerequisites(tenantRoot = process.cwd()) {
|
|
576
|
+
const values = collectTreeseedConfigSeedValues(tenantRoot, "prod", process.env);
|
|
577
|
+
const requiredConfig = [
|
|
578
|
+
["TREESEED_BETTER_AUTH_SECRET"],
|
|
579
|
+
["TREESEED_AGENT_POOL_MIN_WORKERS"],
|
|
580
|
+
["TREESEED_AGENT_POOL_MAX_WORKERS"],
|
|
581
|
+
["TREESEED_AGENT_POOL_TARGET_QUEUE_DEPTH"],
|
|
582
|
+
["TREESEED_AGENT_POOL_COOLDOWN_SECONDS"],
|
|
583
|
+
["TREESEED_API_WEB_SERVICE_ID"],
|
|
584
|
+
["TREESEED_API_WEB_SERVICE_SECRET"],
|
|
585
|
+
["TREESEED_API_WEB_ASSERTION_SECRET"],
|
|
586
|
+
["CLOUDFLARE_ACCOUNT_ID", "TREESEED_CLOUDFLARE_ACCOUNT_ID"]
|
|
587
|
+
];
|
|
588
|
+
const missingConfig = requiredConfig.filter((group) => !group.some((name) => {
|
|
589
|
+
const value = values[name];
|
|
590
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
591
|
+
})).map((group) => group.join(" or "));
|
|
592
|
+
const providerChecks = checkTreeseedProviderConnections({ tenantRoot, scope: "prod", env: process.env });
|
|
593
|
+
const commands = {
|
|
594
|
+
git: commandAvailable("git"),
|
|
595
|
+
gh: commandAvailable("gh"),
|
|
596
|
+
wrangler: commandAvailable("wrangler"),
|
|
597
|
+
railway: commandAvailable("railway")
|
|
598
|
+
};
|
|
599
|
+
const ok = missingConfig.length === 0 && providerChecks.ok === true && Object.values(commands).every(Boolean);
|
|
600
|
+
return {
|
|
601
|
+
ok,
|
|
602
|
+
missingConfig,
|
|
603
|
+
providerChecks,
|
|
604
|
+
commands
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
async function executeKnowledgeCoopManagedLaunch(input) {
|
|
608
|
+
const phases = [];
|
|
609
|
+
const preflight = validateKnowledgeCoopManagedLaunchPrerequisites(process.cwd());
|
|
610
|
+
if (!preflight.ok) {
|
|
611
|
+
throw new KnowledgeCoopLaunchError(
|
|
612
|
+
"runtime_connection_failed",
|
|
613
|
+
`Knowledge Coop launch preflight failed: ${[...preflight.missingConfig, ...preflight.providerChecks.issues].join("; ") || "provider checks failed."}`,
|
|
614
|
+
[]
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
const workingRoot = mkdtempSync(join(tmpdir(), `knowledge-coop-launch-${slugify(input.projectSlug, "project")}-`));
|
|
618
|
+
const repoOwner = slugify(input.repoOwner ?? resolveDefaultGitHubOwner(), "treeseed-ai");
|
|
619
|
+
const repoName = slugify(input.projectSlug, "project");
|
|
620
|
+
try {
|
|
621
|
+
appendPhase(phases, "repo_provision", "running", "Creating GitHub repository.");
|
|
622
|
+
const repository = createGitHubRepository({
|
|
623
|
+
owner: repoOwner,
|
|
624
|
+
name: repoName,
|
|
625
|
+
description: input.summary ?? `Knowledge Coop hub for ${input.projectName}`,
|
|
626
|
+
visibility: input.repoVisibility ?? "private",
|
|
627
|
+
homepageUrl: resolveManagedWebUrl(repoName),
|
|
628
|
+
topics: ["knowledge-coop", "treeseed", "knowledge-hub"]
|
|
629
|
+
});
|
|
630
|
+
appendPhase(phases, "repo_provision", "completed", `Created ${repository.slug}.`);
|
|
631
|
+
appendPhase(phases, "content_bootstrap", "running", "Scaffolding the project and seeding initial content.");
|
|
632
|
+
await scaffoldKnowledgeCoopSource(workingRoot, input);
|
|
633
|
+
ensureHostedProjectFiles(workingRoot);
|
|
634
|
+
const managedDefaults = applyManagedProjectDefaults(workingRoot, input);
|
|
635
|
+
const seed = seedKnowledgeCoopContent(workingRoot, input);
|
|
636
|
+
appendPhase(phases, "content_bootstrap", "completed", "Scaffolded the repo and seeded Direct content.");
|
|
637
|
+
appendPhase(phases, "workflow_bootstrap", "running", "Initializing git branches and GitHub workflows.");
|
|
638
|
+
const initResult = initializeGitHubRepositoryWorkingTree(workingRoot, repository, {
|
|
639
|
+
defaultBranch: "main",
|
|
640
|
+
createStaging: true,
|
|
641
|
+
commitMessage: `Initialize ${input.projectName}`
|
|
642
|
+
});
|
|
643
|
+
pushDefaultWorkstreamBranch(workingRoot);
|
|
644
|
+
const workflows = ensureGitHubDeployAutomation(workingRoot);
|
|
645
|
+
appendPhase(phases, "workflow_bootstrap", "completed", "Configured GitHub workflows, secrets, and variables.");
|
|
646
|
+
appendPhase(phases, "hosting_registration", "running", "Provisioning Cloudflare resources and deploy state.");
|
|
647
|
+
const staging = provisionCloudflareResources(workingRoot, { scope: "staging" });
|
|
648
|
+
const prod = provisionCloudflareResources(workingRoot, { scope: "prod" });
|
|
649
|
+
syncCloudflareSecrets(workingRoot, { scope: "prod" });
|
|
650
|
+
runRemoteD1Migrations(workingRoot, { scope: "prod" });
|
|
651
|
+
markDeploymentInitialized(workingRoot, { scope: "staging" });
|
|
652
|
+
const verification = verifyProvisionedCloudflareResources(workingRoot, { scope: "prod" });
|
|
653
|
+
appendPhase(phases, "hosting_registration", "completed", "Provisioned Cloudflare resources.");
|
|
654
|
+
const launchConfig = loadCliDeployConfig(workingRoot);
|
|
655
|
+
const managedRuntime = launchConfig.runtime?.mode === "treeseed_managed";
|
|
656
|
+
let services = [];
|
|
657
|
+
let deployments = [];
|
|
658
|
+
let schedules = [];
|
|
659
|
+
let railwayVerification = [];
|
|
660
|
+
if (managedRuntime) {
|
|
661
|
+
appendPhase(phases, "runtime_connection", "running", "Deploying Railway services and registering runtime connectivity.");
|
|
662
|
+
validateRailwayDeployPrerequisites(workingRoot, "prod");
|
|
663
|
+
services = configuredRailwayServices(workingRoot, "prod");
|
|
664
|
+
deployments = services.map((service) => deployRailwayService(workingRoot, service));
|
|
665
|
+
schedules = await ensureRailwayScheduledJobs(workingRoot, "prod");
|
|
666
|
+
railwayVerification = await verifyRailwayScheduledJobs(workingRoot, "prod");
|
|
667
|
+
finalizeDeploymentState(workingRoot, { scope: "prod", serviceResults: deployments });
|
|
668
|
+
appendPhase(phases, "runtime_connection", "completed", "Deployed Railway services and recorded runtime readiness.");
|
|
669
|
+
} else {
|
|
670
|
+
appendPhase(phases, "runtime_connection", "completed", "Skipped managed runtime deployment for hub-only or BYO runtime launch.");
|
|
671
|
+
}
|
|
672
|
+
const defaultWorkstream = createDefaultWorkstream(input.projectId, input, seed);
|
|
673
|
+
const projectMetadata = loadProjectMetadata(
|
|
674
|
+
input.projectId,
|
|
675
|
+
input,
|
|
676
|
+
seed,
|
|
677
|
+
defaultWorkstream,
|
|
678
|
+
managedDefaults.siteUrl,
|
|
679
|
+
managedDefaults.projectApiBaseUrl,
|
|
680
|
+
{ slug: repository.slug, url: repository.url }
|
|
681
|
+
);
|
|
682
|
+
const templatePackage = buildKnowledgeCoopTemplatePackage(workingRoot, {
|
|
683
|
+
projectSlug: input.projectSlug,
|
|
684
|
+
title: `${input.projectName} template`,
|
|
685
|
+
summary: input.summary ?? null,
|
|
686
|
+
market: {
|
|
687
|
+
publisherId: input.teamId,
|
|
688
|
+
publisherName: input.teamSlug ?? input.teamId,
|
|
689
|
+
publishMetadata: {
|
|
690
|
+
sourceProjectId: input.projectId,
|
|
691
|
+
sourceKind: input.sourceKind
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
const knowledgePackPackage = buildKnowledgeCoopKnowledgePackPackage(workingRoot, {
|
|
696
|
+
projectSlug: input.projectSlug,
|
|
697
|
+
title: `${input.projectName} knowledge pack`,
|
|
698
|
+
summary: input.summary ?? null,
|
|
699
|
+
market: {
|
|
700
|
+
publisherId: input.teamId,
|
|
701
|
+
publisherName: input.teamSlug ?? input.teamId,
|
|
702
|
+
publishMetadata: {
|
|
703
|
+
sourceProjectId: input.projectId,
|
|
704
|
+
sourceKind: input.sourceKind
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
return {
|
|
709
|
+
workingRoot,
|
|
710
|
+
repository: {
|
|
711
|
+
slug: repository.slug,
|
|
712
|
+
owner: repository.owner,
|
|
713
|
+
name: repository.name,
|
|
714
|
+
url: repository.url,
|
|
715
|
+
defaultBranch: initResult.defaultBranch,
|
|
716
|
+
stagingBranch: initResult.stagingBranch,
|
|
717
|
+
visibility: repository.visibility
|
|
718
|
+
},
|
|
719
|
+
workflows,
|
|
720
|
+
cloudflare: {
|
|
721
|
+
staging,
|
|
722
|
+
prod,
|
|
723
|
+
verification
|
|
724
|
+
},
|
|
725
|
+
railway: {
|
|
726
|
+
services,
|
|
727
|
+
deployments,
|
|
728
|
+
schedules,
|
|
729
|
+
verification: railwayVerification
|
|
730
|
+
},
|
|
731
|
+
projectApiBaseUrl: managedDefaults.projectApiBaseUrl,
|
|
732
|
+
projectSiteUrl: managedDefaults.siteUrl,
|
|
733
|
+
projectMetadata,
|
|
734
|
+
defaultWorkstream,
|
|
735
|
+
phases,
|
|
736
|
+
templatePackage,
|
|
737
|
+
knowledgePackPackage
|
|
738
|
+
};
|
|
739
|
+
} catch (error) {
|
|
740
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
741
|
+
const phase = error instanceof KnowledgeCoopLaunchError ? error.phase : phases.some((entry) => entry.phase === "runtime_connection" && entry.status === "running") ? "runtime_connection_failed" : phases.some((entry) => entry.phase === "hosting_registration" && entry.status === "running") ? "hosting_registration_failed" : phases.some((entry) => entry.phase === "workflow_bootstrap" && entry.status === "running") ? "workflow_bootstrap_failed" : phases.some((entry) => entry.phase === "content_bootstrap" && entry.status === "running") ? "content_bootstrap_failed" : "repo_provision_failed";
|
|
742
|
+
appendPhase(phases, phase.replace(/_failed$/u, ""), "failed", message);
|
|
743
|
+
throw new KnowledgeCoopLaunchError(phase, message, phases);
|
|
744
|
+
} finally {
|
|
745
|
+
if (input.preserveWorkingTree === false) {
|
|
746
|
+
rmSync(workingRoot, { recursive: true, force: true });
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
export {
|
|
751
|
+
executeKnowledgeCoopManagedLaunch,
|
|
752
|
+
validateKnowledgeCoopManagedLaunchPrerequisites
|
|
753
|
+
};
|