@treeseed/sdk 0.6.38 → 0.6.40

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 (46) hide show
  1. package/dist/capacity.d.ts +53 -0
  2. package/dist/capacity.js +100 -0
  3. package/dist/control-plane-client.d.ts +41 -1
  4. package/dist/control-plane-client.js +154 -0
  5. package/dist/control-plane.d.ts +6 -1
  6. package/dist/control-plane.js +39 -2
  7. package/dist/d1-store.d.ts +63 -1
  8. package/dist/d1-store.js +190 -1
  9. package/dist/index.d.ts +3 -1
  10. package/dist/index.js +12 -0
  11. package/dist/operations/services/config-runtime.js +5 -3
  12. package/dist/operations/services/deploy.js +3 -2
  13. package/dist/operations/services/github-api.d.ts +2 -1
  14. package/dist/operations/services/github-api.js +35 -26
  15. package/dist/operations/services/knowledge-coop-launch.js +5 -28
  16. package/dist/operations/services/package-reference-policy.d.ts +68 -0
  17. package/dist/operations/services/package-reference-policy.js +135 -0
  18. package/dist/operations/services/project-platform.d.ts +14 -0
  19. package/dist/operations/services/project-platform.js +3 -2
  20. package/dist/operations/services/railway-api.d.ts +33 -0
  21. package/dist/operations/services/railway-api.js +273 -0
  22. package/dist/operations/services/railway-deploy.d.ts +22 -0
  23. package/dist/operations/services/railway-deploy.js +81 -19
  24. package/dist/operations/services/release-candidate.d.ts +2 -0
  25. package/dist/operations/services/release-candidate.js +28 -0
  26. package/dist/operations/services/runtime-tools.js +1 -1
  27. package/dist/operations-registry.js +1 -0
  28. package/dist/reconcile/bootstrap-systems.js +1 -1
  29. package/dist/reconcile/builtin-adapters.js +5 -9
  30. package/dist/reconcile/contracts.d.ts +1 -1
  31. package/dist/reconcile/desired-state.js +9 -17
  32. package/dist/reconcile/state.js +4 -4
  33. package/dist/reconcile/units.js +4 -8
  34. package/dist/sdk-types.d.ts +566 -3
  35. package/dist/sdk.d.ts +12 -1
  36. package/dist/sdk.js +44 -0
  37. package/dist/stores/operational-store.d.ts +12 -1
  38. package/dist/stores/operational-store.js +283 -5
  39. package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +5 -24
  40. package/dist/types/agents.d.ts +27 -0
  41. package/dist/workflow/operations.d.ts +94 -2
  42. package/dist/workflow/operations.js +90 -32
  43. package/dist/workflow-state.js +3 -5
  44. package/dist/workflow.d.ts +8 -1
  45. package/dist/workflow.js +6 -0
  46. package/package.json +5 -1
package/dist/d1-store.js CHANGED
@@ -54,6 +54,11 @@ class MemoryAgentDatabase {
54
54
  graphRuns = /* @__PURE__ */ new Map();
55
55
  reports = /* @__PURE__ */ new Map();
56
56
  workPolicies = /* @__PURE__ */ new Map();
57
+ workdayRequests = /* @__PURE__ */ new Map();
58
+ workdayManagerLeases = /* @__PURE__ */ new Map();
59
+ workerRunners = /* @__PURE__ */ new Map();
60
+ repositoryClaims = /* @__PURE__ */ new Map();
61
+ runnerScaleDecisions = /* @__PURE__ */ new Map();
57
62
  priorityOverrides = /* @__PURE__ */ new Map();
58
63
  prioritySnapshots = /* @__PURE__ */ new Map();
59
64
  taskCreditLedger = /* @__PURE__ */ new Map();
@@ -761,11 +766,19 @@ class MemoryAgentDatabase {
761
766
  return this.workPolicies.get(`${projectId}:${environment}`) ?? null;
762
767
  }
763
768
  async upsertWorkPolicy(request) {
769
+ const dailyCreditBudget = Number(request.dailyCreditBudget ?? request.dailyTaskCreditBudget ?? 0);
764
770
  const policy = {
765
771
  projectId: request.projectId,
766
772
  environment: request.environment,
767
773
  schedule: request.schedule,
768
- dailyTaskCreditBudget: request.dailyTaskCreditBudget,
774
+ enabled: request.enabled ?? true,
775
+ startCron: request.startCron ?? "0 9 * * 1-5",
776
+ durationMinutes: Number(request.durationMinutes ?? 480),
777
+ maxRunners: Number(request.maxRunners ?? request.autoscale.maxWorkers ?? 1),
778
+ maxWorkersPerRunner: Number(request.maxWorkersPerRunner ?? 4),
779
+ dailyCreditBudget,
780
+ closeoutGraceMinutes: Number(request.closeoutGraceMinutes ?? 15),
781
+ dailyTaskCreditBudget: dailyCreditBudget,
769
782
  maxQueuedTasks: request.maxQueuedTasks,
770
783
  maxQueuedCredits: request.maxQueuedCredits,
771
784
  autoscale: request.autoscale,
@@ -775,6 +788,149 @@ class MemoryAgentDatabase {
775
788
  this.workPolicies.set(`${request.projectId}:${request.environment}`, policy);
776
789
  return policy;
777
790
  }
791
+ async createWorkdayRequest(request) {
792
+ const timestamp = nowIso();
793
+ const record = {
794
+ id: request.id ?? crypto.randomUUID(),
795
+ projectId: request.projectId,
796
+ environment: request.environment,
797
+ type: request.type,
798
+ state: request.state ?? "pending",
799
+ workDayId: request.workDayId ?? null,
800
+ requestedBy: request.requestedBy ?? null,
801
+ reason: request.reason ?? null,
802
+ payload: request.payload ?? {},
803
+ metadata: request.metadata ?? {},
804
+ createdAt: timestamp,
805
+ updatedAt: timestamp
806
+ };
807
+ this.workdayRequests.set(record.id, record);
808
+ return record;
809
+ }
810
+ async listWorkdayRequests(projectId, environment, state) {
811
+ return [...this.workdayRequests.values()].filter((entry) => entry.projectId === projectId && entry.environment === environment).filter((entry) => !state || entry.state === state).sort((left, right) => left.createdAt.localeCompare(right.createdAt));
812
+ }
813
+ async claimWorkdayManagerLease(request) {
814
+ const timestamp = request.now ?? nowIso();
815
+ const nowMs = Date.parse(timestamp);
816
+ const staleAfterMs = (request.staleAfterSeconds ?? request.ttlSeconds) * 1e3;
817
+ const existing = [...this.workdayManagerLeases.values()].find((entry) => entry.projectId === request.projectId && entry.environment === request.environment && entry.state === "active");
818
+ if (existing && existing.managerId !== request.managerId) {
819
+ const heartbeatMs = Date.parse(existing.heartbeatAt);
820
+ if (Number.isFinite(heartbeatMs) && Number.isFinite(nowMs) && nowMs - heartbeatMs <= staleAfterMs) {
821
+ return null;
822
+ }
823
+ }
824
+ const id = existing?.id ?? request.id ?? crypto.randomUUID();
825
+ const record = {
826
+ id,
827
+ projectId: request.projectId,
828
+ environment: request.environment,
829
+ workDayId: request.workDayId ?? existing?.workDayId ?? null,
830
+ managerId: request.managerId,
831
+ state: "active",
832
+ heartbeatAt: timestamp,
833
+ expiresAt: new Date(Date.parse(timestamp) + request.ttlSeconds * 1e3).toISOString(),
834
+ metadata: request.metadata ?? existing?.metadata ?? {},
835
+ createdAt: existing?.createdAt ?? timestamp,
836
+ updatedAt: timestamp
837
+ };
838
+ this.workdayManagerLeases.set(id, record);
839
+ return record;
840
+ }
841
+ async releaseWorkdayManagerLease(request) {
842
+ const existing = this.workdayManagerLeases.get(request.id);
843
+ if (!existing || existing.managerId !== request.managerId) return null;
844
+ const next = { ...existing, state: "released", updatedAt: nowIso() };
845
+ this.workdayManagerLeases.set(next.id, next);
846
+ return next;
847
+ }
848
+ async recordWorkerRunner(request) {
849
+ const timestamp = nowIso();
850
+ const id = request.id ?? `${request.projectId}:${request.environment}:${request.runnerId}`;
851
+ const activeLocalWorkers = Number(request.activeLocalWorkers ?? 0);
852
+ const maxLocalWorkers = Number(request.maxLocalWorkers ?? 4);
853
+ const record = {
854
+ id,
855
+ projectId: request.projectId,
856
+ environment: request.environment,
857
+ runnerId: request.runnerId,
858
+ runnerServiceName: request.runnerServiceName,
859
+ volumeIdentity: request.volumeIdentity,
860
+ state: request.state ?? "active",
861
+ maxLocalWorkers,
862
+ activeLocalWorkers,
863
+ availableCapacity: Math.max(0, maxLocalWorkers - activeLocalWorkers),
864
+ lastHeartbeatAt: timestamp,
865
+ claimedRepositoryIds: request.claimedRepositoryIds ?? [],
866
+ metadata: request.metadata ?? {},
867
+ createdAt: this.workerRunners.get(id)?.createdAt ?? timestamp,
868
+ updatedAt: timestamp
869
+ };
870
+ this.workerRunners.set(id, record);
871
+ return record;
872
+ }
873
+ async listWorkerRunners(projectId, environment) {
874
+ return [...this.workerRunners.values()].filter((entry) => entry.projectId === projectId && entry.environment === environment).sort((left, right) => left.runnerId.localeCompare(right.runnerId));
875
+ }
876
+ async recordRepositoryClaim(request) {
877
+ const timestamp = nowIso();
878
+ const id = request.id ?? `${request.projectId}:${request.repositoryId}:${request.runnerId}`;
879
+ const record = {
880
+ id,
881
+ projectId: request.projectId,
882
+ repositoryId: request.repositoryId,
883
+ runnerId: request.runnerId,
884
+ runnerServiceName: request.runnerServiceName,
885
+ volumeIdentity: request.volumeIdentity,
886
+ lastSeenCommit: request.lastSeenCommit ?? null,
887
+ lastTaskAt: request.lastTaskAt ?? timestamp,
888
+ claimState: request.claimState ?? "active",
889
+ metadata: request.metadata ?? {},
890
+ createdAt: this.repositoryClaims.get(id)?.createdAt ?? timestamp,
891
+ updatedAt: timestamp
892
+ };
893
+ this.repositoryClaims.set(id, record);
894
+ return record;
895
+ }
896
+ async listRepositoryClaims(projectId, repositoryId) {
897
+ return [...this.repositoryClaims.values()].filter((entry) => entry.projectId === projectId).filter((entry) => !repositoryId || entry.repositoryId === repositoryId).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
898
+ }
899
+ async recordRunnerScaleDecision(request) {
900
+ const record = {
901
+ id: request.id ?? crypto.randomUUID(),
902
+ projectId: request.projectId,
903
+ environment: request.environment,
904
+ workDayId: request.workDayId ?? null,
905
+ runnerId: request.runnerId ?? null,
906
+ runnerServiceName: request.runnerServiceName ?? null,
907
+ action: request.action,
908
+ reason: request.reason,
909
+ metadata: request.metadata ?? {},
910
+ createdAt: nowIso()
911
+ };
912
+ this.runnerScaleDecisions.set(record.id, record);
913
+ return record;
914
+ }
915
+ async listRunnerScaleDecisions(projectId, environment, workDayId) {
916
+ return [...this.runnerScaleDecisions.values()].filter((entry) => entry.projectId === projectId && entry.environment === environment).filter((entry) => !workDayId || entry.workDayId === workDayId).sort((left, right) => right.createdAt.localeCompare(left.createdAt));
917
+ }
918
+ async updateWorkDayGraph(request) {
919
+ const existing = this.workDays.get(request.id);
920
+ if (!existing) return null;
921
+ const summary = {
922
+ ...existing.summaryJson ? JSON.parse(existing.summaryJson) : {},
923
+ ...request.summaryPatch ?? {}
924
+ };
925
+ const next = {
926
+ ...existing,
927
+ graphVersion: request.graphVersion,
928
+ summaryJson: JSON.stringify(summary),
929
+ updatedAt: nowIso()
930
+ };
931
+ this.workDays.set(next.id, next);
932
+ return next;
933
+ }
778
934
  async listPriorityOverrides(projectId) {
779
935
  return [...this.priorityOverrides.values()].filter((entry) => entry.projectId === projectId);
780
936
  }
@@ -1244,6 +1400,39 @@ class CloudflareD1AgentDatabase {
1244
1400
  upsertWorkPolicy(request) {
1245
1401
  return this.operational.upsertWorkPolicy(request);
1246
1402
  }
1403
+ createWorkdayRequest(request) {
1404
+ return this.operational.createWorkdayRequest(request);
1405
+ }
1406
+ listWorkdayRequests(projectId, environment, state) {
1407
+ return this.operational.listWorkdayRequests(projectId, environment, state);
1408
+ }
1409
+ claimWorkdayManagerLease(request) {
1410
+ return this.operational.claimWorkdayManagerLease(request);
1411
+ }
1412
+ releaseWorkdayManagerLease(request) {
1413
+ return this.operational.releaseWorkdayManagerLease(request);
1414
+ }
1415
+ recordWorkerRunner(request) {
1416
+ return this.operational.recordWorkerRunner(request);
1417
+ }
1418
+ listWorkerRunners(projectId, environment) {
1419
+ return this.operational.listWorkerRunners(projectId, environment);
1420
+ }
1421
+ recordRepositoryClaim(request) {
1422
+ return this.operational.recordRepositoryClaim(request);
1423
+ }
1424
+ listRepositoryClaims(projectId, repositoryId) {
1425
+ return this.operational.listRepositoryClaims(projectId, repositoryId);
1426
+ }
1427
+ recordRunnerScaleDecision(request) {
1428
+ return this.operational.recordRunnerScaleDecision(request);
1429
+ }
1430
+ listRunnerScaleDecisions(projectId, environment, workDayId) {
1431
+ return this.operational.listRunnerScaleDecisions(projectId, environment, workDayId);
1432
+ }
1433
+ updateWorkDayGraph(request) {
1434
+ return this.operational.updateWorkDayGraph(request);
1435
+ }
1247
1436
  listPriorityOverrides(projectId) {
1248
1437
  return this.operational.listPriorityOverrides(projectId);
1249
1438
  }
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export { ContentGraphRuntime } from './graph.ts';
3
3
  export { projectConnectionModeFromHosting } from './sdk-types.ts';
4
4
  export { createControlPlaneReporter } from './control-plane.ts';
5
5
  export { ControlPlaneClient } from './control-plane-client.ts';
6
+ export { reservationHasCapacity, reserveCreditsForEstimate, scoreCapacityLane, selectBestCapacityLane, summarizeCapacityPlan, } from './capacity.ts';
6
7
  export { executeKnowledgeCoopManagedLaunch, validateKnowledgeCoopManagedLaunchPrerequisites, } from './operations/services/knowledge-coop-launch.ts';
7
8
  export { ensureRailwayEnvironment, ensureRailwayProject, ensureRailwayService, getRailwayAuthProfile, listRailwayEnvironments, listRailwayProjects, listRailwayServices, listRailwayVariables, railwayGraphqlRequest, resolveRailwayApiToken, resolveRailwayApiUrl, resolveRailwayWorkspace, resolveRailwayWorkspaceContext, upsertRailwayVariables, } from './operations/services/railway-api.ts';
8
9
  export { buildKnowledgeCoopKnowledgePackPackage, buildKnowledgeCoopTemplatePackage, importKnowledgeCoopKnowledgePack, } from './operations/services/knowledge-coop-packaging.ts';
@@ -30,10 +31,11 @@ export { TreeseedWorkflowSdk } from './workflow.ts';
30
31
  export * from './db/index.ts';
31
32
  export { collectTreeseedReconcileStatus, createTreeseedReconcileRegistry, deriveTreeseedDesiredUnits, destroyTreeseedTargetUnits, observeTreeseedUnits, planTreeseedReconciliation, reconcileTreeseedTarget, } from './reconcile/index.ts';
32
33
  export { getTreeseedVerifyDriverStatus, runTreeseedVerifyDriver } from './verification.ts';
33
- export type { KnowledgeCoopLaunchPreflightReport, KnowledgeCoopLaunchFailurePhase, KnowledgeCoopManagedLaunchInput, KnowledgeCoopManagedLaunchResult, AgentMessageKind, AgentMessageRecord, AgentStatusRecord, DirectBoardItemSummary, InboxItem, KnowledgeCoopJobStatus, LaunchProjectRequest, LaunchProjectResult, LinkedProjectRecordRef, ProjectConnectionStatus, ProjectOverviewSummary, ReleaseDetail, ReleaseState, ReleaseSummary, SharePackageState, SharePackageStatus, TeamCapability, TeamHomeSummary, TeamMemberSummary, WorkstreamDetail, WorkstreamEvent, WorkstreamState, WorkstreamSummary, SdkContentEntry, SdkDispatchCapability, SdkDispatchConfig, SdkDispatchCredentialSource, SdkDispatchExecutionClass, SdkDispatchNamespace, SdkDispatchPolicy, SdkDispatchRequest, SdkDispatchResult, SdkDispatchTarget, SdkCursorEntity, SdkFilterCondition, SdkFollowRequest, SdkGraphEdge, SdkGraphEdgeType, SdkGraphDslRelation, SdkGraphDslParseResult, SdkGraphModelConfig, SdkGraphNode, SdkGraphNodeType, SdkGraphPathExplanation, SdkGraphQueryStage, SdkGraphQueryView, SdkGraphQueryOptions, SdkGraphQueryRequest, SdkGraphQueryResult, SdkGraphRankingBuildInput, SdkGraphRankingDiagnostics, SdkGraphRankingIndex, SdkGraphRankingNodeResult, SdkGraphRankingProvider, SdkGraphRankingQueryRequest, SdkGraphRankingQueryResult, SdkGraphRankingSearchRequest, SdkGraphRefreshPayload, SdkGraphRefreshRequest, SdkGraphSearchOptions, SdkGraphSearchResult, SdkGraphSeed, SdkGraphSeedResolution, SdkGraphTraversalResult, SdkGraphWhereFilter, SdkContextPack, SdkContextPackRequest, SdkGetRequest, SdkJsonEnvelope, SdkLeaseEntity, SdkManagerContextPayload, SdkMessageEntity, SdkModelFieldBinding, SdkModelDefinition, SdkModelRegistry, SdkModelName, SdkMutationRequest, SdkOperation, SdkPickRequest, SdkPickResult, SdkQueueMessageEnvelope, SdkRunEntity, SdkSearchRequest, SdkTaskEntity, SdkTaskEventEntity, SdkTaskOutputEntity, SdkWorkDayEntity, SdkGraphRunEntity, SdkReportEntity, SdkSubscriptionEntity, SdkTemplateCatalogEntry, SdkTemplateCatalogPublisher, SdkTemplateCatalogResponse, SdkTemplateCatalogSource, SdkUpdateRequest, ProjectCapabilityGrant, ProjectConnection, ProjectConnectionMode, ProjectDeployment, ProjectDeploymentKind, ProjectDeploymentStatus, ProjectEnvironment, ProjectExecutionOwner, ProjectHosting, ProjectInfrastructureResource, ProjectInfrastructureResourceKind, ProjectInfrastructureResourceProvider, ProjectRunnerRegistrationState, RemoteJob, RemoteJobEvent, RemoteJobStatus, AgentPool, AgentPoolAutoscalePolicy, AgentPoolRegistration, AgentPoolScaleDecision, AgentPoolStatus, CatalogArtifactVersion, CatalogItem, CatalogItemFilters, CatalogItemOfferMode, ProjectEnvironmentName, ProjectWorkdaySummary, TreeseedHostingKind, TreeseedHostingRegistration, PriorityOverride, WorkdayWindow, WorkdaySchedule, TaskCreditWeight, TaskCreditBudget, WorkdayPolicy, PrioritySnapshotItem, PrioritySnapshot, TaskCreditLedgerEntry, ScaleDecision, TeamStorageLocator, TeamWebHost, TeamWebHostOwnership, TeamWebHostProvider, EncryptedWebHostPayload, UpsertAgentPoolRequest, UpsertCatalogArtifactVersionRequest, UpsertCatalogItemRequest, UpsertProjectEnvironmentRequest, UpsertProjectHostingRequest, UpsertProjectInfrastructureResourceRequest, UpsertTeamStorageLocatorRequest, UpsertTeamWebHostRequest, CreateProjectDeploymentRequest, RecordAgentPoolRegistrationRequest, WorkerPoolScaleResult, WorkerPoolScaler, } from './sdk-types.ts';
34
+ export type { KnowledgeCoopLaunchPreflightReport, KnowledgeCoopLaunchFailurePhase, KnowledgeCoopManagedLaunchInput, KnowledgeCoopManagedLaunchResult, AgentMessageKind, AgentMessageRecord, AgentStatusRecord, DirectBoardItemSummary, InboxItem, KnowledgeCoopJobStatus, LaunchProjectRequest, LaunchProjectResult, LinkedProjectRecordRef, ProjectConnectionStatus, ProjectOverviewSummary, ReleaseDetail, ReleaseState, ReleaseSummary, SharePackageState, SharePackageStatus, TeamCapability, TeamHomeSummary, TeamMemberSummary, WorkstreamDetail, WorkstreamEvent, WorkstreamState, WorkstreamSummary, SdkContentEntry, SdkDispatchCapability, SdkDispatchConfig, SdkDispatchCredentialSource, SdkDispatchExecutionClass, SdkDispatchNamespace, SdkDispatchPolicy, SdkDispatchRequest, SdkDispatchResult, SdkDispatchTarget, SdkCursorEntity, SdkFilterCondition, SdkFollowRequest, SdkGraphEdge, SdkGraphEdgeType, SdkGraphDslRelation, SdkGraphDslParseResult, SdkGraphModelConfig, SdkGraphNode, SdkGraphNodeType, SdkGraphPathExplanation, SdkGraphQueryStage, SdkGraphQueryView, SdkGraphQueryOptions, SdkGraphQueryRequest, SdkGraphQueryResult, SdkGraphRankingBuildInput, SdkGraphRankingDiagnostics, SdkGraphRankingIndex, SdkGraphRankingNodeResult, SdkGraphRankingProvider, SdkGraphRankingQueryRequest, SdkGraphRankingQueryResult, SdkGraphRankingSearchRequest, SdkGraphRefreshPayload, SdkGraphRefreshRequest, SdkGraphSearchOptions, SdkGraphSearchResult, SdkGraphSeed, SdkGraphSeedResolution, SdkGraphTraversalResult, SdkGraphWhereFilter, SdkContextPack, SdkContextPackRequest, SdkGetRequest, SdkJsonEnvelope, SdkLeaseEntity, SdkManagerContextPayload, SdkMessageEntity, SdkModelFieldBinding, SdkModelDefinition, SdkModelRegistry, SdkModelName, SdkMutationRequest, SdkOperation, SdkPickRequest, SdkPickResult, SdkQueueMessageEnvelope, SdkRunEntity, SdkSearchRequest, SdkTaskEntity, SdkTaskEventEntity, SdkTaskOutputEntity, SdkWorkDayEntity, SdkGraphRunEntity, SdkReportEntity, SdkSubscriptionEntity, SdkTemplateCatalogEntry, SdkTemplateCatalogPublisher, SdkTemplateCatalogResponse, SdkTemplateCatalogSource, SdkUpdateRequest, ProjectCapabilityGrant, ProjectConnection, ProjectConnectionMode, ProjectDeployment, ProjectDeploymentKind, ProjectDeploymentStatus, ProjectEnvironment, ProjectExecutionOwner, ProjectHosting, ProjectInfrastructureResource, ProjectInfrastructureResourceKind, ProjectInfrastructureResourceProvider, ProjectRunnerRegistrationState, RemoteJob, RemoteJobEvent, RemoteJobStatus, AgentPool, AgentPoolAutoscalePolicy, AgentPoolRegistration, AgentPoolScaleDecision, AgentPoolStatus, CatalogArtifactVersion, CatalogItem, CatalogItemFilters, CatalogItemOfferMode, ProjectEnvironmentName, ProjectWorkdaySummary, TreeseedHostingKind, TreeseedHostingRegistration, PriorityOverride, WorkdayWindow, WorkdaySchedule, WorkdayRequest, WorkdayManagerLease, WorkerRunner, WorkerRunnerState, RepositoryClaim, TaskCreditWeight, TaskCreditBudget, WorkdayPolicy, PrioritySnapshotItem, PrioritySnapshot, TaskCreditLedgerEntry, ApprovalRequest, CapacityBusinessModel, CapacityGrant, CapacityGrantScope, CapacityLedgerEntry, CapacityLaneUnit, CapacityPlan, CapacityProvider, CapacityProviderHost, CapacityProviderKind, CapacityProviderLane, CapacityReservation, CapacityRoutingDecision, CapacityTaskExecutionEnvelope, CreateApprovalRequestRequest, CreateCapacityReservationRequest, CreateCapacityRoutingDecisionRequest, CreateTaskEstimateRequest, CreateTaskUsageActualRequest, RecordCapacityUsageRequest, TaskEstimate, TaskEstimateProfile, TaskUsageActual, UpsertCapacityGrantRequest, UpsertCapacityProviderHostRequest, UpsertCapacityProviderLaneRequest, UpsertCapacityProviderRequest, ScaleDecision, RunnerScaleDecision, TeamStorageLocator, TeamWebHost, TeamWebHostOwnership, TeamWebHostProvider, EncryptedWebHostPayload, UpsertAgentPoolRequest, UpsertCatalogArtifactVersionRequest, UpsertCatalogItemRequest, UpsertProjectEnvironmentRequest, UpsertProjectHostingRequest, UpsertProjectInfrastructureResourceRequest, UpsertTeamStorageLocatorRequest, UpsertTeamWebHostRequest, CreateProjectDeploymentRequest, RecordAgentPoolRegistrationRequest, SdkCreateWorkdayRequest, SdkClaimWorkdayManagerLeaseRequest, SdkReleaseWorkdayManagerLeaseRequest, SdkRecordWorkerRunnerRequest, SdkRecordRepositoryClaimRequest, SdkRecordRunnerScaleDecisionRequest, SdkUpdateWorkDayGraphRequest, WorkerPoolScaleResult, WorkerPoolScaler, } from './sdk-types.ts';
34
35
  export type * from './knowledge-coop.ts';
35
36
  export type { ControlPlaneAgentPoolHeartbeat, ControlPlaneDeploymentReport, ControlPlaneEnvironmentReport, ControlPlaneReporter, ControlPlaneReporterKind, ControlPlaneResourceReport, ControlPlaneScaleDecisionReport, ControlPlaneWorkdaySummaryReport, } from './control-plane.ts';
36
37
  export type { ControlPlaneClientOptions } from './control-plane-client.ts';
38
+ export type { CapacityEstimateInput, CapacityLaneCandidate, CapacityLaneScore, } from './capacity.ts';
37
39
  export type { TreeseedFieldAliasBinding, TreeseedFieldAliasRegistry, } from './field-aliases.ts';
38
40
  export type * from './operations-types.ts';
39
41
  export type * from './workflow.ts';
package/dist/index.js CHANGED
@@ -3,6 +3,13 @@ import { ContentGraphRuntime } from "./graph.js";
3
3
  import { projectConnectionModeFromHosting } from "./sdk-types.js";
4
4
  import { createControlPlaneReporter } from "./control-plane.js";
5
5
  import { ControlPlaneClient } from "./control-plane-client.js";
6
+ import {
7
+ reservationHasCapacity,
8
+ reserveCreditsForEstimate,
9
+ scoreCapacityLane,
10
+ selectBestCapacityLane,
11
+ summarizeCapacityPlan
12
+ } from "./capacity.js";
6
13
  import {
7
14
  executeKnowledgeCoopManagedLaunch,
8
15
  validateKnowledgeCoopManagedLaunchPrerequisites
@@ -290,6 +297,8 @@ export {
290
297
  readPublishedOverlayManifest,
291
298
  reconcileTreeseedTarget,
292
299
  removeMarketProfile,
300
+ reservationHasCapacity,
301
+ reserveCreditsForEstimate,
293
302
  resolveAliasedField,
294
303
  resolveCatalogMarketProfiles,
295
304
  resolveCloudflareR2Bucket,
@@ -314,9 +323,12 @@ export {
314
323
  resolveTreeseedToolCommand,
315
324
  runTreeseedCopilotTask,
316
325
  runTreeseedVerifyDriver,
326
+ scoreCapacityLane,
327
+ selectBestCapacityLane,
317
328
  setActiveMarketProfile,
318
329
  setMarketSession,
319
330
  signEditorialPreviewToken,
331
+ summarizeCapacityPlan,
320
332
  tenantFeatureEnabled,
321
333
  tenantModelRendered,
322
334
  upsertRailwayVariables,
@@ -2001,12 +2001,14 @@ async function syncTreeseedGitHubEnvironment({
2001
2001
  const githubClient = createGitHubApiClient({ env: ghEnv });
2002
2002
  const environment = scope === "prod" ? "production" : scope;
2003
2003
  const deploymentBranch = scope === "prod" ? PRODUCTION_BRANCH : scope === "staging" ? STAGING_BRANCH : null;
2004
+ const deploymentTag = scope === "prod" ? "*.*.*" : null;
2004
2005
  const progress = (message, stream = "stdout") => onProgress?.(message, stream);
2005
2006
  if (!dryRun) {
2006
2007
  progress(`[${scope}][github][environment] Ensuring GitHub environment ${environment} exists...`);
2007
2008
  await ensureGitHubActionsEnvironment(repository, environment, {
2008
2009
  client: githubClient,
2009
- branchName: deploymentBranch
2010
+ branchName: deploymentBranch,
2011
+ tagName: deploymentTag
2010
2012
  });
2011
2013
  }
2012
2014
  progress(`[${scope}][github][sync] Loading existing GitHub secrets and variables...`);
@@ -2086,14 +2088,14 @@ function syncTreeseedRailwayEnvironment({ tenantRoot, scope = "prod", dryRun = f
2086
2088
  const registry = collectTreeseedEnvironmentContext(tenantRoot);
2087
2089
  const railwaySecretNames = registry.entries.filter((entry) => entry.scopes.includes(scope) && entry.targets.includes("railway-secret")).map((entry) => entry.id).filter((key) => typeof values[key] === "string" && values[key].length > 0);
2088
2090
  const railwayVariableNames = registry.entries.filter((entry) => entry.scopes.includes(scope) && entry.targets.includes("railway-var")).map((entry) => entry.id).filter((key) => typeof values[key] === "string" && values[key].length > 0);
2089
- const services = ["api", "manager", "worker", "workdayStart", "workdayReport"].map((serviceKey) => {
2091
+ const services = ["api", "workdayManager", "workerRunner"].map((serviceKey) => {
2090
2092
  const service = deployConfig.services?.[serviceKey];
2091
2093
  if (!service || service.enabled === false || (service.provider ?? "railway") !== "railway") {
2092
2094
  return null;
2093
2095
  }
2094
2096
  const environment = service.environments?.[scope];
2095
2097
  const fallbackServiceName = serviceKey === "api" ? config.settings.services.railway.apiServiceName : "";
2096
- const defaultRootDir = ["api", "manager", "worker", "workdayStart", "workdayReport"].includes(serviceKey) ? "." : "packages/core";
2098
+ const defaultRootDir = ["api", "workdayManager", "workerRunner"].includes(serviceKey) ? "." : "packages/core";
2097
2099
  return {
2098
2100
  service: serviceKey,
2099
2101
  projectName: service.railway?.projectName ?? config.settings.services.railway.projectName,
@@ -13,7 +13,7 @@ const GENERATED_ROOT = ".treeseed/generated";
13
13
  const STATE_ROOT = ".treeseed/state";
14
14
  const WORKTREE_METADATA_RELATIVE_PATH = ".treeseed/worktree.json";
15
15
  const PERSISTENT_SCOPES = /* @__PURE__ */ new Set(["local", "staging", "prod"]);
16
- const MANAGED_SERVICE_KEYS = ["api", "manager", "worker", "workdayStart", "workdayReport"];
16
+ const MANAGED_SERVICE_KEYS = ["api", "workdayManager", "workerRunner"];
17
17
  const TRESEED_ENVELOPE_SCHEMA_GENERATION = "runtime-envelopes-v1";
18
18
  const TRESEED_MIGRATION_WAVE_ID = "0005_runtime_envelopes";
19
19
  const TRESEED_SUPPORTED_PAYLOAD_RANGE = { min: 1, max: 1 };
@@ -154,7 +154,8 @@ function resolveConfiguredSurfaceBaseUrl(deployConfig, target, surface) {
154
154
  return null;
155
155
  }
156
156
  function sharedDeploymentName(identity, role = "") {
157
- return role ? `${identity.deploymentKey}-${sanitizeSegment(role)}` : identity.deploymentKey;
157
+ const roleSegment = role === "workdayManager" ? "workday-manager" : role === "workerRunner" ? "worker-runner-01" : role;
158
+ return role ? `${identity.deploymentKey}-${sanitizeSegment(roleSegment)}` : identity.deploymentKey;
158
159
  }
159
160
  function environmentScopedIdentityName(identity, role, target) {
160
161
  const environmentSegment = target.kind === "persistent" ? target.scope : sanitizeSegment(target.branchName);
@@ -97,9 +97,10 @@ export declare function listGitHubRepositoryVariableNames(repository: string | {
97
97
  export declare function ensureGitHubActionsEnvironment(repository: string | {
98
98
  owner: string;
99
99
  name: string;
100
- }, environmentName: string, { client, branchName, }?: {
100
+ }, environmentName: string, { client, branchName, tagName, }?: {
101
101
  client?: GitHubApiClient;
102
102
  branchName?: string | null;
103
+ tagName?: string | null;
103
104
  }): Promise<{
104
105
  repository: string;
105
106
  environment: string;
@@ -223,27 +223,32 @@ async function listGitHubRepositoryVariableNames(repository, { client = createGi
223
223
  }
224
224
  async function ensureGitHubActionsEnvironment(repository, environmentName, {
225
225
  client = createGitHubApiClient(),
226
- branchName
226
+ branchName,
227
+ tagName
227
228
  } = {}) {
228
229
  const { owner, name: repo } = typeof repository === "string" ? parseGitHubRepositorySlug(repository) : repository;
230
+ const desiredPolicies = [
231
+ ...branchName ? [{ name: branchName, type: "branch" }] : [],
232
+ ...tagName ? [{ name: tagName, type: "tag" }] : []
233
+ ];
229
234
  try {
230
235
  await withGitHubApiRetries(() => client.request("PUT /repos/{owner}/{repo}/environments/{environment_name}", {
231
236
  owner,
232
237
  repo,
233
238
  environment_name: environmentName,
234
- ...branchName ? {
239
+ ...desiredPolicies.length > 0 ? {
235
240
  deployment_branch_policy: {
236
241
  protected_branches: false,
237
242
  custom_branch_policies: true
238
243
  }
239
244
  } : {}
240
245
  }));
241
- if (branchName) {
242
- await ensureGitHubEnvironmentBranchPolicy(client, {
246
+ if (desiredPolicies.length > 0) {
247
+ await ensureGitHubEnvironmentDeploymentPolicies(client, {
243
248
  owner,
244
249
  repo,
245
250
  environmentName,
246
- branchName
251
+ policies: desiredPolicies
247
252
  });
248
253
  }
249
254
  return { repository: `${owner}/${repo}`, environment: environmentName };
@@ -251,11 +256,11 @@ async function ensureGitHubActionsEnvironment(repository, environmentName, {
251
256
  throw normalizeGitHubApiError(error, `Unable to ensure GitHub environment ${environmentName} for ${owner}/${repo}`);
252
257
  }
253
258
  }
254
- async function ensureGitHubEnvironmentBranchPolicy(client, {
259
+ async function ensureGitHubEnvironmentDeploymentPolicies(client, {
255
260
  owner,
256
261
  repo,
257
262
  environmentName,
258
- branchName
263
+ policies: desiredPolicies
259
264
  }) {
260
265
  const response = await withGitHubApiRetries(() => client.request(
261
266
  "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies",
@@ -267,9 +272,10 @@ async function ensureGitHubEnvironmentBranchPolicy(client, {
267
272
  }
268
273
  ));
269
274
  const policies = Array.isArray(response.data?.branch_policies) ? response.data.branch_policies : [];
270
- const desired = policies.find((policy) => policy.name === branchName && (policy.type ?? "branch") === "branch");
275
+ const desiredKey = (policy) => `${policy.type ?? "branch"}:${policy.name ?? ""}`;
276
+ const desiredKeys = new Set(desiredPolicies.map((policy) => desiredKey(policy)));
271
277
  for (const policy of policies) {
272
- if (!policy.id || policy.name === branchName && (policy.type ?? "branch") === "branch") {
278
+ if (!policy.id || desiredKeys.has(desiredKey(policy))) {
273
279
  continue;
274
280
  }
275
281
  await withGitHubApiRetries(() => client.request(
@@ -282,25 +288,28 @@ async function ensureGitHubEnvironmentBranchPolicy(client, {
282
288
  }
283
289
  ));
284
290
  }
285
- if (desired) {
286
- return;
287
- }
288
- try {
289
- await withGitHubApiRetries(() => client.request(
290
- "POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies",
291
- {
292
- owner,
293
- repo,
294
- environment_name: environmentName,
295
- name: branchName,
296
- type: "branch"
291
+ const existingKeys = new Set(policies.map((policy) => desiredKey(policy)));
292
+ for (const policy of desiredPolicies) {
293
+ if (existingKeys.has(desiredKey(policy))) {
294
+ continue;
295
+ }
296
+ try {
297
+ await withGitHubApiRetries(() => client.request(
298
+ "POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies",
299
+ {
300
+ owner,
301
+ repo,
302
+ environment_name: environmentName,
303
+ name: policy.name,
304
+ type: policy.type
305
+ }
306
+ ));
307
+ } catch (error) {
308
+ if (error && typeof error === "object" && error.status === 303) {
309
+ continue;
297
310
  }
298
- ));
299
- } catch (error) {
300
- if (error && typeof error === "object" && error.status === 303) {
301
- return;
311
+ throw error;
302
312
  }
303
- throw error;
304
313
  }
305
314
  }
306
315
  async function paginateGitHubEnvironmentNames(client, route, params) {
@@ -324,47 +324,24 @@ function applyManagedProjectDefaults(projectRoot, input) {
324
324
  }
325
325
  }
326
326
  },
327
- manager: {
327
+ workdayManager: {
328
328
  enabled: managedRuntime,
329
329
  provider: managedRuntime ? "railway" : "none",
330
330
  railway: {
331
- serviceName: `${slug}-manager`,
331
+ serviceName: `${slug}-workday-manager`,
332
332
  rootDir: ".",
333
333
  buildCommand: "npm run build",
334
- startCommand: "node ./node_modules/@treeseed/core/dist/services/manager.js",
335
- schedule: "*/5 * * * *"
336
- }
337
- },
338
- worker: {
339
- enabled: managedRuntime,
340
- provider: managedRuntime ? "railway" : "none",
341
- railway: {
342
- serviceName: `${slug}-worker`,
343
- rootDir: ".",
344
- buildCommand: "npm run build",
345
- startCommand: "node ./node_modules/@treeseed/core/dist/services/worker.js"
346
- }
347
- },
348
- workdayStart: {
349
- enabled: managedRuntime,
350
- provider: managedRuntime ? "railway" : "none",
351
- railway: {
352
- serviceName: `${slug}-workday-start`,
353
- rootDir: ".",
354
- buildCommand: "npm run build",
355
- startCommand: "node ./node_modules/@treeseed/core/dist/services/workday-start.js",
334
+ startCommand: "node ./node_modules/@treeseed/core/dist/services/workday-manager.js",
356
335
  schedule: "0 9 * * 1-5"
357
336
  }
358
337
  },
359
- workdayReport: {
338
+ workerRunner: {
360
339
  enabled: managedRuntime,
361
340
  provider: managedRuntime ? "railway" : "none",
362
341
  railway: {
363
- serviceName: `${slug}-workday-report`,
364
342
  rootDir: ".",
365
343
  buildCommand: "npm run build",
366
- startCommand: "node ./node_modules/@treeseed/core/dist/services/workday-report.js",
367
- schedule: "5 17 * * 1-5"
344
+ startCommand: "node ./node_modules/@treeseed/core/dist/services/worker.js"
368
345
  }
369
346
  },
370
347
  ...config.services ?? {}
@@ -1,6 +1,7 @@
1
1
  export type DevDependencyReferenceMode = 'git-tag' | 'registry-prerelease';
2
2
  export type DevTagCleanupMode = 'safe-after-release' | 'off';
3
3
  export type GitDependencyProtocol = 'preserve-origin' | 'https' | 'ssh';
4
+ export type DevTagBranchScope = 'staging' | 'preview' | 'all';
4
5
  export type PackageDependencyReference = {
5
6
  packageName: string;
6
7
  version: string;
@@ -18,6 +19,22 @@ export type RewrittenDevReference = {
18
19
  to: string;
19
20
  tagName: string | null;
20
21
  };
22
+ export type TreeseedDevTagInfo = {
23
+ tagName: string;
24
+ stableVersion: string;
25
+ branchSlug: string;
26
+ timestamp: string;
27
+ metadata: Record<string, string>;
28
+ branch: string | null;
29
+ packageName: string | null;
30
+ version: string | null;
31
+ };
32
+ export type StaleDevTagClassification = {
33
+ tagName: string;
34
+ action: 'delete' | 'skip';
35
+ reason: string;
36
+ info: TreeseedDevTagInfo | null;
37
+ };
21
38
  export declare function internalDependencyFields(packageJson: Record<string, unknown> | null): string[];
22
39
  export declare function isPrereleaseVersion(version: string): boolean;
23
40
  export declare function isStableVersion(version: string): boolean;
@@ -61,6 +78,15 @@ export declare function createDevTagMessage(input: {
61
78
  }): string;
62
79
  export declare function gitTagMessage(repoDir: string, tagName: string): string;
63
80
  export declare function tagHasTreeseedDevMetadata(repoDir: string, tagName: string): boolean;
81
+ export declare function parseTreeseedDevTag(tagName: string, message: string): TreeseedDevTagInfo | null;
82
+ export declare function classifyStaleTreeseedDevTag(input: {
83
+ tagName: string;
84
+ message: string;
85
+ currentVersion: string;
86
+ activeReferences?: string[];
87
+ branchScope?: DevTagBranchScope;
88
+ expectedPackageName?: string | null;
89
+ }): StaleDevTagClassification;
64
90
  export declare function cleanupDevTags(repoDir: string, tagNames: string[], activeReferences?: string[]): {
65
91
  cleaned: string[];
66
92
  skipped: {
@@ -68,3 +94,45 @@ export declare function cleanupDevTags(repoDir: string, tagNames: string[], acti
68
94
  reason: string;
69
95
  }[];
70
96
  };
97
+ export declare function collectTreeseedDevTagCleanupPlan(input: {
98
+ repoDir: string;
99
+ packageName: string;
100
+ currentVersion: string;
101
+ activeReferences?: string[];
102
+ branchScope?: DevTagBranchScope;
103
+ }): {
104
+ packageName: string;
105
+ currentVersion: string;
106
+ branchScope: DevTagBranchScope;
107
+ candidates: StaleDevTagClassification[];
108
+ skipped: StaleDevTagClassification[];
109
+ tags: StaleDevTagClassification[];
110
+ };
111
+ export declare function cleanupStaleTreeseedDevTags(input: {
112
+ repoDir: string;
113
+ packageName: string;
114
+ currentVersion: string;
115
+ activeReferences?: string[];
116
+ branchScope?: DevTagBranchScope;
117
+ dryRun?: boolean;
118
+ }): {
119
+ status: string;
120
+ packageName: string;
121
+ currentVersion: string;
122
+ branchScope: DevTagBranchScope;
123
+ candidates: {
124
+ tagName: string;
125
+ reason: string;
126
+ branch: string | null | undefined;
127
+ branchSlug: string | undefined;
128
+ version: string | null | undefined;
129
+ }[];
130
+ candidateCount: number;
131
+ cleaned: string[];
132
+ cleanedCount: number;
133
+ skipped: {
134
+ tagName: string;
135
+ reason: string;
136
+ }[];
137
+ skippedCount: number;
138
+ };