@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,223 @@
|
|
|
1
|
+
import type { ProjectConnection, RemoteJobStatus } from './sdk-types.ts';
|
|
2
|
+
export declare const KNOWLEDGE_COOP_TEAM_CAPABILITIES: readonly ["launch_projects", "edit_direct", "manage_workstreams", "stage_releases", "publish_releases", "publish_market_listings", "manage_products", "manage_billing", "approve_remote_execution"];
|
|
3
|
+
export declare const KNOWLEDGE_COOP_JOB_STATUSES: readonly ["queued", "running", "waiting_for_approval", "failed", "completed", "rolled_back", "cancelled"];
|
|
4
|
+
export declare const KNOWLEDGE_COOP_WORKSTREAM_STATES: readonly ["drafting", "active_local", "verifying", "saved_remote", "in_staging", "archived"];
|
|
5
|
+
export declare const KNOWLEDGE_COOP_RELEASE_STATES: readonly ["drafting", "waiting_on_verification", "ready_to_publish", "published", "rolled_back"];
|
|
6
|
+
export declare const KNOWLEDGE_COOP_SHARE_PACKAGE_STATES: readonly ["draft", "packaged", "ready_to_publish", "published", "archived", "failed"];
|
|
7
|
+
export declare const KNOWLEDGE_COOP_AGENT_MESSAGE_KINDS: readonly ["informational", "warning", "action_requested", "release_readiness"];
|
|
8
|
+
export type TeamCapability = (typeof KNOWLEDGE_COOP_TEAM_CAPABILITIES)[number];
|
|
9
|
+
export type KnowledgeCoopJobStatus = (typeof KNOWLEDGE_COOP_JOB_STATUSES)[number];
|
|
10
|
+
export type WorkstreamState = (typeof KNOWLEDGE_COOP_WORKSTREAM_STATES)[number];
|
|
11
|
+
export type ReleaseState = (typeof KNOWLEDGE_COOP_RELEASE_STATES)[number];
|
|
12
|
+
export type SharePackageState = (typeof KNOWLEDGE_COOP_SHARE_PACKAGE_STATES)[number];
|
|
13
|
+
export type AgentMessageKind = (typeof KNOWLEDGE_COOP_AGENT_MESSAGE_KINDS)[number];
|
|
14
|
+
export interface LinkedProjectRecordRef {
|
|
15
|
+
model: 'objective' | 'question' | 'note' | 'proposal' | 'decision';
|
|
16
|
+
id: string;
|
|
17
|
+
}
|
|
18
|
+
export interface DirectBoardItemSummary {
|
|
19
|
+
model: 'objective' | 'question' | 'note' | 'proposal' | 'decision';
|
|
20
|
+
id: string;
|
|
21
|
+
title: string;
|
|
22
|
+
status: string | null;
|
|
23
|
+
updatedAt: string | null;
|
|
24
|
+
linkedWorkstreamIds: string[];
|
|
25
|
+
linkedReleaseIds: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface WorkstreamEvent {
|
|
28
|
+
id: string;
|
|
29
|
+
workstreamId: string;
|
|
30
|
+
projectId: string;
|
|
31
|
+
kind: string;
|
|
32
|
+
summary: string | null;
|
|
33
|
+
data: Record<string, unknown>;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
}
|
|
36
|
+
export interface WorkstreamSummary {
|
|
37
|
+
id: string;
|
|
38
|
+
projectId: string;
|
|
39
|
+
title: string;
|
|
40
|
+
summary: string | null;
|
|
41
|
+
state: WorkstreamState;
|
|
42
|
+
branchName: string | null;
|
|
43
|
+
branchRef: string | null;
|
|
44
|
+
owner: string | null;
|
|
45
|
+
linkedItems: LinkedProjectRecordRef[];
|
|
46
|
+
verificationStatus: 'completed' | 'failed' | 'waiting' | null;
|
|
47
|
+
verificationSummary: string | null;
|
|
48
|
+
lastSaveAt: string | null;
|
|
49
|
+
lastStageAt: string | null;
|
|
50
|
+
archivedAt: string | null;
|
|
51
|
+
createdAt: string;
|
|
52
|
+
updatedAt: string;
|
|
53
|
+
metadata?: Record<string, unknown>;
|
|
54
|
+
}
|
|
55
|
+
export interface WorkstreamDetail extends WorkstreamSummary {
|
|
56
|
+
events: WorkstreamEvent[];
|
|
57
|
+
}
|
|
58
|
+
export interface ReleaseSummary {
|
|
59
|
+
id: string;
|
|
60
|
+
projectId: string;
|
|
61
|
+
version: string;
|
|
62
|
+
title: string | null;
|
|
63
|
+
state: ReleaseState;
|
|
64
|
+
summary: string | null;
|
|
65
|
+
workstreamIds: string[];
|
|
66
|
+
releaseTag: string | null;
|
|
67
|
+
commitSha: string | null;
|
|
68
|
+
publishedAt: string | null;
|
|
69
|
+
rolledBackAt: string | null;
|
|
70
|
+
createdAt: string;
|
|
71
|
+
updatedAt: string;
|
|
72
|
+
metadata?: Record<string, unknown>;
|
|
73
|
+
}
|
|
74
|
+
export interface ReleaseDetail extends ReleaseSummary {
|
|
75
|
+
items: Array<{
|
|
76
|
+
id: string;
|
|
77
|
+
workstreamId: string | null;
|
|
78
|
+
model: string | null;
|
|
79
|
+
recordId: string | null;
|
|
80
|
+
summary: string | null;
|
|
81
|
+
metadata?: Record<string, unknown>;
|
|
82
|
+
createdAt: string;
|
|
83
|
+
}>;
|
|
84
|
+
}
|
|
85
|
+
export interface SharePackageStatus {
|
|
86
|
+
id: string;
|
|
87
|
+
projectId: string;
|
|
88
|
+
kind: 'export' | 'template' | 'knowledge_pack' | 'market_listing';
|
|
89
|
+
state: SharePackageState;
|
|
90
|
+
title: string;
|
|
91
|
+
summary: string | null;
|
|
92
|
+
version: string | null;
|
|
93
|
+
outputPath: string | null;
|
|
94
|
+
artifactKey: string | null;
|
|
95
|
+
manifestKey: string | null;
|
|
96
|
+
publishedItemId: string | null;
|
|
97
|
+
lastError: string | null;
|
|
98
|
+
createdAt: string;
|
|
99
|
+
updatedAt: string;
|
|
100
|
+
metadata?: Record<string, unknown>;
|
|
101
|
+
}
|
|
102
|
+
export interface AgentStatusRecord {
|
|
103
|
+
agentSlug: string;
|
|
104
|
+
handler: string;
|
|
105
|
+
status: 'active' | 'idle' | 'failed' | 'waiting';
|
|
106
|
+
currentTask: string | null;
|
|
107
|
+
workstreamId: string | null;
|
|
108
|
+
lastMessage: string | null;
|
|
109
|
+
lastRunAt: string | null;
|
|
110
|
+
}
|
|
111
|
+
export interface AgentMessageRecord {
|
|
112
|
+
id: string;
|
|
113
|
+
agentSlug: string;
|
|
114
|
+
kind: AgentMessageKind;
|
|
115
|
+
type: string;
|
|
116
|
+
status: string;
|
|
117
|
+
summary: string;
|
|
118
|
+
workstreamId: string | null;
|
|
119
|
+
releaseId: string | null;
|
|
120
|
+
createdAt: string;
|
|
121
|
+
metadata?: Record<string, unknown>;
|
|
122
|
+
}
|
|
123
|
+
export interface ProjectConnectionStatus {
|
|
124
|
+
projectId: string;
|
|
125
|
+
connection: ProjectConnection | null;
|
|
126
|
+
connected: boolean;
|
|
127
|
+
hubMode?: 'treeseed_hosted' | 'customer_hosted' | null;
|
|
128
|
+
runtimeMode?: 'none' | 'byo_attached' | 'treeseed_managed' | null;
|
|
129
|
+
runtimeRegistration?: 'optional' | 'required' | 'none' | null;
|
|
130
|
+
runtimeAttached?: boolean;
|
|
131
|
+
runtimeReady?: boolean;
|
|
132
|
+
runnerReady: boolean;
|
|
133
|
+
projectApiReady: boolean;
|
|
134
|
+
mode: ProjectConnection['mode'] | 'disconnected';
|
|
135
|
+
}
|
|
136
|
+
export interface ProjectOverviewSummary {
|
|
137
|
+
projectId: string;
|
|
138
|
+
teamId: string;
|
|
139
|
+
health: {
|
|
140
|
+
state: string;
|
|
141
|
+
label: string;
|
|
142
|
+
reason: string;
|
|
143
|
+
};
|
|
144
|
+
counts: {
|
|
145
|
+
objectives: number;
|
|
146
|
+
questions: number;
|
|
147
|
+
notes: number;
|
|
148
|
+
proposals: number;
|
|
149
|
+
decisions: number;
|
|
150
|
+
activeWorkstreams: number;
|
|
151
|
+
agents: number;
|
|
152
|
+
releases: number;
|
|
153
|
+
};
|
|
154
|
+
connection: ProjectConnectionStatus;
|
|
155
|
+
nextBestAction: string;
|
|
156
|
+
recentActivity: Array<{
|
|
157
|
+
kind: string;
|
|
158
|
+
id: string;
|
|
159
|
+
title: string;
|
|
160
|
+
status: string | null;
|
|
161
|
+
timestamp: string | null;
|
|
162
|
+
summary: string | null;
|
|
163
|
+
metadata?: Record<string, unknown>;
|
|
164
|
+
}>;
|
|
165
|
+
}
|
|
166
|
+
export interface TeamHomeSummary {
|
|
167
|
+
teamId: string;
|
|
168
|
+
projects: ProjectOverviewSummary[];
|
|
169
|
+
inboxCount: number;
|
|
170
|
+
productsCount: number;
|
|
171
|
+
}
|
|
172
|
+
export interface TeamMemberSummary {
|
|
173
|
+
id: string;
|
|
174
|
+
teamId: string;
|
|
175
|
+
userId: string;
|
|
176
|
+
status: string;
|
|
177
|
+
displayName: string | null;
|
|
178
|
+
email: string | null;
|
|
179
|
+
roles: string[];
|
|
180
|
+
createdAt: string;
|
|
181
|
+
updatedAt: string;
|
|
182
|
+
}
|
|
183
|
+
export interface InboxItem {
|
|
184
|
+
id: string;
|
|
185
|
+
teamId: string;
|
|
186
|
+
projectId: string | null;
|
|
187
|
+
kind: string;
|
|
188
|
+
state: KnowledgeCoopJobStatus | string;
|
|
189
|
+
title: string;
|
|
190
|
+
summary: string | null;
|
|
191
|
+
href: string | null;
|
|
192
|
+
metadata?: Record<string, unknown>;
|
|
193
|
+
createdAt: string;
|
|
194
|
+
updatedAt: string;
|
|
195
|
+
}
|
|
196
|
+
export interface LaunchProjectRequest {
|
|
197
|
+
teamId: string;
|
|
198
|
+
name: string;
|
|
199
|
+
slug: string;
|
|
200
|
+
summary?: string | null;
|
|
201
|
+
sourceKind: 'blank' | 'template' | 'knowledge_pack';
|
|
202
|
+
sourceRef?: string | null;
|
|
203
|
+
hostingMode: 'managed' | 'hybrid' | 'self_hosted';
|
|
204
|
+
publicSite?: boolean;
|
|
205
|
+
repoProvider?: 'github';
|
|
206
|
+
repoVisibility?: 'private' | 'public';
|
|
207
|
+
enableDefaultAgents?: boolean;
|
|
208
|
+
initialObjectives?: string[];
|
|
209
|
+
}
|
|
210
|
+
export interface LaunchProjectResult {
|
|
211
|
+
project: {
|
|
212
|
+
id: string;
|
|
213
|
+
teamId: string;
|
|
214
|
+
slug: string;
|
|
215
|
+
name: string;
|
|
216
|
+
description: string | null;
|
|
217
|
+
};
|
|
218
|
+
connection: ProjectConnection | null;
|
|
219
|
+
launchJobId: string | null;
|
|
220
|
+
overview: ProjectOverviewSummary | null;
|
|
221
|
+
}
|
|
222
|
+
export declare function normalizeKnowledgeCoopJobStatus(status: string | null | undefined): KnowledgeCoopJobStatus;
|
|
223
|
+
export declare function normalizeRemoteJobStatus(status: RemoteJobStatus): KnowledgeCoopJobStatus;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const KNOWLEDGE_COOP_TEAM_CAPABILITIES = [
|
|
2
|
+
"launch_projects",
|
|
3
|
+
"edit_direct",
|
|
4
|
+
"manage_workstreams",
|
|
5
|
+
"stage_releases",
|
|
6
|
+
"publish_releases",
|
|
7
|
+
"publish_market_listings",
|
|
8
|
+
"manage_products",
|
|
9
|
+
"manage_billing",
|
|
10
|
+
"approve_remote_execution"
|
|
11
|
+
];
|
|
12
|
+
const KNOWLEDGE_COOP_JOB_STATUSES = [
|
|
13
|
+
"queued",
|
|
14
|
+
"running",
|
|
15
|
+
"waiting_for_approval",
|
|
16
|
+
"failed",
|
|
17
|
+
"completed",
|
|
18
|
+
"rolled_back",
|
|
19
|
+
"cancelled"
|
|
20
|
+
];
|
|
21
|
+
const KNOWLEDGE_COOP_WORKSTREAM_STATES = [
|
|
22
|
+
"drafting",
|
|
23
|
+
"active_local",
|
|
24
|
+
"verifying",
|
|
25
|
+
"saved_remote",
|
|
26
|
+
"in_staging",
|
|
27
|
+
"archived"
|
|
28
|
+
];
|
|
29
|
+
const KNOWLEDGE_COOP_RELEASE_STATES = [
|
|
30
|
+
"drafting",
|
|
31
|
+
"waiting_on_verification",
|
|
32
|
+
"ready_to_publish",
|
|
33
|
+
"published",
|
|
34
|
+
"rolled_back"
|
|
35
|
+
];
|
|
36
|
+
const KNOWLEDGE_COOP_SHARE_PACKAGE_STATES = [
|
|
37
|
+
"draft",
|
|
38
|
+
"packaged",
|
|
39
|
+
"ready_to_publish",
|
|
40
|
+
"published",
|
|
41
|
+
"archived",
|
|
42
|
+
"failed"
|
|
43
|
+
];
|
|
44
|
+
const KNOWLEDGE_COOP_AGENT_MESSAGE_KINDS = [
|
|
45
|
+
"informational",
|
|
46
|
+
"warning",
|
|
47
|
+
"action_requested",
|
|
48
|
+
"release_readiness"
|
|
49
|
+
];
|
|
50
|
+
function normalizeKnowledgeCoopJobStatus(status) {
|
|
51
|
+
switch (String(status ?? "").trim()) {
|
|
52
|
+
case "running":
|
|
53
|
+
return "running";
|
|
54
|
+
case "waiting_for_approval":
|
|
55
|
+
return "waiting_for_approval";
|
|
56
|
+
case "failed":
|
|
57
|
+
return "failed";
|
|
58
|
+
case "completed":
|
|
59
|
+
return "completed";
|
|
60
|
+
case "rolled_back":
|
|
61
|
+
return "rolled_back";
|
|
62
|
+
case "cancelled":
|
|
63
|
+
return "cancelled";
|
|
64
|
+
case "claimed":
|
|
65
|
+
case "pending":
|
|
66
|
+
default:
|
|
67
|
+
return "queued";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function normalizeRemoteJobStatus(status) {
|
|
71
|
+
return normalizeKnowledgeCoopJobStatus(status);
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
KNOWLEDGE_COOP_AGENT_MESSAGE_KINDS,
|
|
75
|
+
KNOWLEDGE_COOP_JOB_STATUSES,
|
|
76
|
+
KNOWLEDGE_COOP_RELEASE_STATES,
|
|
77
|
+
KNOWLEDGE_COOP_SHARE_PACKAGE_STATES,
|
|
78
|
+
KNOWLEDGE_COOP_TEAM_CAPABILITIES,
|
|
79
|
+
KNOWLEDGE_COOP_WORKSTREAM_STATES,
|
|
80
|
+
normalizeKnowledgeCoopJobStatus,
|
|
81
|
+
normalizeRemoteJobStatus
|
|
82
|
+
};
|
package/dist/model-registry.js
CHANGED
|
@@ -107,6 +107,85 @@ function buildBuiltinModelRegistry(repoRoot) {
|
|
|
107
107
|
contentCollection: "questions",
|
|
108
108
|
contentDir: path.join(root, "questions")
|
|
109
109
|
},
|
|
110
|
+
proposal: {
|
|
111
|
+
name: "proposal",
|
|
112
|
+
aliases: ["proposals"],
|
|
113
|
+
storage: "content",
|
|
114
|
+
operations: ["get", "read", "search", "follow", "pick", "create", "update"],
|
|
115
|
+
graph: graph({
|
|
116
|
+
entityType: "Proposal",
|
|
117
|
+
titleField: "title",
|
|
118
|
+
tagField: "tags",
|
|
119
|
+
enableSections: true,
|
|
120
|
+
referenceFields: [
|
|
121
|
+
{ field: "related_objectives", edgeType: "REFERENCES", targetModels: ["objective"], multiple: true },
|
|
122
|
+
{ field: "related_questions", edgeType: "REFERENCES", targetModels: ["question"], multiple: true },
|
|
123
|
+
{ field: "related_notes", edgeType: "REFERENCES", targetModels: ["note"], multiple: true },
|
|
124
|
+
{ field: "related_books", edgeType: "REFERENCES", targetModels: ["book"], multiple: true },
|
|
125
|
+
{ field: "decision", edgeType: "REFERENCES", targetModels: ["decision"] },
|
|
126
|
+
{ field: "supersedes", edgeType: "SUPERSEDES", targetModels: ["proposal"], multiple: true },
|
|
127
|
+
{ field: "primary_contributor", edgeType: "REFERENCES", targetModels: ["person", "agent"] }
|
|
128
|
+
]
|
|
129
|
+
}),
|
|
130
|
+
fields: {
|
|
131
|
+
title: field("title", { filterable: true, sortable: true, contentKeys: ["title"], writeContentKey: "title" }),
|
|
132
|
+
status: field("status", { filterable: true, contentKeys: ["status"], writeContentKey: "status" }),
|
|
133
|
+
tags: field("tags", { filterable: true, comparableAs: "string_array", contentKeys: ["tags"], writeContentKey: "tags" }),
|
|
134
|
+
date: field("date", { filterable: true, sortable: true, comparableAs: "date", contentKeys: ["date"], writeContentKey: "date" }),
|
|
135
|
+
proposal_type: field("proposal_type", { aliases: ["proposalType"], filterable: true, contentKeys: ["proposal_type", "proposalType"], writeContentKey: "proposal_type" }),
|
|
136
|
+
related_objectives: field("related_objectives", { aliases: ["relatedObjectives"], filterable: true, comparableAs: "string_array", contentKeys: ["related_objectives", "relatedObjectives"], writeContentKey: "related_objectives" }),
|
|
137
|
+
related_questions: field("related_questions", { aliases: ["relatedQuestions"], filterable: true, comparableAs: "string_array", contentKeys: ["related_questions", "relatedQuestions"], writeContentKey: "related_questions" }),
|
|
138
|
+
related_notes: field("related_notes", { aliases: ["relatedNotes"], filterable: true, comparableAs: "string_array", contentKeys: ["related_notes", "relatedNotes"], writeContentKey: "related_notes" }),
|
|
139
|
+
related_books: field("related_books", { aliases: ["relatedBooks"], filterable: true, comparableAs: "string_array", contentKeys: ["related_books", "relatedBooks"], writeContentKey: "related_books" }),
|
|
140
|
+
decision: field("decision", { filterable: true, contentKeys: ["decision"], writeContentKey: "decision" }),
|
|
141
|
+
updated_at: field("updated_at", { aliases: ["updated", "updatedAt"], sortable: true, comparableAs: "date", contentKeys: ["updated_at", "updated", "updatedAt"], writeContentKey: "updated_at" })
|
|
142
|
+
},
|
|
143
|
+
filterableFields: ["title", "status", "tags", "date", "proposal_type", "related_objectives", "related_questions", "related_notes", "related_books", "decision"],
|
|
144
|
+
sortableFields: ["title", "date", "updated_at"],
|
|
145
|
+
pickField: "date",
|
|
146
|
+
contentCollection: "proposals",
|
|
147
|
+
contentDir: path.join(root, "proposals")
|
|
148
|
+
},
|
|
149
|
+
decision: {
|
|
150
|
+
name: "decision",
|
|
151
|
+
aliases: ["decisions"],
|
|
152
|
+
storage: "content",
|
|
153
|
+
operations: ["get", "read", "search", "follow", "pick", "create", "update"],
|
|
154
|
+
graph: graph({
|
|
155
|
+
entityType: "Decision",
|
|
156
|
+
titleField: "title",
|
|
157
|
+
tagField: "tags",
|
|
158
|
+
enableSections: true,
|
|
159
|
+
referenceFields: [
|
|
160
|
+
{ field: "related_objectives", edgeType: "REFERENCES", targetModels: ["objective"], multiple: true },
|
|
161
|
+
{ field: "related_questions", edgeType: "REFERENCES", targetModels: ["question"], multiple: true },
|
|
162
|
+
{ field: "related_notes", edgeType: "REFERENCES", targetModels: ["note"], multiple: true },
|
|
163
|
+
{ field: "related_proposals", edgeType: "REFERENCES", targetModels: ["proposal"], multiple: true },
|
|
164
|
+
{ field: "related_books", edgeType: "REFERENCES", targetModels: ["book"], multiple: true },
|
|
165
|
+
{ field: "supersedes", edgeType: "SUPERSEDES", targetModels: ["decision"], multiple: true },
|
|
166
|
+
{ field: "primary_contributor", edgeType: "REFERENCES", targetModels: ["person", "agent"] }
|
|
167
|
+
]
|
|
168
|
+
}),
|
|
169
|
+
fields: {
|
|
170
|
+
title: field("title", { filterable: true, sortable: true, contentKeys: ["title"], writeContentKey: "title" }),
|
|
171
|
+
status: field("status", { filterable: true, contentKeys: ["status"], writeContentKey: "status" }),
|
|
172
|
+
tags: field("tags", { filterable: true, comparableAs: "string_array", contentKeys: ["tags"], writeContentKey: "tags" }),
|
|
173
|
+
date: field("date", { filterable: true, sortable: true, comparableAs: "date", contentKeys: ["date"], writeContentKey: "date" }),
|
|
174
|
+
decision_type: field("decision_type", { aliases: ["decisionType"], filterable: true, contentKeys: ["decision_type", "decisionType"], writeContentKey: "decision_type" }),
|
|
175
|
+
authority: field("authority", { filterable: true, contentKeys: ["authority"], writeContentKey: "authority" }),
|
|
176
|
+
related_objectives: field("related_objectives", { aliases: ["relatedObjectives"], filterable: true, comparableAs: "string_array", contentKeys: ["related_objectives", "relatedObjectives"], writeContentKey: "related_objectives" }),
|
|
177
|
+
related_questions: field("related_questions", { aliases: ["relatedQuestions"], filterable: true, comparableAs: "string_array", contentKeys: ["related_questions", "relatedQuestions"], writeContentKey: "related_questions" }),
|
|
178
|
+
related_notes: field("related_notes", { aliases: ["relatedNotes"], filterable: true, comparableAs: "string_array", contentKeys: ["related_notes", "relatedNotes"], writeContentKey: "related_notes" }),
|
|
179
|
+
related_proposals: field("related_proposals", { aliases: ["relatedProposals"], filterable: true, comparableAs: "string_array", contentKeys: ["related_proposals", "relatedProposals"], writeContentKey: "related_proposals" }),
|
|
180
|
+
related_books: field("related_books", { aliases: ["relatedBooks"], filterable: true, comparableAs: "string_array", contentKeys: ["related_books", "relatedBooks"], writeContentKey: "related_books" }),
|
|
181
|
+
updated_at: field("updated_at", { aliases: ["updated", "updatedAt"], sortable: true, comparableAs: "date", contentKeys: ["updated_at", "updated", "updatedAt"], writeContentKey: "updated_at" })
|
|
182
|
+
},
|
|
183
|
+
filterableFields: ["title", "status", "tags", "date", "decision_type", "authority", "related_objectives", "related_questions", "related_notes", "related_proposals", "related_books"],
|
|
184
|
+
sortableFields: ["title", "date", "updated_at"],
|
|
185
|
+
pickField: "date",
|
|
186
|
+
contentCollection: "decisions",
|
|
187
|
+
contentDir: path.join(root, "decisions")
|
|
188
|
+
},
|
|
110
189
|
book: {
|
|
111
190
|
name: "book",
|
|
112
191
|
aliases: ["books"],
|
|
@@ -9,8 +9,17 @@ import {
|
|
|
9
9
|
} from "../../operations-registry.js";
|
|
10
10
|
import {
|
|
11
11
|
clearTreeseedRemoteSession,
|
|
12
|
+
inspectTreeseedKeyAgentStatus,
|
|
13
|
+
lockTreeseedSecretSession,
|
|
14
|
+
migrateTreeseedMachineKeyToWrapped,
|
|
15
|
+
resolveTreeseedLaunchEnvironment,
|
|
12
16
|
resolveTreeseedRemoteConfig,
|
|
13
|
-
|
|
17
|
+
rotateTreeseedMachineKey,
|
|
18
|
+
rotateTreeseedMachineKeyPassphrase,
|
|
19
|
+
setTreeseedRemoteSession,
|
|
20
|
+
TREESEED_MACHINE_KEY_PASSPHRASE_ENV,
|
|
21
|
+
TreeseedKeyAgentError,
|
|
22
|
+
unlockTreeseedSecretSessionFromEnv
|
|
14
23
|
} from "../../operations/services/config-runtime.js";
|
|
15
24
|
import {
|
|
16
25
|
createPersistentDeployTarget,
|
|
@@ -37,6 +46,7 @@ import {
|
|
|
37
46
|
syncTemplateProject,
|
|
38
47
|
validateTemplateProduct
|
|
39
48
|
} from "../../operations/services/template-registry.js";
|
|
49
|
+
import { validateKnowledgeCoopManagedLaunchPrerequisites } from "../../operations/services/knowledge-coop-launch.js";
|
|
40
50
|
import {
|
|
41
51
|
collectCliPreflight,
|
|
42
52
|
formatCliPreflightReport
|
|
@@ -68,11 +78,15 @@ function failureResult(metadata, message, options = {}) {
|
|
|
68
78
|
function contextEnv(context) {
|
|
69
79
|
return { ...process.env, ...context.env ?? {} };
|
|
70
80
|
}
|
|
81
|
+
function operationEnv(context) {
|
|
82
|
+
const tenantConfigPath = resolve(context.cwd, "treeseed.site.yaml");
|
|
83
|
+
return existsSync(tenantConfigPath) ? resolveTreeseedLaunchEnvironment({ tenantRoot: context.cwd, scope: "local", baseEnv: contextEnv(context) }) : contextEnv(context);
|
|
84
|
+
}
|
|
71
85
|
function runNodeScript(metadata, scriptName, args, context) {
|
|
72
86
|
if (context.spawn) {
|
|
73
87
|
const result2 = context.spawn(process.execPath, [packageScriptPath(scriptName), ...args], {
|
|
74
88
|
cwd: context.cwd,
|
|
75
|
-
env:
|
|
89
|
+
env: operationEnv(context),
|
|
76
90
|
stdio: "inherit"
|
|
77
91
|
});
|
|
78
92
|
return operationResult(metadata, {
|
|
@@ -85,7 +99,7 @@ function runNodeScript(metadata, scriptName, args, context) {
|
|
|
85
99
|
}
|
|
86
100
|
const result = spawnSync(process.execPath, [packageScriptPath(scriptName), ...args], {
|
|
87
101
|
cwd: context.cwd,
|
|
88
|
-
env:
|
|
102
|
+
env: operationEnv(context),
|
|
89
103
|
encoding: "utf8",
|
|
90
104
|
stdio: "pipe"
|
|
91
105
|
});
|
|
@@ -198,11 +212,30 @@ class PreflightOperation extends BaseOperation {
|
|
|
198
212
|
cwd: context.cwd,
|
|
199
213
|
requireAuth: input.requireAuth ?? this.requireAuth
|
|
200
214
|
});
|
|
215
|
+
const launch = input.launch === true || input.managedLaunch === true ? validateKnowledgeCoopManagedLaunchPrerequisites(context.cwd) : null;
|
|
201
216
|
const stdout = [formatCliPreflightReport(report)];
|
|
217
|
+
if (launch) {
|
|
218
|
+
stdout.push(
|
|
219
|
+
"",
|
|
220
|
+
"Knowledge Coop managed launch preflight",
|
|
221
|
+
`- ok: ${launch.ok ? "yes" : "no"}`,
|
|
222
|
+
`- commands: git=${launch.commands.git ? "ok" : "missing"}, gh=${launch.commands.gh ? "ok" : "missing"}, wrangler=${launch.commands.wrangler ? "ok" : "missing"}, railway=${launch.commands.railway ? "ok" : "missing"}`
|
|
223
|
+
);
|
|
224
|
+
if (launch.missingConfig.length > 0) {
|
|
225
|
+
stdout.push(...launch.missingConfig.map((item) => `- missing config: ${item}`));
|
|
226
|
+
}
|
|
227
|
+
if (launch.providerChecks.issues.length > 0) {
|
|
228
|
+
stdout.push(...launch.providerChecks.issues.map((item) => `- provider issue: ${item}`));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
202
231
|
for (const line of stdout) context.write?.(line, "stdout");
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
232
|
+
const ok = report.ok && (!launch || launch.ok);
|
|
233
|
+
return operationResult(this.metadata, {
|
|
234
|
+
...report,
|
|
235
|
+
launch
|
|
236
|
+
}, {
|
|
237
|
+
ok,
|
|
238
|
+
exitCode: ok ? 0 : 1,
|
|
206
239
|
stdout,
|
|
207
240
|
stderr: []
|
|
208
241
|
});
|
|
@@ -350,6 +383,87 @@ class AuthWhoAmIOperation extends BaseOperation {
|
|
|
350
383
|
});
|
|
351
384
|
}
|
|
352
385
|
}
|
|
386
|
+
class SecretsStatusOperation extends BaseOperation {
|
|
387
|
+
async execute(_input, context) {
|
|
388
|
+
return operationResult(this.metadata, {
|
|
389
|
+
status: inspectTreeseedKeyAgentStatus(context.cwd)
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
class SecretsUnlockOperation extends BaseOperation {
|
|
394
|
+
async execute(input, context) {
|
|
395
|
+
try {
|
|
396
|
+
const status = unlockTreeseedSecretSessionFromEnv(context.cwd, {
|
|
397
|
+
allowMigration: input.allowMigration !== false,
|
|
398
|
+
createIfMissing: input.createIfMissing !== false
|
|
399
|
+
});
|
|
400
|
+
return operationResult(this.metadata, { status });
|
|
401
|
+
} catch (error) {
|
|
402
|
+
if (error instanceof TreeseedKeyAgentError) {
|
|
403
|
+
return failureResult(this.metadata, error.message, { meta: { code: error.code, details: error.details ?? null } });
|
|
404
|
+
}
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
class SecretsLockOperation extends BaseOperation {
|
|
410
|
+
async execute(_input, context) {
|
|
411
|
+
try {
|
|
412
|
+
return operationResult(this.metadata, {
|
|
413
|
+
status: lockTreeseedSecretSession(context.cwd)
|
|
414
|
+
});
|
|
415
|
+
} catch (error) {
|
|
416
|
+
if (error instanceof TreeseedKeyAgentError) {
|
|
417
|
+
return failureResult(this.metadata, error.message, { meta: { code: error.code, details: error.details ?? null } });
|
|
418
|
+
}
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
class SecretsMigrateKeyOperation extends BaseOperation {
|
|
424
|
+
async execute(input, context) {
|
|
425
|
+
const passphrase = String(input.passphrase ?? context.env?.[TREESEED_MACHINE_KEY_PASSPHRASE_ENV] ?? "").trim();
|
|
426
|
+
if (!passphrase) {
|
|
427
|
+
return failureResult(this.metadata, `Set ${TREESEED_MACHINE_KEY_PASSPHRASE_ENV} or pass { passphrase } when migrating the machine key.`);
|
|
428
|
+
}
|
|
429
|
+
try {
|
|
430
|
+
return operationResult(this.metadata, migrateTreeseedMachineKeyToWrapped(context.cwd, passphrase));
|
|
431
|
+
} catch (error) {
|
|
432
|
+
if (error instanceof TreeseedKeyAgentError) {
|
|
433
|
+
return failureResult(this.metadata, error.message, { meta: { code: error.code, details: error.details ?? null } });
|
|
434
|
+
}
|
|
435
|
+
throw error;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
class SecretsRotatePassphraseOperation extends BaseOperation {
|
|
440
|
+
async execute(input, context) {
|
|
441
|
+
const passphrase = String(input.passphrase ?? context.env?.[TREESEED_MACHINE_KEY_PASSPHRASE_ENV] ?? "").trim();
|
|
442
|
+
if (!passphrase) {
|
|
443
|
+
return failureResult(this.metadata, `Set ${TREESEED_MACHINE_KEY_PASSPHRASE_ENV} or pass { passphrase } when rotating the wrapped-key passphrase.`);
|
|
444
|
+
}
|
|
445
|
+
try {
|
|
446
|
+
return operationResult(this.metadata, rotateTreeseedMachineKeyPassphrase(context.cwd, passphrase));
|
|
447
|
+
} catch (error) {
|
|
448
|
+
if (error instanceof TreeseedKeyAgentError) {
|
|
449
|
+
return failureResult(this.metadata, error.message, { meta: { code: error.code, details: error.details ?? null } });
|
|
450
|
+
}
|
|
451
|
+
throw error;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
class SecretsRotateMachineKeyOperation extends BaseOperation {
|
|
456
|
+
async execute(_input, context) {
|
|
457
|
+
try {
|
|
458
|
+
return operationResult(this.metadata, rotateTreeseedMachineKey(context.cwd));
|
|
459
|
+
} catch (error) {
|
|
460
|
+
if (error instanceof TreeseedKeyAgentError) {
|
|
461
|
+
return failureResult(this.metadata, error.message, { meta: { code: error.code, details: error.details ?? null } });
|
|
462
|
+
}
|
|
463
|
+
throw error;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
353
467
|
class RollbackOperation extends BaseOperation {
|
|
354
468
|
async execute(input, context) {
|
|
355
469
|
const scope = typeof input.environment === "string" ? input.environment : null;
|
|
@@ -469,6 +583,12 @@ class DefaultTreeseedOperationsProvider {
|
|
|
469
583
|
new AuthLoginOperation("auth:login"),
|
|
470
584
|
new AuthLogoutOperation("auth:logout"),
|
|
471
585
|
new AuthWhoAmIOperation("auth:whoami"),
|
|
586
|
+
new SecretsStatusOperation("secrets:status"),
|
|
587
|
+
new SecretsUnlockOperation("secrets:unlock"),
|
|
588
|
+
new SecretsLockOperation("secrets:lock"),
|
|
589
|
+
new SecretsMigrateKeyOperation("secrets:migrate-key"),
|
|
590
|
+
new SecretsRotatePassphraseOperation("secrets:rotate-passphrase"),
|
|
591
|
+
new SecretsRotateMachineKeyOperation("secrets:rotate-machine-key"),
|
|
472
592
|
new RollbackOperation("rollback"),
|
|
473
593
|
new ScriptOperation("build", "tenant-build"),
|
|
474
594
|
new ScriptOperation("check", "tenant-check"),
|
|
@@ -486,7 +606,6 @@ class DefaultTreeseedOperationsProvider {
|
|
|
486
606
|
new ScriptOperation("test:release:full", "workspace-release-verify", ["--full-smoke"]),
|
|
487
607
|
new ScriptOperation("release:publish:changed", "workspace-publish-changed-packages"),
|
|
488
608
|
new ScriptOperation("astro", "tenant-astro-command"),
|
|
489
|
-
new ScriptOperation("sync:devvars", "sync-dev-vars"),
|
|
490
609
|
new MailpitUpOperation("mailpit:up"),
|
|
491
610
|
new MailpitDownOperation("mailpit:down"),
|
|
492
611
|
new MailpitLogsOperation("mailpit:logs"),
|