@treeseed/sdk 0.10.6 → 0.10.7

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 (41) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +58 -0
  3. package/dist/operations/repository-operations.d.ts +129 -0
  4. package/dist/operations/repository-operations.js +634 -0
  5. package/dist/operations/services/config-runtime.d.ts +7 -6
  6. package/dist/operations/services/config-runtime.js +45 -25
  7. package/dist/operations/services/deploy.d.ts +42 -0
  8. package/dist/operations/services/deploy.js +1 -1
  9. package/dist/operations/services/project-platform.d.ts +41 -1
  10. package/dist/operations/services/project-platform.js +13 -0
  11. package/dist/operations/services/railway-api.d.ts +35 -1
  12. package/dist/operations/services/railway-api.js +240 -35
  13. package/dist/operations/services/railway-deploy.d.ts +16 -234
  14. package/dist/operations/services/railway-deploy.js +177 -62
  15. package/dist/operations/services/release-candidate.js +1 -2
  16. package/dist/operations/services/runtime-tools.d.ts +14 -0
  17. package/dist/operations/services/runtime-tools.js +15 -1
  18. package/dist/operations/services/workspace-save.d.ts +24 -0
  19. package/dist/operations/services/workspace-save.js +143 -3
  20. package/dist/operations/services/workspace-tools.js +1 -1
  21. package/dist/platform/env.yaml +163 -2
  22. package/dist/platform/environment.d.ts +1 -0
  23. package/dist/platform/environment.js +9 -0
  24. package/dist/platform-operation-store.d.ts +90 -0
  25. package/dist/platform-operation-store.js +505 -0
  26. package/dist/platform-operations.d.ts +265 -0
  27. package/dist/platform-operations.js +421 -0
  28. package/dist/reconcile/bootstrap-systems.js +3 -3
  29. package/dist/reconcile/builtin-adapters.js +225 -29
  30. package/dist/reconcile/contracts.d.ts +1 -1
  31. package/dist/reconcile/desired-state.d.ts +14 -0
  32. package/dist/reconcile/desired-state.js +4 -0
  33. package/dist/reconcile/engine.d.ts +28 -0
  34. package/dist/reconcile/state.js +3 -0
  35. package/dist/reconcile/units.js +2 -0
  36. package/dist/workflow/operations.d.ts +13 -5
  37. package/dist/workflow/operations.js +69 -12
  38. package/dist/workflow-state.d.ts +2 -0
  39. package/dist/workflow-state.js +7 -2
  40. package/dist/workflow.d.ts +2 -0
  41. package/package.json +15 -2
@@ -87,10 +87,12 @@ import { runTenantDeployPreflight, runWorkspaceReleasePreflight, runWorkspaceSav
87
87
  import { collectCliPreflight } from "../operations/services/workspace-preflight.js";
88
88
  import {
89
89
  collectMergeConflictReport,
90
+ collectPublicPackageReleaseLineState,
90
91
  currentBranch,
91
92
  formatMergeConflictReport,
92
93
  gitStatusPorcelain,
93
94
  hasMeaningfulChanges,
95
+ highestStableGitTagOnLine,
94
96
  incrementVersion,
95
97
  originRemoteUrl,
96
98
  planWorkspaceReleaseBump,
@@ -1724,6 +1726,10 @@ function releasePlanVersionMap(plannedVersions) {
1724
1726
  Object.entries(plannedVersions).filter(([name]) => name !== "@treeseed/market").map(([name, version]) => [name, String(version)])
1725
1727
  );
1726
1728
  }
1729
+ function releasePlanStableDependencyVersionMap(plannedRelease) {
1730
+ const stableDependencyVersions = plannedRelease.stableDependencyVersions && typeof plannedRelease.stableDependencyVersions === "object" && !Array.isArray(plannedRelease.stableDependencyVersions) ? plannedRelease.stableDependencyVersions : {};
1731
+ return new Map(Object.entries(stableDependencyVersions).map(([name, version]) => [name, String(version)]));
1732
+ }
1727
1733
  function releasePlanPackageSelection(value) {
1728
1734
  const record = value && typeof value === "object" ? value : {};
1729
1735
  return {
@@ -1732,6 +1738,20 @@ function releasePlanPackageSelection(value) {
1732
1738
  selected: Array.isArray(record.selected) ? record.selected.map(String) : []
1733
1739
  };
1734
1740
  }
1741
+ function stableDependencyVersionsForReleaseLine(root, options) {
1742
+ const targetLine = typeof options.targetLine === "string" ? options.targetLine : null;
1743
+ const group = new Set(Array.isArray(options.group) ? options.group.map(String) : []);
1744
+ if (!targetLine || group.size === 0) return {};
1745
+ const versions = {};
1746
+ for (const pkg of workspacePackages(root)) {
1747
+ if (!group.has(pkg.name) || options.selected.has(pkg.name)) continue;
1748
+ const stableVersion = highestStableGitTagOnLine(pkg.dir, targetLine);
1749
+ if (stableVersion) {
1750
+ versions[pkg.name] = stableVersion;
1751
+ }
1752
+ }
1753
+ return versions;
1754
+ }
1735
1755
  function assertReleaseCandidatePassed(operation, report) {
1736
1756
  if (report.status === "passed") {
1737
1757
  return;
@@ -1748,10 +1768,11 @@ function assertReleaseCandidatePassed(operation, report) {
1748
1768
  }
1749
1769
  async function runReleaseCandidateForPlan(operation, root, plannedRelease, options = {}) {
1750
1770
  const plannedVersions = plannedRelease.plannedVersions && typeof plannedRelease.plannedVersions === "object" && !Array.isArray(plannedRelease.plannedVersions) ? plannedRelease.plannedVersions : {};
1771
+ const stableDependencyVersions = plannedRelease.stableDependencyVersions && typeof plannedRelease.stableDependencyVersions === "object" && !Array.isArray(plannedRelease.stableDependencyVersions) ? plannedRelease.stableDependencyVersions : {};
1751
1772
  const packageSelection = releasePlanPackageSelection(plannedRelease.packageSelection);
1752
1773
  const report = await runReleaseCandidateGate({
1753
1774
  root,
1754
- plannedVersions,
1775
+ plannedVersions: { ...stableDependencyVersions, ...plannedVersions },
1755
1776
  selectedPackageNames: packageSelection.selected,
1756
1777
  allowReuse: options.allowReuse
1757
1778
  });
@@ -1760,31 +1781,49 @@ async function runReleaseCandidateForPlan(operation, root, plannedRelease, optio
1760
1781
  }
1761
1782
  function buildReleasePlanSnapshot(input) {
1762
1783
  const selectedPackageNames = new Set(input.packageSelection.selected);
1763
- const versionPlan = planWorkspaceReleaseBump(input.level, input.root, input.mode === "recursive-workspace" ? { selectedPackageNames } : {});
1784
+ const versionPlan = planWorkspaceReleaseBump(input.level, input.root, input.mode === "recursive-workspace" ? { selectedPackageNames, repairVersionLine: input.repairVersionLine === true, targetVersionLine: input.targetVersionLine } : {});
1785
+ const plannedSelected = [...versionPlan.selected].filter((name) => versionPlan.versions.has(name));
1786
+ const plannedChanged = input.repairVersionLine === true ? plannedSelected : Array.from(new Set(input.packageSelection.changed.filter((name) => plannedSelected.includes(name))));
1787
+ const plannedDependents = plannedSelected.filter((name) => !plannedChanged.includes(name));
1788
+ const plannedPackageSelection = {
1789
+ changed: plannedChanged,
1790
+ dependents: plannedDependents,
1791
+ selected: plannedSelected
1792
+ };
1764
1793
  const rootVersion = planRootPackageVersion(input.root, input.level);
1794
+ const stableDependencyVersions = stableDependencyVersionsForReleaseLine(input.root, {
1795
+ targetLine: versionPlan.releaseLine?.targetLine,
1796
+ group: versionPlan.releaseLine?.group,
1797
+ selected: new Set(plannedPackageSelection.selected)
1798
+ });
1765
1799
  const plannedVersions = {
1766
1800
  "@treeseed/market": rootVersion,
1767
1801
  ...Object.fromEntries(versionPlan.versions.entries())
1768
1802
  };
1769
- const plannedDevReferenceRewrites = input.mode === "recursive-workspace" ? collectInternalDevReferenceIssues(input.root, selectedPackageNames) : [];
1803
+ const plannedDevReferenceRewrites = input.mode === "recursive-workspace" ? collectInternalDevReferenceIssues(input.root, /* @__PURE__ */ new Set([
1804
+ ...plannedPackageSelection.selected,
1805
+ ...Object.keys(stableDependencyVersions)
1806
+ ])) : [];
1770
1807
  return {
1771
1808
  mode: input.mode,
1772
1809
  mergeStrategy: "merge-commit",
1773
1810
  level: input.level,
1811
+ releaseLine: versionPlan.releaseLine,
1774
1812
  rootVersion,
1775
1813
  releaseTag: rootVersion,
1776
1814
  stagingBranch: STAGING_BRANCH,
1777
1815
  productionBranch: PRODUCTION_BRANCH,
1778
- packageSelection: input.packageSelection,
1816
+ packageSelection: plannedPackageSelection,
1779
1817
  plannedVersions,
1818
+ stableDependencyVersions,
1780
1819
  plannedDevReferenceRewrites,
1781
- plannedPublishWaits: input.packageSelection.selected.map((name) => ({
1820
+ plannedPublishWaits: plannedPackageSelection.selected.map((name) => ({
1782
1821
  name,
1783
1822
  workflow: "publish.yml",
1784
1823
  branch: String(plannedVersions[name] ?? PRODUCTION_BRANCH),
1785
1824
  status: "planned"
1786
1825
  })),
1787
- touchedPackages: input.packageSelection.selected,
1826
+ touchedPackages: plannedPackageSelection.selected,
1788
1827
  repos: input.packageReports,
1789
1828
  rootRepo: input.rootRepo,
1790
1829
  finalBranch: STAGING_BRANCH,
@@ -1793,7 +1832,7 @@ function buildReleasePlanSnapshot(input) {
1793
1832
  { id: "release-candidate", description: "Run exact staging release-candidate readiness checks" },
1794
1833
  { id: "workspace-unlink", description: "Remove local workspace links before stable release install" },
1795
1834
  { id: "prepare-release-metadata", description: "Rewrite package metadata and lockfiles to production dependency mode" },
1796
- ...input.packageReports.filter((report) => selectedPackageNames.has(report.name)).map((report) => ({
1835
+ ...input.packageReports.filter((report) => plannedPackageSelection.selected.includes(report.name)).map((report) => ({
1797
1836
  id: `release-${report.name}`,
1798
1837
  description: `Release ${report.name} from staging to main and tag ${plannedVersions[report.name] ?? "(planned)"}`
1799
1838
  })),
@@ -1805,7 +1844,7 @@ function buildReleasePlanSnapshot(input) {
1805
1844
  blockers: input.blockers
1806
1845
  };
1807
1846
  }
1808
- function collectReleasePlanBlockers(session, mode, selectedPackageNames) {
1847
+ function collectReleasePlanBlockers(session, mode, selectedPackageNames, options = {}) {
1809
1848
  const blockers = [];
1810
1849
  if (session.branchName !== STAGING_BRANCH) {
1811
1850
  blockers.push("Release must start from staging.");
@@ -1817,6 +1856,10 @@ function collectReleasePlanBlockers(session, mode, selectedPackageNames) {
1817
1856
  blockers.push("@treeseed/market is missing origin remote.");
1818
1857
  }
1819
1858
  if (mode === "recursive-workspace") {
1859
+ const lineState = collectPublicPackageReleaseLineState(session.root);
1860
+ if (options.repairVersionLine !== true && options.level === "patch" && lineState.drifted) {
1861
+ blockers.push(`Public package version line drift detected (${lineState.packages.map((pkg) => `${pkg.name}@${pkg.version}`).join(", ")}). Run \`treeseed release --repair-version-line --target-version-line ${lineState.highestLine} --plan\` first.`);
1862
+ }
1820
1863
  for (const repo of session.packageRepos) {
1821
1864
  if (!selectedPackageNames.includes(repo.name)) continue;
1822
1865
  if (repo.detached) blockers.push(`${repo.name} is detached.`);
@@ -3823,17 +3866,24 @@ async function workflowRelease(helpers, input) {
3823
3866
  const ciMode = normalizeCiMode(effectiveInput.ciMode, "release");
3824
3867
  const isResume = Boolean(explicitResumeRunId || autoResumeRun);
3825
3868
  const packageSelection = session.packageSelection;
3826
- const selectedPackageNames = new Set(packageSelection.selected);
3827
- const blockers = isResume ? [] : collectReleasePlanBlockers(session, mode, packageSelection.selected);
3828
3869
  const plannedRelease = buildReleasePlanSnapshot({
3829
3870
  root,
3830
3871
  mode,
3831
3872
  level,
3873
+ repairVersionLine: effectiveInput.repairVersionLine === true,
3874
+ targetVersionLine: effectiveInput.targetVersionLine,
3832
3875
  packageSelection,
3833
3876
  packageReports,
3834
3877
  rootRepo,
3835
- blockers
3878
+ blockers: []
3879
+ });
3880
+ const plannedPackageSelection = releasePlanPackageSelection(plannedRelease.packageSelection);
3881
+ const selectedPackageNames = new Set(plannedPackageSelection.selected);
3882
+ const blockers = isResume ? [] : collectReleasePlanBlockers(session, mode, plannedPackageSelection.selected, {
3883
+ level,
3884
+ repairVersionLine: effectiveInput.repairVersionLine === true
3836
3885
  });
3886
+ plannedRelease.blockers = blockers;
3837
3887
  if (executionMode === "plan") {
3838
3888
  return buildWorkflowResult("release", root, {
3839
3889
  ...plannedRelease,
@@ -3863,6 +3913,8 @@ async function workflowRelease(helpers, input) {
3863
3913
  session,
3864
3914
  {
3865
3915
  bump: level,
3916
+ repairVersionLine: effectiveInput.repairVersionLine === true,
3917
+ targetVersionLine: effectiveInput.targetVersionLine,
3866
3918
  devTagCleanup: effectiveInput.devTagCleanup ?? "safe-after-release",
3867
3919
  gitDependencyProtocol: effectiveInput.gitDependencyProtocol ?? "preserve-origin",
3868
3920
  gitRemoteWriteMode: effectiveInput.gitRemoteWriteMode ?? "ssh-pushurl",
@@ -3911,6 +3963,11 @@ async function workflowRelease(helpers, input) {
3911
3963
  const effectivePackageSelection = releasePlanPackageSelection(releasePlan.packageSelection);
3912
3964
  const effectiveSelectedPackageNames = new Set(effectivePackageSelection.selected);
3913
3965
  const effectiveVersions = releasePlanVersionMap(releasePlan.plannedVersions);
3966
+ const effectiveStableDependencyVersions = releasePlanStableDependencyVersionMap(releasePlan);
3967
+ const effectiveDependencyReplacementVersions = new Map([
3968
+ ...effectiveStableDependencyVersions.entries(),
3969
+ ...effectiveVersions.entries()
3970
+ ]);
3914
3971
  const rootVersion = String(releasePlan.rootVersion);
3915
3972
  applyTreeseedEnvironmentToProcess({ tenantRoot: root, scope: "staging", override: true });
3916
3973
  assertReleaseGitHubAutomationReady(root, effectiveSelectedPackageNames, ciMode);
@@ -4089,7 +4146,7 @@ async function workflowRelease(helpers, input) {
4089
4146
  return [pkg.name, String(packageJson.version ?? "")];
4090
4147
  }).filter(([, version]) => version.includes("-dev."))
4091
4148
  );
4092
- const replacedDevReferences2 = rewriteProjectInternalDependenciesToStableVersions(root, effectiveVersions);
4149
+ const replacedDevReferences2 = rewriteProjectInternalDependenciesToStableVersions(root, effectiveDependencyReplacementVersions);
4093
4150
  applyStableWorkspaceVersionChanges(root, effectiveVersions);
4094
4151
  setRootPackageJsonVersion(root, rootVersion);
4095
4152
  const releaseInstalls2 = [
@@ -1,3 +1,4 @@
1
+ import { collectPublicPackageReleaseLineState } from './operations/services/workspace-save.ts';
1
2
  import { inspectWorkspaceDependencyMode } from './operations/services/workspace-dependency-mode.ts';
2
3
  import type { TreeseedWorkflowNextStep } from './workflow.ts';
3
4
  import { type TreeseedWorkflowBranchRole } from './workflow/policy.ts';
@@ -102,6 +103,7 @@ export type TreeseedWorkflowState = {
102
103
  }>;
103
104
  blockers: string[];
104
105
  warnings: string[];
106
+ releaseLine: ReturnType<typeof collectPublicPackageReleaseLineState> | null;
105
107
  };
106
108
  preview: {
107
109
  enabled: boolean;
@@ -21,7 +21,7 @@ import {
21
21
  } from "./operations/services/deploy.js";
22
22
  import { loadCliDeployConfig } from "./operations/services/runtime-tools.js";
23
23
  import { collectCliPreflight } from "./operations/services/workspace-preflight.js";
24
- import { currentBranch, gitStatusPorcelain } from "./operations/services/workspace-save.js";
24
+ import { collectPublicPackageReleaseLineState, currentBranch, gitStatusPorcelain } from "./operations/services/workspace-save.js";
25
25
  import { hasCompleteTreeseedPackageCheckout, isWorkspaceRoot, run, workspacePackages } from "./operations/services/workspace-tools.js";
26
26
  import { inspectWorkspaceDependencyMode } from "./operations/services/workspace-dependency-mode.js";
27
27
  import { inspectDetachedHeadRepair, PRODUCTION_BRANCH, STAGING_BRANCH } from "./operations/services/git-workflow.js";
@@ -369,6 +369,10 @@ function resolveTreeseedWorkflowState(cwd, options = {}) {
369
369
  }) : [];
370
370
  const packageSyncBlockers = [];
371
371
  const packageSyncWarnings = [];
372
+ const packageReleaseLine = completePackageCheckout ? collectPublicPackageReleaseLineState(effectiveCwd) : null;
373
+ if (packageReleaseLine?.drifted) {
374
+ packageSyncWarnings.push(`Public package release lines are drifted: ${packageReleaseLine.packages.map((pkg) => `${pkg.name}@${pkg.version}`).join(", ")}.`);
375
+ }
372
376
  for (const repo of packageSyncRepos) {
373
377
  if (repo.dirty) {
374
378
  packageSyncBlockers.push(`${repo.name} has uncommitted changes.`);
@@ -480,7 +484,8 @@ function resolveTreeseedWorkflowState(cwd, options = {}) {
480
484
  dirty: packageSyncRepos.some((repo) => repo.dirty),
481
485
  repos: packageSyncRepos,
482
486
  blockers: packageSyncBlockers,
483
- warnings: packageSyncWarnings
487
+ warnings: packageSyncWarnings,
488
+ releaseLine: packageReleaseLine
484
489
  },
485
490
  preview: {
486
491
  enabled: false,
@@ -211,6 +211,8 @@ export type TreeseedExportInput = {
211
211
  };
212
212
  export type TreeseedReleaseInput = {
213
213
  bump: 'major' | 'minor' | 'patch';
214
+ repairVersionLine?: boolean;
215
+ targetVersionLine?: string;
214
216
  devTagCleanup?: 'safe-after-release' | 'off';
215
217
  gitDependencyProtocol?: 'preserve-origin' | 'https' | 'ssh';
216
218
  gitRemoteWriteMode?: 'ssh-pushurl' | 'off';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeseed/sdk",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "Shared Treeseed SDK for content-backed and D1-backed object models.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -59,16 +59,17 @@
59
59
  "@github/copilot-language-server": "1.480.0",
60
60
  "@github/copilot-sdk": "0.3.0",
61
61
  "@railway/cli": "4.44.0",
62
+ "drizzle-orm": "^0.45.2",
62
63
  "esbuild": "^0.28.0",
63
64
  "extract-zip": "2.0.1",
64
65
  "github-slugger": "^2.0.0",
65
- "drizzle-orm": "^0.45.2",
66
66
  "hono": "^4.8.2",
67
67
  "ink": "^7.0.0",
68
68
  "libsodium-wrappers": "^0.7.15",
69
69
  "mdast-util-to-string": "^4.0.0",
70
70
  "minisearch": "^7.2.0",
71
71
  "octokit": "^5.0.3",
72
+ "pg": "^8.21.0",
72
73
  "react": "^19.2.5",
73
74
  "remark-mdx": "^3.1.1",
74
75
  "remark-parse": "^11.0.0",
@@ -242,6 +243,18 @@
242
243
  "types": "./dist/capacity-provider.d.ts",
243
244
  "default": "./dist/capacity-provider.js"
244
245
  },
246
+ "./platform-operations": {
247
+ "types": "./dist/platform-operations.d.ts",
248
+ "default": "./dist/platform-operations.js"
249
+ },
250
+ "./platform-operation-store": {
251
+ "types": "./dist/platform-operation-store.d.ts",
252
+ "default": "./dist/platform-operation-store.js"
253
+ },
254
+ "./operations/repository-operations": {
255
+ "types": "./dist/operations/repository-operations.d.ts",
256
+ "default": "./dist/operations/repository-operations.js"
257
+ },
245
258
  "./types": {
246
259
  "types": "./dist/sdk-types.d.ts",
247
260
  "default": "./dist/sdk-types.js"