@treeseed/sdk 0.4.13 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/control-plane-client.d.ts +60 -1
  2. package/dist/control-plane-client.js +59 -0
  3. package/dist/control-plane.d.ts +1 -1
  4. package/dist/control-plane.js +11 -4
  5. package/dist/d1-store.d.ts +58 -0
  6. package/dist/d1-store.js +64 -0
  7. package/dist/dispatch.js +6 -0
  8. package/dist/graph/schema.js +4 -0
  9. package/dist/index.d.ts +5 -1
  10. package/dist/index.js +32 -0
  11. package/dist/knowledge-coop.d.ts +223 -0
  12. package/dist/knowledge-coop.js +82 -0
  13. package/dist/model-registry.js +79 -0
  14. package/dist/operations/providers/default.js +126 -7
  15. package/dist/operations/services/config-runtime.d.ts +102 -24
  16. package/dist/operations/services/config-runtime.js +896 -160
  17. package/dist/operations/services/deploy.d.ts +223 -15
  18. package/dist/operations/services/deploy.js +626 -55
  19. package/dist/operations/services/github-automation.d.ts +60 -0
  20. package/dist/operations/services/github-automation.js +138 -0
  21. package/dist/operations/services/key-agent.d.ts +118 -0
  22. package/dist/operations/services/key-agent.js +476 -0
  23. package/dist/operations/services/knowledge-coop-launch.d.ts +90 -0
  24. package/dist/operations/services/knowledge-coop-launch.js +753 -0
  25. package/dist/operations/services/knowledge-coop-packaging.d.ts +59 -0
  26. package/dist/operations/services/knowledge-coop-packaging.js +234 -0
  27. package/dist/operations/services/local-dev.d.ts +0 -1
  28. package/dist/operations/services/local-dev.js +1 -14
  29. package/dist/operations/services/project-platform.d.ts +42 -182
  30. package/dist/operations/services/project-platform.js +162 -59
  31. package/dist/operations/services/railway-deploy.d.ts +1 -0
  32. package/dist/operations/services/railway-deploy.js +31 -13
  33. package/dist/operations/services/runtime-tools.d.ts +52 -5
  34. package/dist/operations/services/runtime-tools.js +186 -26
  35. package/dist/operations/services/watch-dev.js +2 -4
  36. package/dist/operations/services/workspace-preflight.d.ts +4 -4
  37. package/dist/operations/services/workspace-preflight.js +22 -20
  38. package/dist/operations-registry.js +7 -2
  39. package/dist/platform/contracts.d.ts +39 -3
  40. package/dist/platform/deploy-config.d.ts +12 -1
  41. package/dist/platform/deploy-config.js +214 -15
  42. package/dist/platform/deploy-runtime.d.ts +1 -0
  43. package/dist/platform/deploy-runtime.js +10 -2
  44. package/dist/platform/env.yaml +93 -61
  45. package/dist/platform/environment.d.ts +13 -2
  46. package/dist/platform/environment.js +90 -20
  47. package/dist/platform/plugins/constants.d.ts +1 -0
  48. package/dist/platform/plugins/constants.js +7 -6
  49. package/dist/platform/tenant/runtime-config.js +8 -1
  50. package/dist/platform/tenant-config.js +4 -0
  51. package/dist/platform/utils/site-config-schema.js +18 -0
  52. package/dist/plugin-default.js +2 -2
  53. package/dist/scripts/key-agent.js +165 -0
  54. package/dist/scripts/tenant-build.js +4 -1
  55. package/dist/scripts/tenant-check.js +4 -1
  56. package/dist/scripts/tenant-deploy.js +43 -4
  57. package/dist/scripts/tenant-dev.js +0 -1
  58. package/dist/sdk-types.d.ts +2 -2
  59. package/dist/sdk-types.js +2 -0
  60. package/dist/sdk.d.ts +13 -0
  61. package/dist/sdk.js +40 -0
  62. package/dist/stores/knowledge-coop-store.d.ts +56 -0
  63. package/dist/stores/knowledge-coop-store.js +482 -0
  64. package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +6 -2
  65. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/api/server.js +4 -0
  66. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +25 -0
  67. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/decisions/adopt-initial-proposal-loop.mdx +22 -0
  68. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/people/starter-steward.mdx +11 -0
  69. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/proposals/establish-initial-proposal-loop.mdx +17 -0
  70. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +17 -10
  71. package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +69 -7
  72. package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +1 -0
  73. package/dist/verification.js +90 -2
  74. package/dist/workflow/operations.d.ts +98 -0
  75. package/dist/workflow/operations.js +229 -7
  76. package/dist/workflow-state.d.ts +54 -2
  77. package/dist/workflow-state.js +170 -24
  78. package/dist/workflow-support.d.ts +1 -1
  79. package/dist/workflow-support.js +32 -2
  80. package/dist/workflow.d.ts +29 -0
  81. package/package.json +1 -1
  82. package/templates/github/deploy.workflow.yml +11 -1
  83. package/dist/scripts/sync-dev-vars.js +0 -6
@@ -61,7 +61,6 @@ function runTenantBuildCycle({ includePackageBuild = false, includeSdkBuild = fa
61
61
  const buildScripts = [
62
62
  ['patch-starlight-content-path', []],
63
63
  ['aggregate-book', []],
64
- ['sync-dev-vars', envOverrides],
65
64
  ['tenant-d1-migrate-local', []],
66
65
  ];
67
66
  if (shouldEnsureMailpit()) {
@@ -1,5 +1,5 @@
1
1
  import type { TreeseedFieldAliasBinding } from './field-aliases.ts';
2
- export declare const SDK_MODEL_NAMES: readonly ["page", "note", "question", "book", "knowledge", "objective", "person", "subscription", "message", "agent", "agent_run", "agent_cursor", "content_lease", "work_day", "task", "task_event", "task_output", "graph_run", "report"];
2
+ export declare const SDK_MODEL_NAMES: readonly ["page", "note", "question", "proposal", "decision", "book", "knowledge", "objective", "person", "subscription", "message", "agent", "agent_run", "agent_cursor", "content_lease", "work_day", "task", "task_event", "task_output", "graph_run", "report"];
3
3
  export declare const SDK_OPERATIONS: readonly ["get", "read", "search", "follow", "pick", "create", "update"];
4
4
  export declare const SDK_STORAGE_BACKENDS: readonly ["content", "d1"];
5
5
  export declare const SDK_PICK_STRATEGIES: readonly ["latest", "highest_priority", "oldest"];
@@ -741,7 +741,7 @@ export interface SdkModelDefinition {
741
741
  graph?: SdkGraphModelConfig;
742
742
  }
743
743
  export type SdkModelRegistry = Record<string, SdkModelDefinition>;
744
- export type SdkGraphNodeType = 'File' | 'Section' | 'Agent' | 'Objective' | 'Question' | 'Note' | 'Knowledge' | 'Book' | 'Page' | 'Person' | 'Tag' | 'Series' | 'Reference' | 'Entity';
744
+ export type SdkGraphNodeType = 'File' | 'Section' | 'Agent' | 'Objective' | 'Question' | 'Note' | 'Proposal' | 'Decision' | 'Knowledge' | 'Book' | 'Page' | 'Person' | 'Tag' | 'Series' | 'Reference' | 'Entity';
745
745
  export type SdkGraphEdgeType = 'HAS_SECTION' | 'BELONGS_TO_FILE' | 'PARENT_SECTION' | 'CHILD_SECTION' | 'NEXT_SECTION' | 'PREV_SECTION' | 'LINKS_TO' | 'REFERENCES' | 'MENTIONS' | 'HAS_TAG' | 'IN_SERIES' | 'SAME_DIRECTORY' | 'SAME_COLLECTION' | 'DEFINES' | 'DEFINED_BY' | 'RELATES_TO' | 'DEPENDS_ON' | 'IMPLEMENTS' | 'EXTENDS' | 'SUPERSEDES' | 'BELONGS_TO' | 'ABOUT' | 'USED_BY' | 'GENERATED_FROM';
746
746
  export interface SdkGraphReferenceFieldConfig {
747
747
  field: string;
package/dist/sdk-types.js CHANGED
@@ -2,6 +2,8 @@ const SDK_MODEL_NAMES = [
2
2
  "page",
3
3
  "note",
4
4
  "question",
5
+ "proposal",
6
+ "decision",
5
7
  "book",
6
8
  "knowledge",
7
9
  "objective",
package/dist/sdk.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { AgentPermissionConfig, AgentRuntimeSpec } from './types/agents.ts'
2
2
  import { ContentStore } from './content-store.ts';
3
3
  import { type AgentDatabase } from './d1-store.ts';
4
4
  import { type LoadedTreeseedPluginEntry } from './platform/plugins.ts';
5
+ import type { ReleaseDetail, ReleaseSummary, SharePackageStatus, WorkstreamDetail, WorkstreamEvent, WorkstreamSummary } from './knowledge-coop.ts';
5
6
  import type { SdkAckMessageRequest, SdkClaimMessageRequest, SdkClaimTaskRequest, SdkCloseWorkDayRequest, SdkCompleteTaskRequest, SdkCreateReportRequest, SdkCreateMessageRequest, SdkCreatePrioritySnapshotRequest, SdkCreateTaskRequest, SdkCursorRequest, SdkFailTaskRequest, SdkFollowRequest, SdkGetRequest, SdkGetCursorRequest, SdkJsonEnvelope, SdkLeaseReleaseRequest, SdkManagerContextPayload, SdkMutationRequest, SdkGraphQueryOptions, SdkGraphQueryRequest, SdkGraphRefreshRequest, SdkGraphSearchOptions, SdkContextPackRequest, SdkGraphDslParseResult, SdkPickRequest, SdkPriorityOverrideRequest, SdkRecordRunRequest, SdkRecordScaleDecisionRequest, SdkRecordTaskCreditsRequest, SdkSearchRequest, SdkStartWorkDayRequest, SdkTaskProgressRequest, SdkTaskSearchRequest, SdkUpsertWorkPolicyRequest, SdkUpdateRequest, SdkModelDefinition, SdkModelRegistry, SdkGraphRankingProvider, SdkDispatchConfig, SdkDispatchRequest, SdkDispatchResult, PrioritySnapshot, ScaleDecision, TaskCreditLedgerEntry, WorkdayPolicy } from './sdk-types.ts';
6
7
  export interface AgentSdkOptions {
7
8
  repoRoot?: string;
@@ -95,6 +96,18 @@ export declare class AgentSdk {
95
96
  listTaskCredits(workDayId: string): Promise<SdkJsonEnvelope<TaskCreditLedgerEntry[]>>;
96
97
  recordScaleDecision(request: SdkRecordScaleDecisionRequest): Promise<SdkJsonEnvelope<ScaleDecision>>;
97
98
  getLatestScaleDecision(projectId: string, environment: string, poolName: string): Promise<SdkJsonEnvelope<ScaleDecision>>;
99
+ listWorkstreams(projectId: string): Promise<SdkJsonEnvelope<WorkstreamSummary[]>>;
100
+ getWorkstream(workstreamId: string): Promise<SdkJsonEnvelope<WorkstreamDetail>>;
101
+ upsertWorkstream(input: Partial<WorkstreamSummary> & Pick<WorkstreamSummary, 'projectId' | 'title'>): Promise<SdkJsonEnvelope<WorkstreamSummary>>;
102
+ appendWorkstreamEvent(input: Pick<WorkstreamEvent, 'projectId' | 'workstreamId' | 'kind'> & Partial<WorkstreamEvent>): Promise<SdkJsonEnvelope<WorkstreamEvent>>;
103
+ listReleases(projectId: string): Promise<SdkJsonEnvelope<ReleaseSummary[]>>;
104
+ getRelease(releaseId: string): Promise<SdkJsonEnvelope<ReleaseDetail>>;
105
+ upsertRelease(input: Partial<ReleaseSummary> & Pick<ReleaseSummary, 'projectId' | 'version'> & {
106
+ items?: ReleaseDetail['items'];
107
+ }): Promise<SdkJsonEnvelope<ReleaseDetail>>;
108
+ listSharePackages(projectId: string): Promise<SdkJsonEnvelope<SharePackageStatus[]>>;
109
+ getSharePackage(packageId: string): Promise<SdkJsonEnvelope<SharePackageStatus>>;
110
+ upsertSharePackage(input: Partial<SharePackageStatus> & Pick<SharePackageStatus, 'projectId' | 'kind' | 'title'>): Promise<SdkJsonEnvelope<SharePackageStatus>>;
98
111
  listAgentSpecs(options?: {
99
112
  enabled?: boolean;
100
113
  }): Promise<AgentRuntimeSpec[]>;
package/dist/sdk.js CHANGED
@@ -301,6 +301,46 @@ class AgentSdk {
301
301
  const payload = await this.database.getLatestScaleDecision(projectId, environment, poolName);
302
302
  return this.envelope("report", "get", payload);
303
303
  }
304
+ async listWorkstreams(projectId) {
305
+ const payload = await this.database.listWorkstreams(projectId);
306
+ return this.envelope("task", "search", payload, { count: payload.length });
307
+ }
308
+ async getWorkstream(workstreamId) {
309
+ const payload = await this.database.getWorkstream(workstreamId);
310
+ return this.envelope("task", "get", payload);
311
+ }
312
+ async upsertWorkstream(input) {
313
+ const payload = await this.database.upsertWorkstream(input);
314
+ return this.envelope("task", "update", payload);
315
+ }
316
+ async appendWorkstreamEvent(input) {
317
+ const payload = await this.database.appendWorkstreamEvent(input);
318
+ return this.envelope("task_event", "create", payload);
319
+ }
320
+ async listReleases(projectId) {
321
+ const payload = await this.database.listReleases(projectId);
322
+ return this.envelope("report", "search", payload, { count: payload.length });
323
+ }
324
+ async getRelease(releaseId) {
325
+ const payload = await this.database.getRelease(releaseId);
326
+ return this.envelope("report", "get", payload);
327
+ }
328
+ async upsertRelease(input) {
329
+ const payload = await this.database.upsertRelease(input);
330
+ return this.envelope("report", "update", payload);
331
+ }
332
+ async listSharePackages(projectId) {
333
+ const payload = await this.database.listSharePackages(projectId);
334
+ return this.envelope("report", "search", payload, { count: payload.length });
335
+ }
336
+ async getSharePackage(packageId) {
337
+ const payload = await this.database.getSharePackage(packageId);
338
+ return this.envelope("report", "get", payload);
339
+ }
340
+ async upsertSharePackage(input) {
341
+ const payload = await this.database.upsertSharePackage(input);
342
+ return this.envelope("report", "update", payload);
343
+ }
304
344
  async listAgentSpecs(options) {
305
345
  const rawEntries = await this.listRawAgentSpecs(options);
306
346
  return rawEntries.map((entry) => normalizeAgentSpec(entry)).filter((entry) => Boolean(entry && entry.slug));
@@ -0,0 +1,56 @@
1
+ import type { ReleaseDetail, ReleaseSummary, SharePackageStatus, WorkstreamDetail, WorkstreamEvent, WorkstreamState, WorkstreamSummary, LinkedProjectRecordRef } from '../knowledge-coop.ts';
2
+ import { SqliteStoreBase } from './helpers.ts';
3
+ export declare class MemoryKnowledgeCoopStore {
4
+ private readonly workstreams;
5
+ private readonly workstreamEvents;
6
+ private readonly releases;
7
+ private readonly releaseItems;
8
+ private readonly packages;
9
+ listWorkstreams(projectId: string): WorkstreamSummary[];
10
+ getWorkstream(workstreamId: string): WorkstreamDetail | null;
11
+ upsertWorkstream(input: Partial<WorkstreamSummary> & Pick<WorkstreamSummary, 'projectId' | 'title'>): WorkstreamSummary;
12
+ appendWorkstreamEvent(input: Pick<WorkstreamEvent, 'projectId' | 'workstreamId' | 'kind'> & Partial<WorkstreamEvent>): WorkstreamEvent;
13
+ listReleases(projectId: string): ReleaseSummary[];
14
+ getRelease(releaseId: string): ReleaseDetail | null;
15
+ upsertRelease(input: Partial<ReleaseSummary> & Pick<ReleaseSummary, 'projectId' | 'version'> & {
16
+ items?: ReleaseDetail['items'];
17
+ }): ReleaseDetail | null;
18
+ listSharePackages(projectId: string): SharePackageStatus[];
19
+ getSharePackage(packageId: string): SharePackageStatus | null;
20
+ upsertSharePackage(input: Partial<SharePackageStatus> & Pick<SharePackageStatus, 'projectId' | 'kind' | 'title'>): SharePackageStatus;
21
+ }
22
+ export declare class SqliteKnowledgeCoopStore extends SqliteStoreBase {
23
+ private initialized;
24
+ private ensureSchema;
25
+ listWorkstreams(projectId: string): Promise<WorkstreamSummary[]>;
26
+ getWorkstream(workstreamId: string): Promise<WorkstreamDetail | null>;
27
+ upsertWorkstream(input: Partial<WorkstreamSummary> & Pick<WorkstreamSummary, 'projectId' | 'title'>): Promise<{
28
+ events: WorkstreamEvent[];
29
+ id: string;
30
+ projectId: string;
31
+ title: string;
32
+ summary: string | null;
33
+ state: WorkstreamState;
34
+ branchName: string | null;
35
+ branchRef: string | null;
36
+ owner: string | null;
37
+ linkedItems: LinkedProjectRecordRef[];
38
+ verificationStatus: "completed" | "failed" | "waiting" | null;
39
+ verificationSummary: string | null;
40
+ lastSaveAt: string | null;
41
+ lastStageAt: string | null;
42
+ archivedAt: string | null;
43
+ createdAt: string;
44
+ updatedAt: string;
45
+ metadata?: Record<string, unknown>;
46
+ } | null>;
47
+ appendWorkstreamEvent(input: Pick<WorkstreamEvent, 'projectId' | 'workstreamId' | 'kind'> & Partial<WorkstreamEvent>): Promise<WorkstreamEvent | null>;
48
+ listReleases(projectId: string): Promise<ReleaseSummary[]>;
49
+ getRelease(releaseId: string): Promise<ReleaseDetail | null>;
50
+ upsertRelease(input: Partial<ReleaseSummary> & Pick<ReleaseSummary, 'projectId' | 'version'> & {
51
+ items?: ReleaseDetail['items'];
52
+ }): Promise<ReleaseDetail | null>;
53
+ listSharePackages(projectId: string): Promise<SharePackageStatus[]>;
54
+ getSharePackage(packageId: string): Promise<SharePackageStatus | null>;
55
+ upsertSharePackage(input: Partial<SharePackageStatus> & Pick<SharePackageStatus, 'projectId' | 'kind' | 'title'>): Promise<SharePackageStatus | null>;
56
+ }
@@ -0,0 +1,482 @@
1
+ import crypto from "node:crypto";
2
+ import { SqliteStoreBase, nowIso, toSqlValue } from "./helpers.js";
3
+ function parseJson(value, fallback) {
4
+ if (typeof value !== "string" || !value.trim()) {
5
+ return fallback;
6
+ }
7
+ try {
8
+ return JSON.parse(value);
9
+ } catch {
10
+ return fallback;
11
+ }
12
+ }
13
+ function stringify(value) {
14
+ return JSON.stringify(value ?? {});
15
+ }
16
+ function linkedItemsFromRow(row) {
17
+ return parseJson(row.linked_items_json, []);
18
+ }
19
+ function workstreamFromRow(row) {
20
+ return {
21
+ id: String(row.id ?? ""),
22
+ projectId: String(row.project_id ?? ""),
23
+ title: String(row.title ?? ""),
24
+ summary: row.summary === null || row.summary === void 0 ? null : String(row.summary),
25
+ state: String(row.state ?? "drafting"),
26
+ branchName: row.branch_name === null || row.branch_name === void 0 ? null : String(row.branch_name),
27
+ branchRef: row.branch_ref === null || row.branch_ref === void 0 ? null : String(row.branch_ref),
28
+ owner: row.owner === null || row.owner === void 0 ? null : String(row.owner),
29
+ linkedItems: linkedItemsFromRow(row),
30
+ verificationStatus: row.verification_status === null || row.verification_status === void 0 ? null : String(row.verification_status),
31
+ verificationSummary: row.verification_summary === null || row.verification_summary === void 0 ? null : String(row.verification_summary),
32
+ lastSaveAt: row.last_save_at === null || row.last_save_at === void 0 ? null : String(row.last_save_at),
33
+ lastStageAt: row.last_stage_at === null || row.last_stage_at === void 0 ? null : String(row.last_stage_at),
34
+ archivedAt: row.archived_at === null || row.archived_at === void 0 ? null : String(row.archived_at),
35
+ createdAt: String(row.created_at ?? nowIso()),
36
+ updatedAt: String(row.updated_at ?? nowIso()),
37
+ metadata: parseJson(row.metadata_json, {})
38
+ };
39
+ }
40
+ function workstreamEventFromRow(row) {
41
+ return {
42
+ id: String(row.id ?? ""),
43
+ workstreamId: String(row.workstream_id ?? ""),
44
+ projectId: String(row.project_id ?? ""),
45
+ kind: String(row.kind ?? ""),
46
+ summary: row.summary === null || row.summary === void 0 ? null : String(row.summary),
47
+ data: parseJson(row.data_json, {}),
48
+ createdAt: String(row.created_at ?? nowIso())
49
+ };
50
+ }
51
+ function releaseSummaryFromRow(row) {
52
+ return {
53
+ id: String(row.id ?? ""),
54
+ projectId: String(row.project_id ?? ""),
55
+ version: String(row.version ?? ""),
56
+ title: row.title === null || row.title === void 0 ? null : String(row.title),
57
+ state: String(row.state ?? "drafting"),
58
+ summary: row.summary === null || row.summary === void 0 ? null : String(row.summary),
59
+ workstreamIds: parseJson(row.workstream_ids_json, []),
60
+ releaseTag: row.release_tag === null || row.release_tag === void 0 ? null : String(row.release_tag),
61
+ commitSha: row.commit_sha === null || row.commit_sha === void 0 ? null : String(row.commit_sha),
62
+ publishedAt: row.published_at === null || row.published_at === void 0 ? null : String(row.published_at),
63
+ rolledBackAt: row.rolled_back_at === null || row.rolled_back_at === void 0 ? null : String(row.rolled_back_at),
64
+ createdAt: String(row.created_at ?? nowIso()),
65
+ updatedAt: String(row.updated_at ?? nowIso()),
66
+ metadata: parseJson(row.metadata_json, {})
67
+ };
68
+ }
69
+ function sharePackageFromRow(row) {
70
+ return {
71
+ id: String(row.id ?? ""),
72
+ projectId: String(row.project_id ?? ""),
73
+ kind: String(row.kind ?? "export"),
74
+ state: String(row.state ?? "draft"),
75
+ title: String(row.title ?? ""),
76
+ summary: row.summary === null || row.summary === void 0 ? null : String(row.summary),
77
+ version: row.version === null || row.version === void 0 ? null : String(row.version),
78
+ outputPath: row.output_path === null || row.output_path === void 0 ? null : String(row.output_path),
79
+ artifactKey: row.artifact_key === null || row.artifact_key === void 0 ? null : String(row.artifact_key),
80
+ manifestKey: row.manifest_key === null || row.manifest_key === void 0 ? null : String(row.manifest_key),
81
+ publishedItemId: row.published_item_id === null || row.published_item_id === void 0 ? null : String(row.published_item_id),
82
+ lastError: row.last_error === null || row.last_error === void 0 ? null : String(row.last_error),
83
+ createdAt: String(row.created_at ?? nowIso()),
84
+ updatedAt: String(row.updated_at ?? nowIso()),
85
+ metadata: parseJson(row.metadata_json, {})
86
+ };
87
+ }
88
+ class MemoryKnowledgeCoopStore {
89
+ workstreams = /* @__PURE__ */ new Map();
90
+ workstreamEvents = /* @__PURE__ */ new Map();
91
+ releases = /* @__PURE__ */ new Map();
92
+ releaseItems = /* @__PURE__ */ new Map();
93
+ packages = /* @__PURE__ */ new Map();
94
+ listWorkstreams(projectId) {
95
+ return [...this.workstreams.values()].filter((entry) => entry.projectId === projectId).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
96
+ }
97
+ getWorkstream(workstreamId) {
98
+ const workstream = this.workstreams.get(workstreamId);
99
+ if (!workstream) return null;
100
+ return {
101
+ ...workstream,
102
+ events: [...this.workstreamEvents.get(workstreamId) ?? []]
103
+ };
104
+ }
105
+ upsertWorkstream(input) {
106
+ const timestamp = nowIso();
107
+ const id = input.id ?? crypto.randomUUID();
108
+ const existing = this.workstreams.get(id);
109
+ const next = {
110
+ id,
111
+ projectId: input.projectId,
112
+ title: input.title,
113
+ summary: input.summary ?? existing?.summary ?? null,
114
+ state: input.state ?? existing?.state ?? "drafting",
115
+ branchName: input.branchName ?? existing?.branchName ?? null,
116
+ branchRef: input.branchRef ?? existing?.branchRef ?? null,
117
+ owner: input.owner ?? existing?.owner ?? null,
118
+ linkedItems: input.linkedItems ?? existing?.linkedItems ?? [],
119
+ verificationStatus: input.verificationStatus ?? existing?.verificationStatus ?? null,
120
+ verificationSummary: input.verificationSummary ?? existing?.verificationSummary ?? null,
121
+ lastSaveAt: input.lastSaveAt ?? existing?.lastSaveAt ?? null,
122
+ lastStageAt: input.lastStageAt ?? existing?.lastStageAt ?? null,
123
+ archivedAt: input.archivedAt ?? existing?.archivedAt ?? null,
124
+ createdAt: existing?.createdAt ?? timestamp,
125
+ updatedAt: timestamp,
126
+ metadata: input.metadata ?? existing?.metadata ?? {}
127
+ };
128
+ this.workstreams.set(id, next);
129
+ return next;
130
+ }
131
+ appendWorkstreamEvent(input) {
132
+ const event = {
133
+ id: input.id ?? crypto.randomUUID(),
134
+ projectId: input.projectId,
135
+ workstreamId: input.workstreamId,
136
+ kind: input.kind,
137
+ summary: input.summary ?? null,
138
+ data: input.data ?? {},
139
+ createdAt: input.createdAt ?? nowIso()
140
+ };
141
+ const events = this.workstreamEvents.get(input.workstreamId) ?? [];
142
+ events.push(event);
143
+ this.workstreamEvents.set(input.workstreamId, events);
144
+ return event;
145
+ }
146
+ listReleases(projectId) {
147
+ return [...this.releases.values()].filter((entry) => entry.projectId === projectId).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
148
+ }
149
+ getRelease(releaseId) {
150
+ const release = this.releases.get(releaseId);
151
+ if (!release) return null;
152
+ return {
153
+ ...release,
154
+ items: [...this.releaseItems.get(releaseId) ?? []]
155
+ };
156
+ }
157
+ upsertRelease(input) {
158
+ const timestamp = nowIso();
159
+ const id = input.id ?? crypto.randomUUID();
160
+ const existing = this.releases.get(id);
161
+ const next = {
162
+ id,
163
+ projectId: input.projectId,
164
+ version: input.version,
165
+ title: input.title ?? existing?.title ?? null,
166
+ state: input.state ?? existing?.state ?? "drafting",
167
+ summary: input.summary ?? existing?.summary ?? null,
168
+ workstreamIds: input.workstreamIds ?? existing?.workstreamIds ?? [],
169
+ releaseTag: input.releaseTag ?? existing?.releaseTag ?? null,
170
+ commitSha: input.commitSha ?? existing?.commitSha ?? null,
171
+ publishedAt: input.publishedAt ?? existing?.publishedAt ?? null,
172
+ rolledBackAt: input.rolledBackAt ?? existing?.rolledBackAt ?? null,
173
+ createdAt: existing?.createdAt ?? timestamp,
174
+ updatedAt: timestamp,
175
+ metadata: input.metadata ?? existing?.metadata ?? {}
176
+ };
177
+ this.releases.set(id, next);
178
+ if (input.items) {
179
+ this.releaseItems.set(id, [...input.items]);
180
+ }
181
+ return this.getRelease(id);
182
+ }
183
+ listSharePackages(projectId) {
184
+ return [...this.packages.values()].filter((entry) => entry.projectId === projectId).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
185
+ }
186
+ getSharePackage(packageId) {
187
+ return this.packages.get(packageId) ?? null;
188
+ }
189
+ upsertSharePackage(input) {
190
+ const timestamp = nowIso();
191
+ const id = input.id ?? crypto.randomUUID();
192
+ const existing = this.packages.get(id);
193
+ const next = {
194
+ id,
195
+ projectId: input.projectId,
196
+ kind: input.kind,
197
+ state: input.state ?? existing?.state ?? "draft",
198
+ title: input.title,
199
+ summary: input.summary ?? existing?.summary ?? null,
200
+ version: input.version ?? existing?.version ?? null,
201
+ outputPath: input.outputPath ?? existing?.outputPath ?? null,
202
+ artifactKey: input.artifactKey ?? existing?.artifactKey ?? null,
203
+ manifestKey: input.manifestKey ?? existing?.manifestKey ?? null,
204
+ publishedItemId: input.publishedItemId ?? existing?.publishedItemId ?? null,
205
+ lastError: input.lastError ?? existing?.lastError ?? null,
206
+ createdAt: existing?.createdAt ?? timestamp,
207
+ updatedAt: timestamp,
208
+ metadata: input.metadata ?? existing?.metadata ?? {}
209
+ };
210
+ this.packages.set(id, next);
211
+ return next;
212
+ }
213
+ }
214
+ class SqliteKnowledgeCoopStore extends SqliteStoreBase {
215
+ initialized = false;
216
+ async ensureSchema() {
217
+ if (this.initialized) return;
218
+ const statements = [
219
+ `CREATE TABLE IF NOT EXISTS project_workstreams (
220
+ id TEXT PRIMARY KEY,
221
+ project_id TEXT NOT NULL,
222
+ title TEXT NOT NULL,
223
+ summary TEXT,
224
+ state TEXT NOT NULL,
225
+ branch_name TEXT,
226
+ branch_ref TEXT,
227
+ owner TEXT,
228
+ linked_items_json TEXT NOT NULL DEFAULT '[]',
229
+ verification_status TEXT,
230
+ verification_summary TEXT,
231
+ last_save_at TEXT,
232
+ last_stage_at TEXT,
233
+ archived_at TEXT,
234
+ metadata_json TEXT NOT NULL DEFAULT '{}',
235
+ created_at TEXT NOT NULL,
236
+ updated_at TEXT NOT NULL
237
+ )`,
238
+ `CREATE INDEX IF NOT EXISTS idx_project_workstreams_project_updated
239
+ ON project_workstreams(project_id, updated_at DESC)`,
240
+ `CREATE TABLE IF NOT EXISTS project_workstream_events (
241
+ id TEXT PRIMARY KEY,
242
+ workstream_id TEXT NOT NULL,
243
+ project_id TEXT NOT NULL,
244
+ kind TEXT NOT NULL,
245
+ summary TEXT,
246
+ data_json TEXT NOT NULL DEFAULT '{}',
247
+ created_at TEXT NOT NULL
248
+ )`,
249
+ `CREATE INDEX IF NOT EXISTS idx_project_workstream_events_workstream_created
250
+ ON project_workstream_events(workstream_id, created_at ASC)`,
251
+ `CREATE TABLE IF NOT EXISTS project_releases (
252
+ id TEXT PRIMARY KEY,
253
+ project_id TEXT NOT NULL,
254
+ version TEXT NOT NULL,
255
+ title TEXT,
256
+ state TEXT NOT NULL,
257
+ summary TEXT,
258
+ workstream_ids_json TEXT NOT NULL DEFAULT '[]',
259
+ release_tag TEXT,
260
+ commit_sha TEXT,
261
+ published_at TEXT,
262
+ rolled_back_at TEXT,
263
+ metadata_json TEXT NOT NULL DEFAULT '{}',
264
+ created_at TEXT NOT NULL,
265
+ updated_at TEXT NOT NULL
266
+ )`,
267
+ `CREATE INDEX IF NOT EXISTS idx_project_releases_project_updated
268
+ ON project_releases(project_id, updated_at DESC)`,
269
+ `CREATE TABLE IF NOT EXISTS project_release_items (
270
+ id TEXT PRIMARY KEY,
271
+ release_id TEXT NOT NULL,
272
+ workstream_id TEXT,
273
+ model TEXT,
274
+ record_id TEXT,
275
+ summary TEXT,
276
+ metadata_json TEXT NOT NULL DEFAULT '{}',
277
+ created_at TEXT NOT NULL
278
+ )`,
279
+ `CREATE INDEX IF NOT EXISTS idx_project_release_items_release_created
280
+ ON project_release_items(release_id, created_at ASC)`,
281
+ `CREATE TABLE IF NOT EXISTS project_share_packages (
282
+ id TEXT PRIMARY KEY,
283
+ project_id TEXT NOT NULL,
284
+ kind TEXT NOT NULL,
285
+ state TEXT NOT NULL,
286
+ title TEXT NOT NULL,
287
+ summary TEXT,
288
+ version TEXT,
289
+ output_path TEXT,
290
+ artifact_key TEXT,
291
+ manifest_key TEXT,
292
+ published_item_id TEXT,
293
+ last_error TEXT,
294
+ metadata_json TEXT NOT NULL DEFAULT '{}',
295
+ created_at TEXT NOT NULL,
296
+ updated_at TEXT NOT NULL
297
+ )`,
298
+ `CREATE INDEX IF NOT EXISTS idx_project_share_packages_project_updated
299
+ ON project_share_packages(project_id, updated_at DESC)`
300
+ ];
301
+ for (const statement of statements) {
302
+ await this.execute(statement);
303
+ }
304
+ this.initialized = true;
305
+ }
306
+ async listWorkstreams(projectId) {
307
+ await this.ensureSchema();
308
+ const rows = await this.selectAll(
309
+ `SELECT * FROM project_workstreams WHERE project_id = ${toSqlValue(projectId)} ORDER BY updated_at DESC`
310
+ );
311
+ return rows.map(workstreamFromRow);
312
+ }
313
+ async getWorkstream(workstreamId) {
314
+ await this.ensureSchema();
315
+ const row = await this.selectFirst(`SELECT * FROM project_workstreams WHERE id = ${toSqlValue(workstreamId)} LIMIT 1`);
316
+ if (!row) return null;
317
+ const eventRows = await this.selectAll(`SELECT * FROM project_workstream_events WHERE workstream_id = ${toSqlValue(workstreamId)} ORDER BY created_at ASC`);
318
+ return {
319
+ ...workstreamFromRow(row),
320
+ events: eventRows.map(workstreamEventFromRow)
321
+ };
322
+ }
323
+ async upsertWorkstream(input) {
324
+ await this.ensureSchema();
325
+ const id = input.id ?? crypto.randomUUID();
326
+ const timestamp = nowIso();
327
+ await this.execute(
328
+ `INSERT OR REPLACE INTO project_workstreams (
329
+ id, project_id, title, summary, state, branch_name, branch_ref, owner, linked_items_json, verification_status, verification_summary,
330
+ last_save_at, last_stage_at, archived_at, metadata_json, created_at, updated_at
331
+ ) VALUES (
332
+ ${toSqlValue(id)},
333
+ ${toSqlValue(input.projectId)},
334
+ ${toSqlValue(input.title)},
335
+ ${toSqlValue(input.summary ?? null)},
336
+ ${toSqlValue(input.state ?? "drafting")},
337
+ ${toSqlValue(input.branchName ?? null)},
338
+ ${toSqlValue(input.branchRef ?? null)},
339
+ ${toSqlValue(input.owner ?? null)},
340
+ ${toSqlValue(JSON.stringify(input.linkedItems ?? []))},
341
+ ${toSqlValue(input.verificationStatus ?? null)},
342
+ ${toSqlValue(input.verificationSummary ?? null)},
343
+ ${toSqlValue(input.lastSaveAt ?? null)},
344
+ ${toSqlValue(input.lastStageAt ?? null)},
345
+ ${toSqlValue(input.archivedAt ?? null)},
346
+ ${toSqlValue(stringify(input.metadata ?? {}))},
347
+ COALESCE((SELECT created_at FROM project_workstreams WHERE id = ${toSqlValue(id)}), ${toSqlValue(timestamp)}),
348
+ ${toSqlValue(timestamp)}
349
+ )`
350
+ );
351
+ const detail = await this.getWorkstream(id);
352
+ return detail ? { ...detail } : null;
353
+ }
354
+ async appendWorkstreamEvent(input) {
355
+ await this.ensureSchema();
356
+ const id = input.id ?? crypto.randomUUID();
357
+ await this.execute(
358
+ `INSERT INTO project_workstream_events (
359
+ id, workstream_id, project_id, kind, summary, data_json, created_at
360
+ ) VALUES (
361
+ ${toSqlValue(id)},
362
+ ${toSqlValue(input.workstreamId)},
363
+ ${toSqlValue(input.projectId)},
364
+ ${toSqlValue(input.kind)},
365
+ ${toSqlValue(input.summary ?? null)},
366
+ ${toSqlValue(stringify(input.data ?? {}))},
367
+ ${toSqlValue(input.createdAt ?? nowIso())}
368
+ )`
369
+ );
370
+ const row = await this.selectFirst(`SELECT * FROM project_workstream_events WHERE id = ${toSqlValue(id)} LIMIT 1`);
371
+ return row ? workstreamEventFromRow(row) : null;
372
+ }
373
+ async listReleases(projectId) {
374
+ await this.ensureSchema();
375
+ const rows = await this.selectAll(`SELECT * FROM project_releases WHERE project_id = ${toSqlValue(projectId)} ORDER BY updated_at DESC`);
376
+ return rows.map(releaseSummaryFromRow);
377
+ }
378
+ async getRelease(releaseId) {
379
+ await this.ensureSchema();
380
+ const row = await this.selectFirst(`SELECT * FROM project_releases WHERE id = ${toSqlValue(releaseId)} LIMIT 1`);
381
+ if (!row) return null;
382
+ const items = await this.selectAll(`SELECT * FROM project_release_items WHERE release_id = ${toSqlValue(releaseId)} ORDER BY created_at ASC`);
383
+ return {
384
+ ...releaseSummaryFromRow(row),
385
+ items: items.map((item) => ({
386
+ id: String(item.id ?? ""),
387
+ workstreamId: item.workstream_id === null || item.workstream_id === void 0 ? null : String(item.workstream_id),
388
+ model: item.model === null || item.model === void 0 ? null : String(item.model),
389
+ recordId: item.record_id === null || item.record_id === void 0 ? null : String(item.record_id),
390
+ summary: item.summary === null || item.summary === void 0 ? null : String(item.summary),
391
+ metadata: parseJson(item.metadata_json, {}),
392
+ createdAt: String(item.created_at ?? nowIso())
393
+ }))
394
+ };
395
+ }
396
+ async upsertRelease(input) {
397
+ await this.ensureSchema();
398
+ const id = input.id ?? crypto.randomUUID();
399
+ const timestamp = nowIso();
400
+ await this.execute(
401
+ `INSERT OR REPLACE INTO project_releases (
402
+ id, project_id, version, title, state, summary, workstream_ids_json, release_tag, commit_sha, published_at, rolled_back_at, metadata_json, created_at, updated_at
403
+ ) VALUES (
404
+ ${toSqlValue(id)},
405
+ ${toSqlValue(input.projectId)},
406
+ ${toSqlValue(input.version)},
407
+ ${toSqlValue(input.title ?? null)},
408
+ ${toSqlValue(input.state ?? "drafting")},
409
+ ${toSqlValue(input.summary ?? null)},
410
+ ${toSqlValue(JSON.stringify(input.workstreamIds ?? []))},
411
+ ${toSqlValue(input.releaseTag ?? null)},
412
+ ${toSqlValue(input.commitSha ?? null)},
413
+ ${toSqlValue(input.publishedAt ?? null)},
414
+ ${toSqlValue(input.rolledBackAt ?? null)},
415
+ ${toSqlValue(stringify(input.metadata ?? {}))},
416
+ COALESCE((SELECT created_at FROM project_releases WHERE id = ${toSqlValue(id)}), ${toSqlValue(timestamp)}),
417
+ ${toSqlValue(timestamp)}
418
+ )`
419
+ );
420
+ if (input.items) {
421
+ await this.execute(`DELETE FROM project_release_items WHERE release_id = ${toSqlValue(id)}`);
422
+ for (const item of input.items) {
423
+ await this.execute(
424
+ `INSERT INTO project_release_items (
425
+ id, release_id, workstream_id, model, record_id, summary, metadata_json, created_at
426
+ ) VALUES (
427
+ ${toSqlValue(item.id ?? crypto.randomUUID())},
428
+ ${toSqlValue(id)},
429
+ ${toSqlValue(item.workstreamId ?? null)},
430
+ ${toSqlValue(item.model ?? null)},
431
+ ${toSqlValue(item.recordId ?? null)},
432
+ ${toSqlValue(item.summary ?? null)},
433
+ ${toSqlValue(stringify(item.metadata ?? {}))},
434
+ ${toSqlValue(item.createdAt ?? timestamp)}
435
+ )`
436
+ );
437
+ }
438
+ }
439
+ return this.getRelease(id);
440
+ }
441
+ async listSharePackages(projectId) {
442
+ await this.ensureSchema();
443
+ const rows = await this.selectAll(`SELECT * FROM project_share_packages WHERE project_id = ${toSqlValue(projectId)} ORDER BY updated_at DESC`);
444
+ return rows.map(sharePackageFromRow);
445
+ }
446
+ async getSharePackage(packageId) {
447
+ await this.ensureSchema();
448
+ const row = await this.selectFirst(`SELECT * FROM project_share_packages WHERE id = ${toSqlValue(packageId)} LIMIT 1`);
449
+ return row ? sharePackageFromRow(row) : null;
450
+ }
451
+ async upsertSharePackage(input) {
452
+ await this.ensureSchema();
453
+ const id = input.id ?? crypto.randomUUID();
454
+ const timestamp = nowIso();
455
+ await this.execute(
456
+ `INSERT OR REPLACE INTO project_share_packages (
457
+ id, project_id, kind, state, title, summary, version, output_path, artifact_key, manifest_key, published_item_id, last_error, metadata_json, created_at, updated_at
458
+ ) VALUES (
459
+ ${toSqlValue(id)},
460
+ ${toSqlValue(input.projectId)},
461
+ ${toSqlValue(input.kind)},
462
+ ${toSqlValue(input.state ?? "draft")},
463
+ ${toSqlValue(input.title)},
464
+ ${toSqlValue(input.summary ?? null)},
465
+ ${toSqlValue(input.version ?? null)},
466
+ ${toSqlValue(input.outputPath ?? null)},
467
+ ${toSqlValue(input.artifactKey ?? null)},
468
+ ${toSqlValue(input.manifestKey ?? null)},
469
+ ${toSqlValue(input.publishedItemId ?? null)},
470
+ ${toSqlValue(input.lastError ?? null)},
471
+ ${toSqlValue(stringify(input.metadata ?? {}))},
472
+ COALESCE((SELECT created_at FROM project_share_packages WHERE id = ${toSqlValue(id)}), ${toSqlValue(timestamp)}),
473
+ ${toSqlValue(timestamp)}
474
+ )`
475
+ );
476
+ return this.getSharePackage(id);
477
+ }
478
+ }
479
+ export {
480
+ MemoryKnowledgeCoopStore,
481
+ SqliteKnowledgeCoopStore
482
+ };
@@ -11,11 +11,15 @@
11
11
  "setup": "npm install",
12
12
  "setup:ci": "npm ci",
13
13
  "config": "treeseed config",
14
+ "preflight": "treeseed preflight",
14
15
  "dev": "treeseed dev",
16
+ "dev:web": "treeseed dev:web",
17
+ "dev:api": "treeseed dev:api",
15
18
  "dev:watch": "treeseed dev --watch",
16
19
  "check": "treeseed check",
17
- "build": "treeseed build",
18
- "deploy": "treeseed deploy",
20
+ "build:web": "treeseed build",
21
+ "build": "npm run build:web",
22
+ "deploy": "treeseed release",
19
23
  "preview": "treeseed preview",
20
24
  "sync": "treeseed sync",
21
25
  "verify": "npm run check && npm run build"
@@ -0,0 +1,4 @@
1
+ import { createRailwayTreeseedApiServer } from '@treeseed/core/api';
2
+
3
+ const server = await createRailwayTreeseedApiServer();
4
+ console.log(`Treeseed project API listening on ${server.url}`);