@treeseed/sdk 0.13.0-rc.33 → 0.13.0-rc.35
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/content/validation/agent-operational-content-schemas.d.ts +4 -4
- package/dist/content/validation/auxiliary-content-schemas.d.ts +34 -34
- package/dist/content/validation/content-model-schemas.d.ts +70 -70
- package/dist/content/validation/portable-content-data.d.ts +12 -12
- package/dist/deployment/schemas.d.ts +19 -1
- package/dist/deployment/schemas.js +8 -1
- package/dist/operator-contracts/canonical-command-tree.js +66 -0
- package/dist/operator-contracts/control-plane-operations.js +10 -10
- package/dist/operator-contracts/seed/seed-bundle.d.ts +22 -7
- package/dist/operator-contracts/seed/seed-bundle.js +17 -3
- package/package.json +1 -1
|
@@ -425,12 +425,26 @@ export declare const hostConfigurationSchema: z.ZodObject<{
|
|
|
425
425
|
role: string;
|
|
426
426
|
architecture: "amd64";
|
|
427
427
|
}>;
|
|
428
|
-
runtime: z.ZodObject<{
|
|
428
|
+
runtime: z.ZodEffects<z.ZodObject<{
|
|
429
429
|
management: z.ZodEnum<["managed", "external"]>;
|
|
430
|
+
environment: z.ZodDefault<z.ZodEnum<["production", "development"]>>;
|
|
431
|
+
dataRoot: z.ZodOptional<z.ZodString>;
|
|
430
432
|
}, "strict", z.ZodTypeAny, {
|
|
431
433
|
management: "managed" | "external";
|
|
434
|
+
environment: "development" | "production";
|
|
435
|
+
dataRoot?: string | undefined;
|
|
436
|
+
}, {
|
|
437
|
+
management: "managed" | "external";
|
|
438
|
+
environment?: "development" | "production" | undefined;
|
|
439
|
+
dataRoot?: string | undefined;
|
|
440
|
+
}>, {
|
|
441
|
+
management: "managed" | "external";
|
|
442
|
+
environment: "development" | "production";
|
|
443
|
+
dataRoot?: string | undefined;
|
|
432
444
|
}, {
|
|
433
445
|
management: "managed" | "external";
|
|
446
|
+
environment?: "development" | "production" | undefined;
|
|
447
|
+
dataRoot?: string | undefined;
|
|
434
448
|
}>;
|
|
435
449
|
updates: z.ZodObject<{
|
|
436
450
|
defaultTrack: z.ZodEnum<["stable", "development"]>;
|
|
@@ -1145,6 +1159,8 @@ export declare const hostConfigurationSchema: z.ZodObject<{
|
|
|
1145
1159
|
};
|
|
1146
1160
|
runtime: {
|
|
1147
1161
|
management: "managed" | "external";
|
|
1162
|
+
environment: "development" | "production";
|
|
1163
|
+
dataRoot?: string | undefined;
|
|
1148
1164
|
};
|
|
1149
1165
|
updates: {
|
|
1150
1166
|
stable: {
|
|
@@ -1253,6 +1269,8 @@ export declare const hostConfigurationSchema: z.ZodObject<{
|
|
|
1253
1269
|
};
|
|
1254
1270
|
runtime: {
|
|
1255
1271
|
management: "managed" | "external";
|
|
1272
|
+
environment?: "development" | "production" | undefined;
|
|
1273
|
+
dataRoot?: string | undefined;
|
|
1256
1274
|
};
|
|
1257
1275
|
updates: {
|
|
1258
1276
|
stable: {
|
|
@@ -69,7 +69,14 @@ const hostConfigurationSchema = z.object({
|
|
|
69
69
|
role: hostRoleSchema,
|
|
70
70
|
architecture: z.literal("amd64")
|
|
71
71
|
}).strict(),
|
|
72
|
-
runtime: z.object({
|
|
72
|
+
runtime: z.object({
|
|
73
|
+
management: z.enum(["managed", "external"]),
|
|
74
|
+
environment: z.enum(["production", "development"]).default("production"),
|
|
75
|
+
dataRoot: z.string().startsWith("/").regex(/\/\.treeseed\/data$/u, "Development dataRoot must end with /.treeseed/data.").optional()
|
|
76
|
+
}).strict().superRefine((runtime, context) => {
|
|
77
|
+
if (runtime.environment === "development" && !runtime.dataRoot) context.addIssue({ code: z.ZodIssueCode.custom, path: ["dataRoot"], message: "Development hosts require an explicit workspace-visible dataRoot." });
|
|
78
|
+
if (runtime.environment === "production" && runtime.dataRoot) context.addIssue({ code: z.ZodIssueCode.custom, path: ["dataRoot"], message: "Production hosts use manager-owned /var/lib state and cannot override dataRoot." });
|
|
79
|
+
}),
|
|
73
80
|
updates: z.object({
|
|
74
81
|
defaultTrack: deploymentTrackSchema,
|
|
75
82
|
stable: z.object({
|
|
@@ -12,6 +12,7 @@ const operationBindings = {
|
|
|
12
12
|
"auth login": protocol("protocol.oauth.device.login"),
|
|
13
13
|
"auth logout": protocol("protocol.oauth.revoke"),
|
|
14
14
|
"auth status": operation("accounts.current.show"),
|
|
15
|
+
"users create": protocol("protocol.accounts.create"),
|
|
15
16
|
"send": operation("communications.send", [field("path", "teamId", "context", "team", true), field("path", "channel", "argument", "channel", true), field("body", "message", "argument", "message", true), field("body", "projectId", "context", "project"), field("body", "recipients", "option", "to"), field("body", "topic", "option"), field("body", "waitSeconds", "option", "wait", false, "integer")]),
|
|
16
17
|
"secrets list": local("local.secrets.list"),
|
|
17
18
|
"secrets status": local("local.secrets.status"),
|
|
@@ -97,6 +98,23 @@ const operationBindings = {
|
|
|
97
98
|
"projects treedx workspaces list": operation("treedx.workspaces.list", [field("path", "projectId", "argument", "project", true), ...page()]),
|
|
98
99
|
"projects treedx workspaces show": operation("treedx.workspaces.show", [field("path", "projectId", "context", "project", true), field("path", "workspaceId", "argument", "workspace", true)]),
|
|
99
100
|
"projects treedx workspaces abandon": operation("treedx.workspaces.abandon", [field("path", "projectId", "context", "project", true), field("path", "workspaceId", "argument", "workspace", true)]),
|
|
101
|
+
"library show": local("local.library.show"),
|
|
102
|
+
"library status": local("local.library.status"),
|
|
103
|
+
"library paths": local("local.library.paths"),
|
|
104
|
+
"library read": local("local.library.read"),
|
|
105
|
+
"library search": local("local.library.search"),
|
|
106
|
+
"library query": local("local.library.query"),
|
|
107
|
+
"library context": local("local.library.context"),
|
|
108
|
+
"library workspace create": operation("knowledge.workspaces.create", [field("path", "projectId", "argument", "project", true), field("body", "requestId", "option", "request")]),
|
|
109
|
+
"library workspace show": operation("knowledge.workspaces.show", [field("path", "workspaceId", "argument", "workspace", true)]),
|
|
110
|
+
"library workspace read": operation("knowledge.workspaces.content.show", [field("path", "workspaceId", "argument", "workspace", true), field("query", "path", "argument", "path", true)]),
|
|
111
|
+
"library workspace diff": operation("knowledge.workspaces.diff", [field("path", "workspaceId", "argument", "workspace", true)]),
|
|
112
|
+
"library workspace write": operation("knowledge.workspaces.content.update", [field("path", "workspaceId", "argument", "workspace", true), field("body", "file", "option", "input", true)]),
|
|
113
|
+
"library workspace submit": operation("knowledge.workspaces.submit", [field("path", "workspaceId", "argument", "workspace", true), field("body", "version", "option", "version", true, "integer"), field("body", "message", "option"), field("body", "notes", "option"), field("body", "contextDigest", "option", "contextDigest")]),
|
|
114
|
+
"library workspace abandon": operation("knowledge.workspaces.abandon", [field("path", "workspaceId", "argument", "workspace", true), field("body", "version", "option", "version", true, "integer")]),
|
|
115
|
+
"library reviews list": operation("knowledge.reviews.list", [field("path", "teamId", "context", "team", true), ...page()]),
|
|
116
|
+
"library reviews decide": operation("knowledge.reviews.decide", [field("path", "reviewId", "argument", "review", true), field("body", "file", "option", "input", true)]),
|
|
117
|
+
"library reviews publish": operation("knowledge.reviews.publish", [field("path", "reviewId", "argument", "review", true), field("body", "file", "option", "input")]),
|
|
100
118
|
"status": operation("status.show"),
|
|
101
119
|
"save": unavailable("Unified GitHub-backed save is intentionally fail-closed during this cutover."),
|
|
102
120
|
"stage": unavailable("Unified GitHub-backed stage is intentionally fail-closed during this cutover."),
|
|
@@ -132,12 +150,41 @@ function hostReset() {
|
|
|
132
150
|
value.options = [...value.options ?? [], { name: "--confirm", description: "Confirm deletion of all manager-owned component data and receipts.", type: "boolean" }];
|
|
133
151
|
return value;
|
|
134
152
|
}
|
|
153
|
+
function userCreate() {
|
|
154
|
+
const value = leaf("create", "mutation", void 0, "credential");
|
|
155
|
+
if (value.nodeType !== "leaf") throw new Error("User creation must be a leaf command.");
|
|
156
|
+
value.description = "Create a local TreeSeed user with a securely prompted password.";
|
|
157
|
+
value.options = [
|
|
158
|
+
...value.options ?? [],
|
|
159
|
+
{ name: "--email", description: "Email address for the new user.", type: "string" },
|
|
160
|
+
{ name: "--username", description: "Unique username for the new user.", type: "string" },
|
|
161
|
+
{ name: "--display-name", description: "Human-readable display name.", type: "string" }
|
|
162
|
+
];
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
function libraryRead(segment, extraArguments = [], extraOptions = []) {
|
|
166
|
+
return {
|
|
167
|
+
nodeType: "leaf",
|
|
168
|
+
segment,
|
|
169
|
+
description: `${segment[0].toUpperCase()}${segment.slice(1)} project library knowledge.`,
|
|
170
|
+
kind: "read",
|
|
171
|
+
arguments: ["project", ...extraArguments].map((name) => ({ name, description: `${name} value.`, required: true })),
|
|
172
|
+
options: [{ name: "--ref", description: "Exact commit or protected library ref.", type: "string" }, ...extraOptions],
|
|
173
|
+
resultSchemaId: `treeseed.command.library.${segment}/v1`,
|
|
174
|
+
execution: local(`local.library.${segment}`)
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function addOptions(node, options) {
|
|
178
|
+
if (node.nodeType === "leaf") node.options = [...node.options ?? [], ...options];
|
|
179
|
+
return node;
|
|
180
|
+
}
|
|
135
181
|
const commandTree = {
|
|
136
182
|
schemaVersion: "treeseed.command-tree/v1",
|
|
137
183
|
executable: "trsd",
|
|
138
184
|
commands: [
|
|
139
185
|
{ nodeType: "leaf", segment: "send", description: "Send a message to project agents through a team discussion channel.", kind: "mutation", arguments: [{ name: "channel", description: "Team discussion channel.", required: true }, { name: "message", description: "Markdown message to send.", required: true }], options: [planOption, { name: "--team", description: "Team identity or slug.", type: "string" }, { name: "--project", description: "Default project for unqualified agent names.", type: "string" }, { name: "--to", description: "Agent target; use project/agent when names may be ambiguous.", type: "string[]" }, { name: "--topic", description: "Optional discussion topic.", type: "string" }, { name: "--wait", description: "Seconds to wait for durable responses.", type: "number", defaultValue: 0 }], authorization: { capability: "agents.execute", confirmation: "never" }, resultSchemaId: "treeseed.communication-send-receipt/v1", execution: unavailable() },
|
|
140
186
|
branch("auth", [leaf("login", "mutation", void 0, "credential"), leaf("logout", "mutation"), leaf("status")]),
|
|
187
|
+
branch("users", [userCreate()]),
|
|
141
188
|
branch("secrets", [leaf("list"), leaf("status"), leaf("unlock", "mutation", void 0, "credential"), leaf("lock", "mutation"), leaf("rotate", "mutation", void 0, "credential")]),
|
|
142
189
|
branch("host", [
|
|
143
190
|
leaf("status"),
|
|
@@ -203,6 +250,25 @@ const commandTree = {
|
|
|
203
250
|
leaf("capabilities", "read", "project"),
|
|
204
251
|
branch("workspaces", [leaf("list", "read", "project"), leaf("show", "read", "workspace"), leaf("abandon", "mutation", "workspace", "destructive")])
|
|
205
252
|
])]),
|
|
253
|
+
branch("library", [
|
|
254
|
+
libraryRead("show"),
|
|
255
|
+
libraryRead("status"),
|
|
256
|
+
libraryRead("paths", [], [{ name: "--prefix", description: "Repository-relative path prefix.", type: "string" }, { name: "--limit", description: "Page size.", type: "number" }, { name: "--cursor", description: "Opaque page cursor.", type: "string" }]),
|
|
257
|
+
libraryRead("read", ["path"]),
|
|
258
|
+
libraryRead("search", ["query"], [{ name: "--path", description: "Restrict search to a repository-relative path.", type: "string" }, { name: "--limit", description: "Page size.", type: "number" }, { name: "--cursor", description: "Opaque page cursor.", type: "string" }]),
|
|
259
|
+
libraryRead("query", ["query"], [{ name: "--model", description: "TreeDX content model.", type: "string" }, { name: "--input", description: "YAML or JSON query body.", type: "string" }]),
|
|
260
|
+
libraryRead("context", ["query"], [{ name: "--max-items", description: "Maximum context items.", type: "number" }, { name: "--max-tokens", description: "Maximum context tokens.", type: "number" }]),
|
|
261
|
+
branch("workspace", [
|
|
262
|
+
addOptions(leaf("create", "mutation", "project"), [{ name: "--request", description: "Replay-safe UUID request identity.", type: "string" }]),
|
|
263
|
+
leaf("show", "read", "workspace"),
|
|
264
|
+
{ nodeType: "leaf", segment: "read", description: "Read a file from a governed library workspace.", kind: "read", arguments: [{ name: "workspace", description: "Workspace identity.", required: true }, { name: "path", description: "Repository-relative path.", required: true }], resultSchemaId: "treeseed.command.library.workspace.read/v1", execution: unavailable() },
|
|
265
|
+
leaf("diff", "read", "workspace"),
|
|
266
|
+
addOptions(leaf("write", "mutation", "workspace"), [{ name: "--input", description: "YAML or JSON draft body.", type: "string", required: true }]),
|
|
267
|
+
addOptions(leaf("submit", "mutation", "workspace"), [{ name: "--version", description: "Expected workspace version.", type: "number", required: true }, { name: "--message", description: "Commit message.", type: "string" }, { name: "--notes", description: "Review notes.", type: "string" }, { name: "--context-digest", description: "Verified editorial context digest.", type: "string" }]),
|
|
268
|
+
addOptions(leaf("abandon", "mutation", "workspace", "destructive"), [{ name: "--version", description: "Expected workspace version.", type: "number", required: true }])
|
|
269
|
+
]),
|
|
270
|
+
branch("reviews", [leaf("list"), addOptions(leaf("decide", "mutation", "review"), [{ name: "--input", description: "YAML or JSON review decision.", type: "string", required: true }]), addOptions(leaf("publish", "mutation", "review"), [{ name: "--input", description: "Optional YAML or JSON publication body.", type: "string" }])])
|
|
271
|
+
]),
|
|
206
272
|
leaf("save", "mutation"),
|
|
207
273
|
leaf("stage", "mutation", void 0, "authority"),
|
|
208
274
|
leaf("release", "mutation", void 0, "production"),
|
|
@@ -184,17 +184,17 @@ const CONTROL_PLANE_OPERATIONS = {
|
|
|
184
184
|
search: resource("knowledge.search", "GET", "/v1/knowledge/search", {}, { capability: "knowledge.read", surfaces: ["rest", "mcp_tool"], pagination: "cursor" }),
|
|
185
185
|
teamCatalog: resource("knowledge.catalog.team", "GET", "/v1/teams/{teamId}/knowledge/catalog", { teamId: z.string().min(1) }, { capability: "knowledge.read", pagination: "cursor" }),
|
|
186
186
|
projectCatalog: resource("knowledge.catalog.project", "GET", "/v1/projects/{projectId}/knowledge/catalog", { projectId: z.string().min(1) }, { capability: "knowledge.read", pagination: "cursor" }),
|
|
187
|
-
createWorkspace: resource("knowledge.workspaces.create", "POST", "/v1/projects/{projectId}/knowledge/workspaces", { projectId: z.string().min(1) }, { capability: "knowledge.write", scopes: ["treeseed:knowledge:write"] }),
|
|
188
|
-
workspace: resource("knowledge.workspaces.show", "GET", "/v1/knowledge/workspaces/{workspaceId}", { workspaceId: z.string().min(1) }, { capability: "knowledge.read" }),
|
|
189
|
-
workspaceContent: resource("knowledge.workspaces.content.show", "GET", "/v1/knowledge/workspaces/{workspaceId}/content", { workspaceId: z.string().min(1) }, { capability: "knowledge.read" }),
|
|
190
|
-
updateWorkspaceContent: resource("knowledge.workspaces.content.update", "PUT", "/v1/knowledge/workspaces/{workspaceId}/content", { workspaceId: z.string().min(1) }, { capability: "knowledge.write", scopes: ["treeseed:knowledge:write"], concurrency: true }),
|
|
191
|
-
workspaceDiff: resource("knowledge.workspaces.diff", "GET", "/v1/knowledge/workspaces/{workspaceId}/diff", { workspaceId: z.string().min(1) }, { capability: "knowledge.read" }),
|
|
192
|
-
abandonWorkspace: resource("knowledge.workspaces.abandon", "POST", "/v1/knowledge/workspaces/{workspaceId}/abandon", { workspaceId: z.string().min(1) }, { capability: "knowledge.write", scopes: ["treeseed:knowledge:write"], risk: "destructive", concurrency: true }),
|
|
193
|
-
submitWorkspace: resource("knowledge.workspaces.submit", "POST", "/v1/knowledge/workspaces/{workspaceId}/submit", { workspaceId: z.string().min(1) }, { capability: "knowledge.write", scopes: ["treeseed:knowledge:write"], concurrency: true }),
|
|
194
|
-
reviews: resource("knowledge.reviews.list", "GET", "/v1/teams/{teamId}/knowledge/reviews", { teamId: z.string().min(1) }, { capability: "knowledge.review", pagination: "cursor" }),
|
|
187
|
+
createWorkspace: resource("knowledge.workspaces.create", "POST", "/v1/projects/{projectId}/knowledge/workspaces", { projectId: z.string().min(1) }, { capability: "knowledge.write", scopes: ["treeseed:knowledge:write"], surfaces: ["rest", "cli"] }),
|
|
188
|
+
workspace: resource("knowledge.workspaces.show", "GET", "/v1/knowledge/workspaces/{workspaceId}", { workspaceId: z.string().min(1) }, { capability: "knowledge.read", surfaces: ["rest", "cli"] }),
|
|
189
|
+
workspaceContent: resource("knowledge.workspaces.content.show", "GET", "/v1/knowledge/workspaces/{workspaceId}/content", { workspaceId: z.string().min(1) }, { capability: "knowledge.read", surfaces: ["rest", "cli"] }),
|
|
190
|
+
updateWorkspaceContent: resource("knowledge.workspaces.content.update", "PUT", "/v1/knowledge/workspaces/{workspaceId}/content", { workspaceId: z.string().min(1) }, { capability: "knowledge.write", scopes: ["treeseed:knowledge:write"], surfaces: ["rest", "cli"], concurrency: true }),
|
|
191
|
+
workspaceDiff: resource("knowledge.workspaces.diff", "GET", "/v1/knowledge/workspaces/{workspaceId}/diff", { workspaceId: z.string().min(1) }, { capability: "knowledge.read", surfaces: ["rest", "cli"] }),
|
|
192
|
+
abandonWorkspace: resource("knowledge.workspaces.abandon", "POST", "/v1/knowledge/workspaces/{workspaceId}/abandon", { workspaceId: z.string().min(1) }, { capability: "knowledge.write", scopes: ["treeseed:knowledge:write"], surfaces: ["rest", "cli"], risk: "destructive", concurrency: true }),
|
|
193
|
+
submitWorkspace: resource("knowledge.workspaces.submit", "POST", "/v1/knowledge/workspaces/{workspaceId}/submit", { workspaceId: z.string().min(1) }, { capability: "knowledge.write", scopes: ["treeseed:knowledge:write"], surfaces: ["rest", "cli"], concurrency: true }),
|
|
194
|
+
reviews: resource("knowledge.reviews.list", "GET", "/v1/teams/{teamId}/knowledge/reviews", { teamId: z.string().min(1) }, { capability: "knowledge.review", surfaces: ["rest", "cli"], pagination: "cursor" }),
|
|
195
195
|
commentReview: resource("knowledge.reviews.comments.create", "POST", "/v1/knowledge/reviews/{reviewId}/comments", { reviewId: z.string().min(1) }, { capability: "knowledge.review", scopes: ["treeseed:knowledge:write"] }),
|
|
196
|
-
decideReview: resource("knowledge.reviews.decide", "POST", "/v1/knowledge/reviews/{reviewId}/decision", { reviewId: z.string().min(1) }, { capability: "knowledge.review", scopes: ["treeseed:knowledge:write"], concurrency: true }),
|
|
197
|
-
publishReview: resource("knowledge.reviews.publish", "POST", "/v1/knowledge/reviews/{reviewId}/publish", { reviewId: z.string().min(1) }, { capability: "knowledge.publish", scopes: ["treeseed:knowledge:write"], concurrency: true })
|
|
196
|
+
decideReview: resource("knowledge.reviews.decide", "POST", "/v1/knowledge/reviews/{reviewId}/decision", { reviewId: z.string().min(1) }, { capability: "knowledge.review", scopes: ["treeseed:knowledge:write"], surfaces: ["rest", "cli"], concurrency: true }),
|
|
197
|
+
publishReview: resource("knowledge.reviews.publish", "POST", "/v1/knowledge/reviews/{reviewId}/publish", { reviewId: z.string().min(1) }, { capability: "knowledge.publish", scopes: ["treeseed:knowledge:write"], surfaces: ["rest", "cli"], concurrency: true })
|
|
198
198
|
},
|
|
199
199
|
governance: {
|
|
200
200
|
proposals: resource("governance.proposals.list", "GET", "/v1/projects/{projectId}/proposals", { projectId: z.string().min(1) }, { capability: "governance.read", surfaces: ["rest", "mcp_tool", "mcp_resource"], pagination: "cursor" }),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ProviderLanePurpose } from '../../agent-capacity/contracts/capacity/communication/communication-records.js';
|
|
2
|
-
export declare const SEED_BUNDLE_SCHEMA_VERSION: "treeseed.seed-bundle/
|
|
2
|
+
export declare const SEED_BUNDLE_SCHEMA_VERSION: "treeseed.seed-bundle/v3";
|
|
3
|
+
export declare const HISTORICAL_SEED_BUNDLE_SCHEMA_VERSION: "treeseed.seed-bundle/v2";
|
|
3
4
|
export type SeedEnvironment = 'local' | 'staging' | 'prod' | string;
|
|
4
5
|
export interface SeedTeamResource {
|
|
5
6
|
key: string;
|
|
@@ -43,7 +44,7 @@ export interface SeedRepositoryPolicy {
|
|
|
43
44
|
export interface SeedRepositoryResource {
|
|
44
45
|
key: string;
|
|
45
46
|
project: string;
|
|
46
|
-
role: 'primary' | 'fixture' | 'support' | 'template';
|
|
47
|
+
role: 'primary' | 'library' | 'fixture' | 'support' | 'template';
|
|
47
48
|
provider: 'github';
|
|
48
49
|
owner: string;
|
|
49
50
|
name: string;
|
|
@@ -62,6 +63,7 @@ export interface SeedProjectResource {
|
|
|
62
63
|
description: string;
|
|
63
64
|
kind: string;
|
|
64
65
|
primaryRepository?: string;
|
|
66
|
+
libraryRepository: string;
|
|
65
67
|
metadata?: Record<string, unknown>;
|
|
66
68
|
}
|
|
67
69
|
export interface SeedCapacityProviderPrerequisite {
|
|
@@ -75,8 +77,7 @@ export interface SeedCapacityProviderPrerequisite {
|
|
|
75
77
|
allowedModes: Array<'planning' | 'acting'>;
|
|
76
78
|
requiredLanePurposes: ProviderLanePurpose[];
|
|
77
79
|
}
|
|
78
|
-
|
|
79
|
-
schemaVersion: typeof SEED_BUNDLE_SCHEMA_VERSION;
|
|
80
|
+
interface SeedBundleBody {
|
|
80
81
|
name: string;
|
|
81
82
|
version: number;
|
|
82
83
|
description: string;
|
|
@@ -92,6 +93,19 @@ export interface SeedBundleV2 {
|
|
|
92
93
|
capacityProviders: SeedCapacityProviderPrerequisite[];
|
|
93
94
|
};
|
|
94
95
|
}
|
|
96
|
+
export interface SeedBundleV3 extends SeedBundleBody {
|
|
97
|
+
schemaVersion: typeof SEED_BUNDLE_SCHEMA_VERSION;
|
|
98
|
+
}
|
|
99
|
+
/** Historical receipt shape. It is decodable, but cannot be planned or applied. */
|
|
100
|
+
export interface SeedBundleV2 extends Omit<SeedBundleBody, 'resources'> {
|
|
101
|
+
schemaVersion: typeof HISTORICAL_SEED_BUNDLE_SCHEMA_VERSION;
|
|
102
|
+
resources: Omit<SeedBundleBody['resources'], 'projects'> & {
|
|
103
|
+
projects: Array<Omit<SeedProjectResource, 'libraryRepository'> & {
|
|
104
|
+
libraryRepository?: string;
|
|
105
|
+
}>;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export type SeedBundle = SeedBundleV3 | SeedBundleV2;
|
|
95
109
|
export interface SeedResourceReceipt {
|
|
96
110
|
resourceKey: string;
|
|
97
111
|
action: 'create' | 'adopt' | 'update' | 'noop' | 'blocked';
|
|
@@ -118,6 +132,7 @@ export interface SeedBundleDiagnostic {
|
|
|
118
132
|
path: string;
|
|
119
133
|
message: string;
|
|
120
134
|
}
|
|
121
|
-
export declare function canonicalSeedBundlePayload(bundle: Omit<
|
|
122
|
-
export declare function digestSeedBundle(bundle: Omit<
|
|
123
|
-
export declare function validateSeedBundle(bundle:
|
|
135
|
+
export declare function canonicalSeedBundlePayload(bundle: Omit<SeedBundle, 'digest'> | SeedBundle): string;
|
|
136
|
+
export declare function digestSeedBundle(bundle: Omit<SeedBundle, 'digest'> | SeedBundle): Promise<`sha256:${string}`>;
|
|
137
|
+
export declare function validateSeedBundle(bundle: SeedBundle): SeedBundleDiagnostic[];
|
|
138
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const SEED_BUNDLE_SCHEMA_VERSION = "treeseed.seed-bundle/
|
|
1
|
+
const SEED_BUNDLE_SCHEMA_VERSION = "treeseed.seed-bundle/v3";
|
|
2
|
+
const HISTORICAL_SEED_BUNDLE_SCHEMA_VERSION = "treeseed.seed-bundle/v2";
|
|
2
3
|
function text(value) {
|
|
3
4
|
return typeof value === "string" && value.trim().length > 0;
|
|
4
5
|
}
|
|
@@ -19,7 +20,11 @@ async function digestSeedBundle(bundle) {
|
|
|
19
20
|
function validateSeedBundle(bundle) {
|
|
20
21
|
const diagnostics = [];
|
|
21
22
|
const add = (code, path, message) => diagnostics.push({ code, path, message });
|
|
22
|
-
if (bundle?.schemaVersion
|
|
23
|
+
if (bundle?.schemaVersion === HISTORICAL_SEED_BUNDLE_SCHEMA_VERSION) {
|
|
24
|
+
add("seed_bundle_v2_migration_required", "schemaVersion", `Historical v2 bundles remain readable but must be migrated to ${SEED_BUNDLE_SCHEMA_VERSION} before planning or apply.`);
|
|
25
|
+
} else if (bundle?.schemaVersion !== SEED_BUNDLE_SCHEMA_VERSION) {
|
|
26
|
+
add("seed_bundle_schema_invalid", "schemaVersion", `schemaVersion must be ${SEED_BUNDLE_SCHEMA_VERSION}.`);
|
|
27
|
+
}
|
|
23
28
|
if (!text(bundle?.name) || !Number.isInteger(bundle?.version) || bundle.version < 1) add("seed_bundle_identity_invalid", "name", "Seed name and positive version are required.");
|
|
24
29
|
if (!/^sha256:[a-f0-9]{64}$/u.test(bundle?.digest ?? "")) add("seed_bundle_digest_invalid", "digest", "Seed digest must be an exact SHA-256 digest.");
|
|
25
30
|
const teams = new Set((bundle?.resources?.teams ?? []).map((entry) => entry.key));
|
|
@@ -35,9 +40,17 @@ function validateSeedBundle(bundle) {
|
|
|
35
40
|
if (!teams.has(project.team)) add("seed_bundle_project_team_unknown", `resources.projects[${index}].team`, "Project references an unknown team.");
|
|
36
41
|
if (!project.primaryRepository && project.kind !== "content") add("seed_bundle_primary_repository_required", `resources.projects[${index}].primaryRepository`, "Non-content projects require a primary source repository.");
|
|
37
42
|
if (project.primaryRepository && !repositories.has(project.primaryRepository)) add("seed_bundle_primary_repository_unknown", `resources.projects[${index}].primaryRepository`, "Project primary repository is missing.");
|
|
43
|
+
if (!project.libraryRepository) add("seed_bundle_library_repository_required", `resources.projects[${index}].libraryRepository`, "Every project requires one library repository.");
|
|
44
|
+
if (project.libraryRepository && !repositories.has(project.libraryRepository)) add("seed_bundle_library_repository_unknown", `resources.projects[${index}].libraryRepository`, "Project library repository is missing.");
|
|
38
45
|
}
|
|
39
46
|
for (const [index, repository] of (bundle?.resources?.repositories ?? []).entries()) {
|
|
40
|
-
if (repository.role === "content") add("
|
|
47
|
+
if (repository.role === "content") add("seed_bundle_content_repository_renamed", `resources.repositories[${index}].role`, "Repository-backed knowledge uses role library.");
|
|
48
|
+
}
|
|
49
|
+
for (const [index, project] of (bundle?.resources?.projects ?? []).entries()) {
|
|
50
|
+
const library = (bundle?.resources?.repositories ?? []).find((entry) => entry.key === project.libraryRepository);
|
|
51
|
+
if (library && (library.role !== "library" || library.project !== project.key)) add("seed_bundle_library_repository_mismatch", `resources.projects[${index}].libraryRepository`, "libraryRepository must reference a library-role repository owned by this project.");
|
|
52
|
+
const projectLibraries = (bundle?.resources?.repositories ?? []).filter((entry) => entry.project === project.key && entry.role === "library");
|
|
53
|
+
if (projectLibraries.length !== 1) add("seed_bundle_library_repository_count_invalid", `resources.projects[${index}].libraryRepository`, "Every project must declare exactly one library-role repository.");
|
|
41
54
|
}
|
|
42
55
|
for (const [index, provider] of (bundle?.runtime?.capacityProviders ?? []).entries()) {
|
|
43
56
|
if (!teams.has(provider.team)) add("seed_bundle_provider_team_unknown", `runtime.capacityProviders[${index}].team`, "Provider references an unknown team.");
|
|
@@ -47,6 +60,7 @@ function validateSeedBundle(bundle) {
|
|
|
47
60
|
return diagnostics;
|
|
48
61
|
}
|
|
49
62
|
export {
|
|
63
|
+
HISTORICAL_SEED_BUNDLE_SCHEMA_VERSION,
|
|
50
64
|
SEED_BUNDLE_SCHEMA_VERSION,
|
|
51
65
|
canonicalSeedBundlePayload,
|
|
52
66
|
digestSeedBundle,
|