@treeseed/cli 0.10.22 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,174 +1,147 @@
1
- # `@treeseed/cli`
1
+ # @treeseed/cli
2
2
 
3
- Operator-facing Treeseed CLI package.
3
+ `@treeseed/cli` publishes the `treeseed` and `trsd` command surfaces. Use it to configure Treeseed, run local development, save/stage/release work, reconcile hosting, operate capacity providers, manage package images, and inspect workflow state.
4
4
 
5
- This package publishes the `treeseed` binary. `@treeseed/sdk` owns the reusable workflow and runtime capabilities, `@treeseed/core` owns integrated local platform orchestration, and `@treeseed/cli` owns argv parsing, command help, terminal formatting, command handlers, and the installable executable surface.
5
+ The CLI is the human and automation entrypoint over package-owned capabilities. It delegates platform logic to `@treeseed/sdk`, web runtime orchestration to `@treeseed/core`, backend behavior to API surfaces, capacity runtime to `@treeseed/agent`, and TreeDX image workflows to package manifests.
6
6
 
7
- ## Requirements
7
+ ## What You Can Do With The CLI
8
8
 
9
- - Node `>=22`
10
- - npm as the canonical package manager for install, CI, and release flows
9
+ - configure local, staging, and production environments
10
+ - start and inspect local development instances
11
+ - save, stage, close, resume, and release multi-repo work
12
+ - plan/apply/verify hosted infrastructure through reconciliation
13
+ - run operations-runner smoke checks
14
+ - build and operate capacity providers
15
+ - manage TreeDX package image workflows
16
+ - inspect package drift, workflow locks, and interrupted runs
11
17
 
12
18
  ## Install
13
19
 
14
- Install the CLI with its runtime dependencies:
15
-
16
20
  ```bash
17
- npm install @treeseed/cli @treeseed/core @treeseed/sdk
21
+ npm install @treeseed/cli
18
22
  ```
19
23
 
20
- `@treeseed/cli` is a thin installable wrapper over `@treeseed/sdk` workflow and operations interfaces plus the Treeseed runtime packages. `treeseed dev` resolves the tenant-installed or sibling-workspace `@treeseed/core` web runtime, while `treeseed agents ...` delegates to `@treeseed/agent`. In normal consumer installs, npm resolves the runtime dependencies automatically.
21
-
22
- Workflow guarantees:
23
-
24
- - `treeseed` is the only supported project-management surface for market and any checked-out `packages/sdk`, `packages/core`, and `packages/cli` repos.
25
- - `treeseed switch` requires clean worktrees, mirrors the task branch into checked-out package repos, and only pushes the market branch on branch creation.
26
- - `treeseed save` is the canonical recursive checkpoint command: it verifies, commits, and pushes dirty package repos in dependency order before saving the market repo.
27
- - `treeseed stage` squash-merges task branches into `staging` across package repos first, refreshes market submodule pointers to package `staging` heads, then stages the market repo.
28
- - `treeseed close` recursively archives and deletes matching task branches across market and checked-out package repos.
29
- - `treeseed release` only bumps, tags, and publishes changed packages plus internal dependents, then syncs market production to package `main` heads.
30
- - Every mutating workflow command supports `--plan`; `--dry-run` is only an alias where it still exists for compatibility.
31
- - Interrupted workflow runs are journaled under `.treeseed/workflow`; use `treeseed recover` to inspect them and `treeseed resume <run-id>` to continue a resumable run.
32
-
33
- After installation, the published binary is available as:
24
+ After installation:
34
25
 
35
26
  ```bash
36
27
  treeseed --help
28
+ trsd --help
37
29
  ```
38
30
 
39
- ## Primary Workflow
40
-
41
- The main workflow commands exposed by the current CLI are:
31
+ In this workspace, use `npx trsd ...` from the root.
42
32
 
43
- - `treeseed status [--json]`
44
- - `treeseed config`
45
- - `treeseed tasks [--json]`
46
- - `treeseed switch <branch-name> [--preview]`
47
- - `treeseed dev`
48
- - `treeseed dev start|status|logs|stop|restart`
49
- - `treeseed save [--preview] [--plan] "<commit message>"`
50
- - `treeseed stage "<resolution message>"`
51
- - `treeseed close "<close reason>"`
52
- - `treeseed release --major|--minor|--patch [--plan]`
53
- - `treeseed resume <run-id>`
54
- - `treeseed recover`
55
- - `treeseed destroy --environment <local|staging|prod> [--plan]`
56
-
57
- Support utilities such as `treeseed rollback`, `treeseed doctor`, `treeseed auth:*`, `treeseed template`, `treeseed sync`, `treeseed lint`, `treeseed test`, `treeseed build`, service helpers, and `treeseed agents ...` remain available.
58
-
59
- Use `treeseed help` for the full command list and `treeseed help <command>` for command-specific usage, options, and examples.
60
-
61
- ## Common Commands
33
+ ## Primary Commands
62
34
 
63
35
  ```bash
64
- treeseed status
65
- treeseed config
66
- treeseed switch feature/search-improvements --plan
67
- treeseed switch feature/search-improvements --preview
68
- treeseed dev
69
- treeseed dev start --web-runtime local
70
- treeseed save --preview "feat: add search filters"
71
- treeseed stage "feat: add search filters"
72
- treeseed release --patch
73
- treeseed recover
74
36
  treeseed status --json
37
+ treeseed config
38
+ treeseed ready local --json
39
+ treeseed switch feature/my-change --plan --json
40
+ treeseed dev start --web-runtime local --json
41
+ treeseed save --verify local --json "describe the checkpoint"
42
+ treeseed stage --plan --json "describe the staging change"
43
+ treeseed release --patch --verify-deployed-resources --plan --json
44
+ treeseed recover --json
75
45
  ```
76
46
 
77
- ## Development Server Instances
78
-
79
- `treeseed dev` remains the foreground local runtime supervisor. It delegates to `@treeseed/core`, starts the Market web/API/control-plane development surface, streams output in the active terminal, and exits when the shell-owned process is stopped.
80
-
81
- Managed dev instances use subcommands:
47
+ Hosted diagnostics:
82
48
 
83
49
  ```bash
84
- treeseed dev start --web-runtime local --json
85
- treeseed dev status --json
86
- treeseed dev status --all --json
87
- treeseed dev logs --follow
88
- treeseed dev stop --json
89
- treeseed dev restart --web-runtime local --json
50
+ treeseed ready staging --json
51
+ treeseed hosting plan --environment staging --service api --json
52
+ treeseed hosting verify --environment staging --service operationsRunner --live --json
53
+ treeseed operations smoke --environment staging --service operationsRunner --json
90
54
  ```
91
55
 
92
- Managed instances are scoped to the current physical worktree. The core runtime writes `.treeseed/dev/instances/<scope>.json`, `.treeseed/dev/pids/<scope>.pid`, and `.treeseed/logs/dev-<scope>.jsonl` in that worktree. A repository-family index under the git common dir makes sibling worktree instances discoverable to humans and AI agents.
93
-
94
- `--force` replaces only the current worktree instance. `--force-conflicts` is the explicit cross-worktree port-owner escape hatch. Additional worktrees receive stable alternate port blocks and worktree-specific local PostgreSQL/Mailpit names, so many agents can run development sessions in the same repository family.
95
-
96
- For the complete architecture, see the root workspace document `docs/local-dev-instances.md`.
97
-
98
- ## Agent-Safe Workflow
99
-
100
- Use planning mode before any destructive or multi-repo mutation:
56
+ Capacity providers:
101
57
 
102
58
  ```bash
103
- treeseed switch feature/search-improvements --plan --json
104
- treeseed save --plan "feat: add search filters" --json
105
- treeseed stage --plan "feat: add search filters" --json
106
- treeseed release --patch --plan --json
59
+ treeseed capacity build
60
+ treeseed capacity up
61
+ treeseed capacity status
62
+ treeseed capacity logs
63
+ treeseed capacity down
107
64
  ```
108
65
 
109
- If a workflow stops partway through, inspect the journaled state and resume from the recorded run:
66
+ TreeDX package image:
110
67
 
111
68
  ```bash
112
- treeseed recover
113
- treeseed resume <run-id>
69
+ treeseed package image --package treedx --branch staging --plan --json
70
+ treeseed package image --package treedx --branch staging --sync-config --json
71
+ treeseed package image --package treedx --branch staging --execute --json
114
72
  ```
115
73
 
116
- In a full checked-out workspace, `treeseed tasks`, `treeseed status`, and `treeseed doctor` also report package-branch drift, dirty embedded repos, active workflow locks, and interrupted runs.
74
+ Use `treeseed help <command>` for command-specific usage and examples.
117
75
 
118
- ## Maintainer Workflow
76
+ ## Managed Package Set
119
77
 
120
- All package maintenance commands are npm-based and run from the `cli/` package root. This package verifies the published command surface, parser/help behavior, and packaged artifact shape.
78
+ The CLI coordinates the root market repo plus checked-out package repositories:
121
79
 
122
- Install dependencies:
80
+ - `@treeseed/sdk`
81
+ - `@treeseed/ui`
82
+ - `@treeseed/core`
83
+ - `@treeseed/admin`
84
+ - `@treeseed/api`
85
+ - `@treeseed/cli`
86
+ - `@treeseed/agent`
87
+ - `packages/treedx`
123
88
 
124
- ```bash
125
- npm install
126
- ```
89
+ Workflow commands save package repos in dependency order, update submodule pointers, verify package release gates, and avoid one-off provider mutation.
127
90
 
128
- Build the published package output:
91
+ ## Save, Stage, And Release
92
+
93
+ `treeseed save` is the default checkpoint command. It saves dirty package repositories first, restores workspace links, performs lightweight release-candidate validation, and then saves the root market repo.
129
94
 
130
95
  ```bash
131
- npm run build
96
+ treeseed save --json "describe the checkpoint"
97
+ treeseed save --verify local --json "describe the checkpoint"
98
+ treeseed save --lane promotion --json "describe the checkpoint"
132
99
  ```
133
100
 
134
- Run the package test suite:
101
+ `treeseed stage` and `treeseed release` are promotion-grade commands. Use `--plan` before risky operations:
135
102
 
136
103
  ```bash
137
- npm test
104
+ treeseed stage --plan --json "describe the staging change"
105
+ treeseed release --patch --verify-deployed-resources --plan --json
138
106
  ```
139
107
 
140
- Run full release verification:
108
+ Interrupted workflow runs are journaled under `.treeseed/workflow`:
141
109
 
142
110
  ```bash
143
- npm run release:verify
111
+ treeseed recover --json
112
+ treeseed resume <run-id> --json
144
113
  ```
145
114
 
146
- The release verification flow is intentionally stricter than a normal test run:
115
+ ## How CLI Fits With Other Packages
147
116
 
148
- 1. Build `dist`
149
- 2. Validate publishable output for forbidden workspace references
150
- 3. Assert the published artifact only contains the thin wrapper entrypoints
151
- 4. Run the CLI wrapper test suite
152
- 5. Pack the CLI tarball
153
- 6. Smoke-test the packed install by running `treeseed --help` from the packed artifact
117
+ - `@treeseed/sdk` owns workflow, reconciliation, config, package discovery, and platform primitives.
118
+ - `@treeseed/core` owns the local web runtime used by `treeseed dev`.
119
+ - `@treeseed/admin` and `@treeseed/ui` are consumed by the web app; CLI does not own those routes or components.
120
+ - `@treeseed/api` owns backend API and operations-runner implementation.
121
+ - `@treeseed/agent` owns capacity-provider runtime artifacts that CLI starts or reconciles.
122
+ - TreeDX owns its service/image; CLI exposes package-image workflow commands.
154
123
 
155
- ## CI And Publishing
124
+ ## Package Development
156
125
 
157
- The GitHub Actions workflows under `.github/workflows/` assume this package is the repository root for the standalone CLI repository.
126
+ From this package root:
158
127
 
159
- - `ci.yml` uses `npm ci`, `npm run build`, `npm test`, and `npm run release:verify`
160
- - `publish.yml` uses the same verification path before publishing to npm
161
- - `publish.yml` validates that the pushed tag matches the package version before `npm publish`
162
-
163
- Release tags must use this format:
164
-
165
- ```text
166
- <version>
128
+ ```bash
129
+ npm install
130
+ npm run build
131
+ npm test
132
+ npm run release:verify
167
133
  ```
168
134
 
169
- For example, package version `0.1.0` publishes from tag `0.1.0`.
135
+ Release verification checks the packaged command surface, parser/help behavior, build output, and publishable artifact shape.
136
+
137
+ ## What CLI Does Not Own
170
138
 
171
- ## Notes
139
+ - SDK reconciliation internals
140
+ - Core web runtime internals
141
+ - Admin routes or UI components
142
+ - backend API implementation
143
+ - capacity-provider runtime implementation
144
+ - TreeDX service internals
145
+ - root market content or ecommerce
172
146
 
173
- - `package-lock.json` should be committed and kept current so `npm ci` remains reproducible in CI and release jobs.
174
- - The README intentionally documents the command surface at a high level. The canonical source of operation identity and semantics is `@treeseed/sdk`, while `@treeseed/cli` owns argv parsing, help rendering, and terminal formatting.
147
+ See the root [Package Ownership](../../docs/package-ownership.md) guide for cross-package boundaries.
@@ -1,4 +1,6 @@
1
1
  import {
2
+ collectTreeseedHostedServiceChecks,
3
+ collectTreeseedLiveHostedServiceChecks,
2
4
  formatTreeseedHostingAuditReport,
3
5
  runTreeseedHostingAudit
4
6
  } from "@treeseed/sdk/workflow-support";
@@ -45,12 +47,25 @@ const handleAudit = async (invocation, context) => {
45
47
  hostKinds: normalizeHostKinds(invocation.args.hostKinds ?? invocation.args.hosts),
46
48
  write: context.write
47
49
  });
50
+ const hostedTarget = report.environment === "prod" ? "prod" : report.environment === "local" ? "local" : "staging";
51
+ const hostedServices = invocation.args.live === true ? await collectTreeseedLiveHostedServiceChecks({
52
+ tenantRoot: context.cwd,
53
+ target: hostedTarget,
54
+ strict: false,
55
+ env: context.env
56
+ }) : collectTreeseedHostedServiceChecks({
57
+ tenantRoot: context.cwd,
58
+ target: hostedTarget
59
+ });
48
60
  const counts = statusCounts(report.checks);
49
61
  if (context.outputFormat === "json") {
50
62
  return {
51
63
  exitCode: report.ok ? 0 : 1,
52
64
  stdout: [],
53
- report
65
+ report: {
66
+ ...report,
67
+ hostedServices
68
+ }
54
69
  };
55
70
  }
56
71
  return guidedResult({
@@ -62,10 +77,20 @@ const handleAudit = async (invocation, context) => {
62
77
  { label: "Mode", value: report.repairMode ? "repair" : "read-only" },
63
78
  { label: "Passed", value: counts.passed ?? 0 },
64
79
  { label: "Warnings", value: (counts.warning ?? 0) + report.warnings.length },
65
- { label: "Failed", value: counts.failed ?? 0 }
80
+ { label: "Failed", value: counts.failed ?? 0 },
81
+ { label: "Hosted checks", value: `${hostedServices.summary.passed} passed, ${hostedServices.summary.warning} warnings, ${hostedServices.summary.failed} failed, ${hostedServices.summary.skipped} skipped` }
82
+ ],
83
+ sections: [
84
+ {
85
+ title: "Hosted service checks",
86
+ lines: hostedServices.checks.map((check) => `${check.provider} ${check.serviceKey ?? check.serviceType} ${check.description}: ${check.status}${check.issues.length ? ` (${check.issues.join("; ")})` : ""}`)
87
+ }
66
88
  ],
67
89
  nextSteps: report.nextActions,
68
- report,
90
+ report: {
91
+ ...report,
92
+ hostedServices
93
+ },
69
94
  exitCode: report.ok ? 0 : 1
70
95
  });
71
96
  } catch (error) {
@@ -378,7 +378,7 @@ function runLifecycleAction(action, invocation, context) {
378
378
  requireConnection: lifecycleActionRequiresConnection(action),
379
379
  overrides: {
380
380
  TREESEED_MARKET_URL: market.baseUrl,
381
- TREESEED_MARKET_ID: market.id,
381
+ TREESEED_MANAGER_ID: market.id,
382
382
  TREESEED_PROVIDER_HOST_DATA_DIR: resolvedHostDataDir,
383
383
  TREESEED_PROVIDER_ENVIRONMENT: providerSelector(invocation),
384
384
  ...diagnostic ? { TREESEED_PROVIDER_STARTUP_MODE: "diagnostic" } : {}
@@ -442,7 +442,7 @@ function invokeProviderEntrypoint(action, invocation, context) {
442
442
  env: {
443
443
  ...context.env,
444
444
  TREESEED_MARKET_URL: market.baseUrl,
445
- TREESEED_MARKET_ID: market.id,
445
+ TREESEED_MANAGER_ID: market.id,
446
446
  TREESEED_PROVIDER_ENVIRONMENT: providerSelector(invocation)
447
447
  },
448
448
  encoding: "utf8"
@@ -28,9 +28,11 @@ const handleDestroy = async (invocation, context) => {
28
28
  dryRun: invocation.args.dryRun === true,
29
29
  force: invocation.args.force === true,
30
30
  deleteData: invocation.args.deleteData === true,
31
+ sweepTreeseed: invocation.args.sweepTreeseed === true,
31
32
  removeBuildArtifacts: invocation.args.removeBuildArtifacts === true
32
33
  });
33
34
  const payload = result.payload;
35
+ const verification = payload.remoteResult?.verification ?? null;
34
36
  return guidedResult({
35
37
  command: invocation.commandName || "destroy",
36
38
  summary: result.executionMode === "plan" ? "Treeseed destroy plan ready." : "Treeseed destroy completed successfully.",
@@ -38,7 +40,10 @@ const handleDestroy = async (invocation, context) => {
38
40
  { label: "Environment", value: payload.scope },
39
41
  { label: "Dry run", value: payload.dryRun ? "yes" : "no" },
40
42
  { label: "Delete data", value: payload.deleteData ? "yes" : "no" },
41
- { label: "Removed build artifacts", value: payload.removeBuildArtifacts ? "yes" : "no" }
43
+ { label: "Sweep TreeSeed resources", value: payload.sweepTreeseed ? "yes" : "no" },
44
+ { label: "Removed build artifacts", value: payload.removeBuildArtifacts ? "yes" : "no" },
45
+ ...verification?.cloudflare ? [{ label: "Cloudflare remaining", value: String(verification.cloudflare.totalRemaining ?? 0) }] : [],
46
+ ...verification?.localDocker ? [{ label: "Local Docker remaining", value: String(verification.localDocker.totalRemaining ?? 0) }] : []
42
47
  ],
43
48
  nextSteps: renderWorkflowNextSteps(result),
44
49
  report: result
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
2
2
  import { createRequire } from "node:module";
3
3
  import { dirname, resolve } from "node:path";
4
4
  import { ensureLocalWorkspaceLinks, findNearestTreeseedWorkspaceRoot, resolveTreeseedLaunchEnvironment } from "@treeseed/sdk/workflow-support";
5
+ import { discoverTreeseedApplications } from "@treeseed/sdk/hosting";
5
6
  import { workflowErrorResult } from "./workflow.js";
6
7
  import { fail } from "./utils.js";
7
8
  const require2 = createRequire(import.meta.url);
@@ -52,12 +53,17 @@ const handleDev = async (invocation, context) => {
52
53
  }
53
54
  const feedback = typeof invocation.args.feedback === "string" ? invocation.args.feedback : void 0;
54
55
  const watch = feedback !== "off";
56
+ const appId = typeof invocation.args.app === "string" && invocation.args.app.trim() ? invocation.args.app.trim() : void 0;
57
+ const apiMode = typeof invocation.args.api === "string" && invocation.args.api.trim() ? invocation.args.api.trim() : "auto";
55
58
  const subcommand = typeof invocation.positionals[0] === "string" ? invocation.positionals[0] : "";
56
59
  const managedSubcommands = /* @__PURE__ */ new Set(["start", "status", "logs", "stop", "restart"]);
57
60
  if (subcommand && !managedSubcommands.has(subcommand)) {
58
61
  return fail(`Unknown dev subcommand "${subcommand}". Use start, status, logs, stop, or restart.`);
59
62
  }
60
- const passthroughArgs = ["--surfaces", "web,api"];
63
+ const discoveredApps = discoverTreeseedApplications(context.cwd);
64
+ const hasApiApp = discoveredApps.some((app) => app.id === "api");
65
+ const selectedSurfaces = appId === "api" ? "api" : appId === "web" || apiMode === "remote" ? "web" : hasApiApp ? "web,api" : "web";
66
+ const passthroughArgs = ["--surfaces", selectedSurfaces];
61
67
  const forwardStringOption = (name, flag) => {
62
68
  const value = invocation.args[name];
63
69
  if (typeof value === "string" && value.trim().length > 0) {
@@ -117,7 +123,15 @@ const handleDev = async (invocation, context) => {
117
123
  watch,
118
124
  executable: resolved.command,
119
125
  args,
120
- workspaceLinks
126
+ workspaceLinks,
127
+ appId: appId ?? null,
128
+ apiMode,
129
+ discoveredApps: discoveredApps.map((app) => ({
130
+ id: app.id,
131
+ relativeRoot: app.relativeRoot,
132
+ roles: app.roles
133
+ })),
134
+ selectedSurfaces
121
135
  }
122
136
  };
123
137
  } catch (error) {
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
- import { collectCliPreflight } from "@treeseed/sdk/workflow-support";
3
+ import { collectCliPreflight, collectTreeseedDeploymentReadiness, collectTreeseedHostedServiceChecks } from "@treeseed/sdk/workflow-support";
4
4
  import { guidedResult } from "./utils.js";
5
5
  import { applyTreeseedSafeRepairs } from "../repair.js";
6
6
  import { createWorkflowSdk, workflowErrorResult } from "./workflow.js";
@@ -8,6 +8,12 @@ const handleDoctor = async (invocation, context) => {
8
8
  try {
9
9
  const status = await createWorkflowSdk(context).status();
10
10
  const state = status.payload;
11
+ const hostedServices = invocation.args.live === true || invocation.args.hostedServices === true ? collectTreeseedHostedServiceChecks({
12
+ tenantRoot: context.cwd,
13
+ target: state.branchRole === "production" || state.branchName === "main" ? "prod" : state.branchRole === "staging" || state.branchName === "staging" ? "staging" : "local"
14
+ }) : null;
15
+ const hostedTarget = state.branchRole === "production" || state.branchName === "main" ? "prod" : state.branchRole === "staging" || state.branchName === "staging" ? "staging" : "local";
16
+ const deploymentReadiness = invocation.args.live === true || invocation.args.hostedServices === true ? collectTreeseedDeploymentReadiness({ tenantRoot: context.cwd, environment: hostedTarget }) : null;
11
17
  const performedFixes = invocation.args.fix === true && state.deployConfigPresent ? applyTreeseedSafeRepairs(state.cwd) : [];
12
18
  const preflight = collectCliPreflight({ cwd: context.cwd, requireAuth: false });
13
19
  const railwayManagedServicesEnabled = Object.values(state.managedServices).some((service) => service.enabled);
@@ -65,7 +71,9 @@ const handleDoctor = async (invocation, context) => {
65
71
  { label: "Optional follow-up", value: optional.length },
66
72
  { label: "Safe fixes applied", value: performedFixes.length },
67
73
  { label: "Branch", value: state.branchName ?? "(none)" },
68
- { label: "Workspace root", value: state.workspaceRoot ? "yes" : "no" }
74
+ { label: "Workspace root", value: state.workspaceRoot ? "yes" : "no" },
75
+ ...hostedServices ? [{ label: "Hosted checks", value: `${hostedServices.summary.passed} passed, ${hostedServices.summary.warning} warnings, ${hostedServices.summary.failed} failed, ${hostedServices.summary.skipped} skipped` }] : [],
76
+ ...deploymentReadiness ? [{ label: "Deployment readiness", value: `${deploymentReadiness.summary.passed} passed, ${deploymentReadiness.summary.failed} failed` }] : []
69
77
  ],
70
78
  nextSteps: [
71
79
  ...mustFixNow.map((item) => item),
@@ -77,7 +85,9 @@ const handleDoctor = async (invocation, context) => {
77
85
  preflight,
78
86
  performedFixes,
79
87
  mustFixNow,
80
- optional
88
+ optional,
89
+ hostedServices,
90
+ deploymentReadiness
81
91
  },
82
92
  exitCode: mustFixNow.length === 0 ? 0 : 1
83
93
  });
@@ -0,0 +1,2 @@
1
+ import type { TreeseedCommandHandler } from '../types.js';
2
+ export declare const handleHosting: TreeseedCommandHandler;