@treeseed/sdk 0.12.41 → 0.12.43

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.
@@ -1717,11 +1717,13 @@ function hostedWorkflowForSavedRepository(root, repo) {
1717
1717
  if (repo.branch === STAGING_BRANCH && existsSync(resolve(repo.path, "treeseed.site.yaml")) && workflowFileExists(repo.path, "deploy.yml")) {
1718
1718
  return "deploy.yml";
1719
1719
  }
1720
- return "verify.yml";
1720
+ if (workflowFileExists(repo.path, "verify.yml")) return "verify.yml";
1721
+ return null;
1721
1722
  }
1722
1723
  function gatesForSavedRepositoryReports(root, reports) {
1723
- return reports.filter((repo) => repo.pushed && repo.commitSha && repo.branch && (repo.committed || repo.tagName)).map((repo) => {
1724
+ return reports.filter((repo) => repo.pushed && repo.commitSha && repo.branch && (repo.committed || repo.tagName)).flatMap((repo) => {
1724
1725
  const workflow = hostedWorkflowForSavedRepository(root, repo);
1726
+ if (!workflow) return [];
1725
1727
  const gate = {
1726
1728
  name: repo.name,
1727
1729
  repoPath: repo.path,
@@ -1729,7 +1731,7 @@ function gatesForSavedRepositoryReports(root, reports) {
1729
1731
  branch: String(repo.branch),
1730
1732
  headSha: String(repo.commitSha)
1731
1733
  };
1732
- return /^deploy(?:[-.]|$)/u.test(workflow) ? hostedDeployGate(gate) : gate;
1734
+ return [/^deploy(?:[-.]|$)/u.test(workflow) ? hostedDeployGate(gate) : gate];
1733
1735
  });
1734
1736
  }
1735
1737
  function packageHostedVerifyWorkflow(adapter) {
@@ -2263,6 +2265,28 @@ function backMergeProductionIntoStaging(repoDir, repoName, message) {
2263
2265
  commitSha: headCommit(repoDir)
2264
2266
  };
2265
2267
  }
2268
+ function releaseHelperRepoToProduction(repo) {
2269
+ syncBranchWithOrigin(repo.dir, STAGING_BRANCH);
2270
+ if (!remoteBranchExists(repo.dir, STAGING_BRANCH)) {
2271
+ throw new Error(`${repo.name} has no origin/${STAGING_BRANCH} branch to release.`);
2272
+ }
2273
+ const stagingHead = remoteHeadCommit(repo.dir, STAGING_BRANCH);
2274
+ const promotion = promoteCommitToProductionBranch(repo.dir, stagingHead);
2275
+ const backMerge = backMergeProductionIntoStaging(repo.dir, repo.name, releaseAdminMessage({
2276
+ subject: `release: back-merge ${PRODUCTION_BRANCH} into ${STAGING_BRANCH}`,
2277
+ version: null,
2278
+ sourceRef: PRODUCTION_BRANCH,
2279
+ targetRef: STAGING_BRANCH
2280
+ }));
2281
+ return {
2282
+ name: repo.name,
2283
+ kind: repo.kind,
2284
+ path: repo.relativeDir,
2285
+ stagingHead,
2286
+ promotion,
2287
+ backMerge
2288
+ };
2289
+ }
2266
2290
  function backMergeRootProductionIntoStaging(root, syncPackageStagingHeads, options = {}) {
2267
2291
  const gitRoot = repoRoot(root);
2268
2292
  const commits = releaseHistoryCommits(gitRoot, STAGING_BRANCH, `origin/${PRODUCTION_BRANCH}`);
@@ -2307,6 +2331,27 @@ function releasePlanStableDependencyVersionMap(plannedRelease) {
2307
2331
  const stableDependencyVersions = plannedRelease.stableDependencyVersions && typeof plannedRelease.stableDependencyVersions === "object" && !Array.isArray(plannedRelease.stableDependencyVersions) ? plannedRelease.stableDependencyVersions : {};
2308
2332
  return new Map(Object.entries(stableDependencyVersions).map(([name, version]) => [name, String(version)]));
2309
2333
  }
2334
+ function collectReleaseHelperRepoBlockers(root) {
2335
+ const blockers = [];
2336
+ for (const repo of checkedOutReleaseHelperRepos(root)) {
2337
+ const branch = currentBranch(repo.dir) || null;
2338
+ if (hasMeaningfulChanges(repo.dir)) {
2339
+ blockers.push(`${repo.name} has uncommitted changes.`);
2340
+ }
2341
+ if (branch !== STAGING_BRANCH) {
2342
+ blockers.push(`${repo.name} is on ${branch ?? "(detached)"} instead of ${STAGING_BRANCH}.`);
2343
+ }
2344
+ try {
2345
+ originRemoteUrl(repo.dir);
2346
+ } catch {
2347
+ blockers.push(`${repo.name} has no readable origin remote.`);
2348
+ }
2349
+ if (!remoteBranchExists(repo.dir, STAGING_BRANCH)) {
2350
+ blockers.push(`${repo.name} has no origin/${STAGING_BRANCH} branch.`);
2351
+ }
2352
+ }
2353
+ return blockers;
2354
+ }
2310
2355
  function releasePlanPackageSelection(value) {
2311
2356
  const record = value && typeof value === "object" ? value : {};
2312
2357
  return {
@@ -5041,16 +5086,38 @@ function writeStageCandidateManifest(root, runId, manifest) {
5041
5086
  }
5042
5087
  return manifest;
5043
5088
  }
5044
- function checkedOutStagePackageRepos(root) {
5045
- return checkedOutManagedWorkflowRepos(root).filter((repo) => repo.kind === "package");
5089
+ function dedupeManagedReposByRemote(repos) {
5090
+ const seen = /* @__PURE__ */ new Set();
5091
+ const deduped = [];
5092
+ for (const repo of repos) {
5093
+ const key = repo.remoteUrl ? `remote:${repo.remoteUrl}` : `path:${repo.dir}`;
5094
+ if (seen.has(key)) continue;
5095
+ seen.add(key);
5096
+ deduped.push(repo);
5097
+ }
5098
+ return deduped;
5099
+ }
5100
+ function checkedOutStagePromotionRepos(root) {
5101
+ return dedupeManagedReposByRemote(checkedOutManagedWorkflowRepos(root).filter((repo) => repo.kind === "package" || repo.kind === "template" || repo.kind === "fixture"));
5102
+ }
5103
+ function checkedOutReleaseHelperRepos(root) {
5104
+ return dedupeManagedReposByRemote(checkedOutManagedWorkflowRepos(root).filter((repo) => repo.kind === "template" || repo.kind === "fixture"));
5105
+ }
5106
+ function syncAllCheckedOutReleaseHelperRepos(root, branchName) {
5107
+ for (const repo of checkedOutManagedWorkflowRepos(root).filter((entry) => entry.kind === "template" || entry.kind === "fixture")) {
5108
+ if (remoteBranchExists(repo.dir, branchName)) {
5109
+ syncBranchWithOrigin(repo.dir, branchName);
5110
+ }
5111
+ }
5046
5112
  }
5047
5113
  function buildStagePromotionPlan(root, branchName, input) {
5048
5114
  const gitRoot = repoRoot(root);
5049
5115
  const repos = [
5050
- ...checkedOutStagePackageRepos(root).map((repo) => ({
5116
+ ...checkedOutStagePromotionRepos(root).map((repo) => ({
5051
5117
  name: repo.name,
5052
5118
  path: repo.dir,
5053
5119
  kind: "managed",
5120
+ repoKind: repo.kind,
5054
5121
  sourceBranch: branchName,
5055
5122
  targetBranch: STAGING_BRANCH,
5056
5123
  remoteSourceExists: remoteBranchExists(repo.dir, branchName),
@@ -5147,6 +5214,7 @@ function createStageCandidateManifest(root, runId, branchName, plan, verificatio
5147
5214
  packages: packageRepos.map((repo) => ({
5148
5215
  name: repo.name,
5149
5216
  path: repo.path,
5217
+ repoKind: repo.repoKind,
5150
5218
  commit: headCommit(repo.path),
5151
5219
  remote: (() => {
5152
5220
  try {
@@ -5163,7 +5231,7 @@ function createStageCandidateManifest(root, runId, branchName, plan, verificatio
5163
5231
  }
5164
5232
  function cleanupStageSourceBranches(root, branchName, manifest) {
5165
5233
  const results = [];
5166
- for (const repo of checkedOutStagePackageRepos(root)) {
5234
+ for (const repo of checkedOutStagePromotionRepos(root)) {
5167
5235
  const manifestRepo = manifest.packages.find((entry) => entry.name === repo.name);
5168
5236
  if (!manifestRepo) continue;
5169
5237
  const remoteDeleted = deleteRemoteBranch(repo.dir, branchName);
@@ -5318,7 +5386,7 @@ ${currentBlockers.map((entry) => `- ${entry}`).join("\n")}`, {
5318
5386
  const mergeDown = await executeJournalStep(root, workflowRun.runId, "merge-staging-down", () => {
5319
5387
  const results = [];
5320
5388
  try {
5321
- for (const repo of checkedOutStagePackageRepos(root)) {
5389
+ for (const repo of checkedOutStagePromotionRepos(root)) {
5322
5390
  if (!remoteBranchExists(repo.dir, featureBranch)) {
5323
5391
  results.push({ name: repo.name, path: repo.dir, skipped: true, reason: "remote-branch-missing" });
5324
5392
  continue;
@@ -5620,6 +5688,7 @@ async function workflowRelease(helpers, input) {
5620
5688
  const rootRepo = createWorkspaceRootRepoReport(root);
5621
5689
  traceReleaseStartup("inspect package repos");
5622
5690
  const packageReports = createWorkspacePackageReports(root);
5691
+ const releaseHelperRepos = checkedOutReleaseHelperRepos(root);
5623
5692
  const explicitResumeRunId = helpers.context.workflow?.resumeRunId ?? null;
5624
5693
  traceReleaseStartup("check auto resume");
5625
5694
  const autoResumeRun = executionMode === "execute" && !explicitResumeRunId && input.fresh !== true ? findAutoResumableReleaseRun(root, session.branchName, rootRepo, packageReports, { archiveStale: false }) : null;
@@ -5651,6 +5720,7 @@ async function workflowRelease(helpers, input) {
5651
5720
  level,
5652
5721
  repairVersionLine: effectiveInput.repairVersionLine === true
5653
5722
  });
5723
+ blockers.push(...collectReleaseHelperRepoBlockers(root));
5654
5724
  const selectedVersions = releasePlanVersionMap(plannedRelease.plannedVersions);
5655
5725
  const releaseImageVersions = productionReleaseImageRefVersions(root, selectedVersions);
5656
5726
  const releaseImageRefs = productionReleaseImageRefEnv(releaseImageVersions);
@@ -5671,6 +5741,12 @@ async function workflowRelease(helpers, input) {
5671
5741
  sceneArtifacts: normalizeSceneArtifactsMode(effectiveInput.sceneArtifacts),
5672
5742
  releaseImageRefs,
5673
5743
  localCleanup,
5744
+ releaseHelperRepos: releaseHelperRepos.map((repo) => ({
5745
+ name: repo.name,
5746
+ kind: repo.kind,
5747
+ path: repo.relativeDir,
5748
+ remote: repo.remoteUrl
5749
+ })),
5674
5750
  freshArchivedRuns: [],
5675
5751
  autoResumeCandidate: planAutoResumeRun ? {
5676
5752
  runId: planAutoResumeRun.runId,
@@ -5738,6 +5814,14 @@ ${blockers.join("\n")}`, {
5738
5814
  resumable: true
5739
5815
  };
5740
5816
  }),
5817
+ {
5818
+ id: "release-helper-repos",
5819
+ description: "Promote starter templates and shared fixture repositories from staging to production",
5820
+ repoName: rootRepo.name,
5821
+ repoPath: rootRepo.path,
5822
+ branch: STAGING_BRANCH,
5823
+ resumable: true
5824
+ },
5741
5825
  { id: "verify-published-artifacts", description: "Verify immutable registry artifacts exist after publish workflows", repoName: rootRepo.name, repoPath: rootRepo.path, branch: PRODUCTION_BRANCH, resumable: true },
5742
5826
  { id: "production-package-deploy-workflows", description: "Wait for production package deploy workflows before live verification", repoName: rootRepo.name, repoPath: rootRepo.path, branch: PRODUCTION_BRANCH, resumable: true },
5743
5827
  { id: "production-hosting", description: "Reconcile and live-verify production hosted resources before root deploy", repoName: rootRepo.name, repoPath: rootRepo.path, branch: PRODUCTION_BRANCH, resumable: true },
@@ -5859,6 +5943,11 @@ ${rendered}`);
5859
5943
  });
5860
5944
  packageReleases.push(packageRelease);
5861
5945
  }
5946
+ const managedHelperReleases = await executeJournalStep(root, workflowRun.runId, "release-helper-repos", () => {
5947
+ const releases = releaseHelperRepos.map((repo) => releaseHelperRepoToProduction(repo));
5948
+ syncAllCheckedOutReleaseHelperRepos(root, STAGING_BRANCH);
5949
+ return { status: "completed", repos: releases };
5950
+ });
5862
5951
  const publishedArtifacts = await executeJournalStep(root, workflowRun.runId, "verify-published-artifacts", () => verifyPublishedReleaseArtifacts(selectedVersions));
5863
5952
  const productionPackageDeployWorkflows = await executeJournalStep(root, workflowRun.runId, "production-package-deploy-workflows", () => {
5864
5953
  const deployGates = productionPackageDeployGates(root, allVersions);
@@ -5948,6 +6037,7 @@ ${rendered}`);
5948
6037
  workspaceUnlink,
5949
6038
  releaseMetadata,
5950
6039
  packageReleases,
6040
+ managedHelperReleases,
5951
6041
  rootRelease,
5952
6042
  publishWait: publishWait.workflowGates,
5953
6043
  publishedArtifacts,
@@ -0,0 +1,60 @@
1
+ CREATE TABLE IF NOT EXISTS "structured_agent_estimates" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "team_id" text NOT NULL,
4
+ "project_id" text NOT NULL,
5
+ "decision_id" text,
6
+ "proposal_id" text,
7
+ "work_unit_id" text,
8
+ "agent_class" text NOT NULL,
9
+ "agent_id" text,
10
+ "status" text DEFAULT 'submitted' NOT NULL,
11
+ "estimate_json" text NOT NULL,
12
+ "metadata_json" text DEFAULT '{}' NOT NULL,
13
+ "created_at" text NOT NULL,
14
+ "accepted_at" text,
15
+ "rejected_at" text
16
+ );
17
+ CREATE INDEX IF NOT EXISTS "idx_structured_agent_estimates_decision" ON "structured_agent_estimates" ("decision_id","status","created_at");
18
+
19
+ CREATE TABLE IF NOT EXISTS "decision_assignment_graphs" (
20
+ "id" text PRIMARY KEY NOT NULL,
21
+ "team_id" text NOT NULL,
22
+ "project_id" text NOT NULL,
23
+ "decision_id" text NOT NULL,
24
+ "version" integer NOT NULL,
25
+ "status" text NOT NULL,
26
+ "active" integer DEFAULT 0 NOT NULL,
27
+ "graph_json" text NOT NULL,
28
+ "metadata_json" text DEFAULT '{}' NOT NULL,
29
+ "compiled_at" text,
30
+ "created_at" text NOT NULL,
31
+ "updated_at" text NOT NULL
32
+ );
33
+ CREATE INDEX IF NOT EXISTS "idx_decision_assignment_graphs_decision" ON "decision_assignment_graphs" ("decision_id","active","version");
34
+
35
+ CREATE TABLE IF NOT EXISTS "deliverable_contracts" (
36
+ "id" text PRIMARY KEY NOT NULL,
37
+ "team_id" text NOT NULL,
38
+ "project_id" text NOT NULL,
39
+ "decision_id" text NOT NULL,
40
+ "deliverable_type" text NOT NULL,
41
+ "status" text NOT NULL,
42
+ "contract_json" text NOT NULL,
43
+ "metadata_json" text DEFAULT '{}' NOT NULL,
44
+ "created_at" text NOT NULL,
45
+ "updated_at" text NOT NULL
46
+ );
47
+ CREATE INDEX IF NOT EXISTS "idx_deliverable_contracts_decision" ON "deliverable_contracts" ("decision_id","status","deliverable_type");
48
+
49
+ CREATE TABLE IF NOT EXISTS "deliverable_manifests" (
50
+ "id" text PRIMARY KEY NOT NULL,
51
+ "deliverable_contract_id" text NOT NULL,
52
+ "project_id" text NOT NULL,
53
+ "decision_id" text NOT NULL,
54
+ "ready_for_review" integer DEFAULT 0 NOT NULL,
55
+ "manifest_json" text NOT NULL,
56
+ "metadata_json" text DEFAULT '{}' NOT NULL,
57
+ "submitted_at" text,
58
+ "created_at" text NOT NULL
59
+ );
60
+ CREATE INDEX IF NOT EXISTS "idx_deliverable_manifests_contract" ON "deliverable_manifests" ("deliverable_contract_id","submitted_at");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeseed/sdk",
3
- "version": "0.12.41",
3
+ "version": "0.12.43",
4
4
  "description": "Shared Treeseed SDK for content-backed and D1-backed object models.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {