@sequenceholdings/studio-cli 0.1.22 → 0.1.24

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.
@@ -5,6 +5,20 @@ import { z } from 'zod';
5
5
  * as artifact-studio's duplicated manifest. Keep the two in sync.
6
6
  */
7
7
  export declare const MF_MANIFEST_FILENAME = "managed-function.yml";
8
+ export declare const managedFunctionAuthorizationAdapterSchema: z.ZodEnum<{
9
+ "encompass.loan-read-by-guid": "encompass.loan-read-by-guid";
10
+ "encompass.loan-read-by-number": "encompass.loan-read-by-number";
11
+ "encompass.loan-search": "encompass.loan-search";
12
+ }>;
13
+ export type ManagedFunctionAuthorizationAdapter = z.infer<typeof managedFunctionAuthorizationAdapterSchema>;
14
+ export declare const managedFunctionAuthorizationSchema: z.ZodObject<{
15
+ version: z.ZodLiteral<1>;
16
+ adapter: z.ZodEnum<{
17
+ "encompass.loan-read-by-guid": "encompass.loan-read-by-guid";
18
+ "encompass.loan-read-by-number": "encompass.loan-read-by-number";
19
+ "encompass.loan-search": "encompass.loan-search";
20
+ }>;
21
+ }, z.core.$strict>;
8
22
  /**
9
23
  * CLI-side copy of the server's egress entry validation (see
10
24
  * atlas/src/server/services/managed-functions/egress.ts). Returns the
@@ -59,6 +73,14 @@ export declare const managedFunctionManifestSchema: z.ZodObject<{
59
73
  secrets: z.ZodDefault<z.ZodArray<z.ZodString>>;
60
74
  egress: z.ZodDefault<z.ZodArray<z.ZodString>>;
61
75
  service_account: z.ZodOptional<z.ZodString>;
76
+ authorization: z.ZodOptional<z.ZodObject<{
77
+ version: z.ZodLiteral<1>;
78
+ adapter: z.ZodEnum<{
79
+ "encompass.loan-read-by-guid": "encompass.loan-read-by-guid";
80
+ "encompass.loan-read-by-number": "encompass.loan-read-by-number";
81
+ "encompass.loan-search": "encompass.loan-search";
82
+ }>;
83
+ }, z.core.$strict>>;
62
84
  input_schema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
63
85
  output_schema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
64
86
  capabilities: z.ZodDefault<z.ZodObject<{
@@ -6,6 +6,22 @@ import { z } from 'zod';
6
6
  */
7
7
  export const MF_MANIFEST_FILENAME = 'managed-function.yml';
8
8
  const SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
9
+ export const managedFunctionAuthorizationAdapterSchema = z.enum([
10
+ 'encompass.loan-read-by-guid',
11
+ 'encompass.loan-read-by-number',
12
+ 'encompass.loan-search',
13
+ ]);
14
+ export const managedFunctionAuthorizationSchema = z
15
+ .object({
16
+ version: z.literal(1),
17
+ adapter: managedFunctionAuthorizationAdapterSchema,
18
+ })
19
+ .strict();
20
+ const AUTHORIZATION_ADAPTER_BY_FUNCTION_ID = {
21
+ 'encompass-get-common-loan-fields': 'encompass.loan-read-by-guid',
22
+ 'encompass-get-loan-by-number': 'encompass.loan-read-by-number',
23
+ 'encompass-search-pipeline': 'encompass.loan-search',
24
+ };
9
25
  /** RFC 1035 label: alnum, optional inner dashes, max 63 chars. */
10
26
  const DNS_LABEL_RE = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
11
27
  /**
@@ -571,6 +587,11 @@ export const managedFunctionManifestSchema = z.object({
571
587
  .string()
572
588
  .regex(SERVICE_ACCOUNT_REF_RE, 'service_account must be a platform service-account slug (lowercase alphanumeric with hyphens) or uuid')
573
589
  .optional(),
590
+ /**
591
+ * Server-owned resource authorization. Authors select a reviewed adapter;
592
+ * they cannot provide input/output paths or executable policy.
593
+ */
594
+ authorization: managedFunctionAuthorizationSchema.optional(),
574
595
  input_schema: z.record(z.string(), z.unknown()).optional(),
575
596
  output_schema: z.record(z.string(), z.unknown()).optional(),
576
597
  /**
@@ -616,6 +637,30 @@ export const managedFunctionManifestSchema = z.object({
616
637
  .default({}),
617
638
  }).default({ uses: [], gates: [], data: {} }),
618
639
  }).superRefine((manifest, ctx) => {
640
+ const expectedAdapter = AUTHORIZATION_ADAPTER_BY_FUNCTION_ID[manifest.function.id];
641
+ if (expectedAdapter !== undefined && manifest.authorization === undefined) {
642
+ ctx.addIssue({
643
+ code: 'custom',
644
+ message: `function "${manifest.function.id}" requires authorization adapter "${expectedAdapter}"`,
645
+ path: ['authorization'],
646
+ });
647
+ }
648
+ else if (expectedAdapter !== undefined &&
649
+ manifest.authorization?.adapter !== expectedAdapter) {
650
+ ctx.addIssue({
651
+ code: 'custom',
652
+ message: `function "${manifest.function.id}" must use authorization adapter "${expectedAdapter}"`,
653
+ path: ['authorization', 'adapter'],
654
+ });
655
+ }
656
+ else if (expectedAdapter === undefined &&
657
+ manifest.authorization !== undefined) {
658
+ ctx.addIssue({
659
+ code: 'custom',
660
+ message: `function "${manifest.function.id}" is not registered for a server-owned authorization adapter`,
661
+ path: ['authorization'],
662
+ });
663
+ }
619
664
  for (const message of validateCapabilityPins({
620
665
  uses: manifest.capabilities.uses,
621
666
  roles: manifest.capabilities.roles,
package/dist/main.d.ts CHANGED
@@ -2,6 +2,9 @@
2
2
  * seq-studio argv router.
3
3
  *
4
4
  * Top-level commands:
5
+ * seq-studio init scaffold an app monorepo (sequence.app.yml)
6
+ * seq-studio add add a primitive to an app monorepo
7
+ * seq-studio deploy deploy all primitives from sequence.app.yml
5
8
  * seq-studio process <sub> manage Lattice processes
6
9
  * seq-studio artifact <sub> manage Artifact Studio apps
7
10
  * seq-studio functions <sub> manage Managed Functions
package/dist/main.js CHANGED
@@ -2,6 +2,9 @@
2
2
  * seq-studio argv router.
3
3
  *
4
4
  * Top-level commands:
5
+ * seq-studio init scaffold an app monorepo (sequence.app.yml)
6
+ * seq-studio add add a primitive to an app monorepo
7
+ * seq-studio deploy deploy all primitives from sequence.app.yml
5
8
  * seq-studio process <sub> manage Lattice processes
6
9
  * seq-studio artifact <sub> manage Artifact Studio apps
7
10
  * seq-studio functions <sub> manage Managed Functions
@@ -21,6 +24,9 @@ import { applyCommand, bundleCommand, doctorCommand, initCommand, lintCommand, p
21
24
  // Lazy-load artifact delegate: published @sequenceholdings/artifact-studio/cli
22
25
  // still auto-runs runCli() at module load; importing it here breaks doctor/process.
23
26
  const TOP_LEVEL_USAGE = `usage:
27
+ seq-studio init <dir> --with <kinds> scaffold an app monorepo (sequence.app.yml)
28
+ seq-studio add <kind> <name> add a primitive to the current app monorepo
29
+ seq-studio deploy -e <env> deploy primitives from sequence.app.yml
24
30
  seq-studio process <sub> [args] lint | plan | apply | test | simulate | bundle | init
25
31
  seq-studio artifact <sub> [args] init | build | plan | deploy | dev | list | show | pull | promote | rollback
26
32
  seq-studio functions <sub> [args] init | build | deploy | list | show | logs | promote | rollback | delete
@@ -65,6 +71,21 @@ export async function run(argv = process.argv.slice(2)) {
65
71
  return namespace ? 0 : 1;
66
72
  }
67
73
  switch (namespace) {
74
+ case 'init': {
75
+ const { runAppInitCommand } = await import('./app/commands.js');
76
+ return runAppInitCommand(parseArgs([sub, ...rest].filter((a) => Boolean(a))));
77
+ }
78
+ case 'add': {
79
+ const { runAppAddCommand } = await import('./app/commands.js');
80
+ return runAppAddCommand({
81
+ kindArg: sub,
82
+ args: parseArgs(rest),
83
+ });
84
+ }
85
+ case 'deploy': {
86
+ const { runAppDeployCommand } = await import('./app/commands.js');
87
+ return runAppDeployCommand(parseArgs([sub, ...rest].filter((a) => Boolean(a))));
88
+ }
68
89
  case 'process':
69
90
  return runProcessNamespace(sub, rest);
70
91
  case 'artifact': {
@@ -0,0 +1,2 @@
1
+ import type { ParsedArgs } from '../process/commands.js';
2
+ export declare function pipelineCodegenTablesCommand(args: ParsedArgs): Promise<number>;
@@ -0,0 +1,118 @@
1
+ /**
2
+ * `seq-studio pipeline codegen tables` — emit one `.stage.yml` per table from a
3
+ * typed TypeScript authoring module (SEQ-2485).
4
+ */
5
+ import { mkdir, writeFile } from 'node:fs/promises';
6
+ import { existsSync } from 'node:fs';
7
+ import { join, resolve } from 'node:path';
8
+ import { pathToFileURL } from 'node:url';
9
+ import { tsImport } from 'tsx/esm/api';
10
+ const LOG = '[seq-studio]';
11
+ function isAuthoring(value) {
12
+ if (!value || typeof value !== 'object')
13
+ return false;
14
+ const record = value;
15
+ return (typeof record.stagePrefix === 'string' &&
16
+ typeof record.runtime === 'string' &&
17
+ typeof record.entrypoint === 'string' &&
18
+ Array.isArray(record.owners) &&
19
+ Array.isArray(record.tables));
20
+ }
21
+ function findAuthoringExport(value) {
22
+ if (isAuthoring(value))
23
+ return value;
24
+ if (!value || typeof value !== 'object')
25
+ return null;
26
+ const record = value;
27
+ for (const key of ['default', 'authoring', 'silverlakeAuthoring']) {
28
+ const nested = record[key];
29
+ if (isAuthoring(nested))
30
+ return nested;
31
+ }
32
+ return null;
33
+ }
34
+ async function loadAuthoringModule(fromPath) {
35
+ const absolute = resolve(fromPath);
36
+ if (!existsSync(absolute)) {
37
+ throw new Error(`authoring module not found: ${absolute}`);
38
+ }
39
+ const loaded = await tsImport(pathToFileURL(absolute).href, import.meta.url);
40
+ if (!loaded || typeof loaded !== 'object') {
41
+ throw new Error(`authoring module '${absolute}' did not export an object`);
42
+ }
43
+ const record = loaded;
44
+ const candidate = findAuthoringExport(record.default) ??
45
+ findAuthoringExport(record.authoring) ??
46
+ findAuthoringExport(record.silverlakeAuthoring);
47
+ if (!candidate) {
48
+ throw new Error(`authoring module '${absolute}' must export default, authoring, or silverlakeAuthoring ` +
49
+ `as a PerTableIngestionAuthoring object (exports: ${Object.keys(record).join(', ')})`);
50
+ }
51
+ return candidate;
52
+ }
53
+ export async function pipelineCodegenTablesCommand(args) {
54
+ const spec = await import('@sequenceholdings/pipeline-spec');
55
+ const from = typeof args.flags.from === 'string'
56
+ ? args.flags.from
57
+ : join(process.cwd(), 'authoring.tables.ts');
58
+ const dir = resolve(typeof args.flags.dir === 'string' ? args.flags.dir : '.');
59
+ const dryRun = args.flags['dry-run'] === true;
60
+ let authoring;
61
+ try {
62
+ authoring = await loadAuthoringModule(from);
63
+ }
64
+ catch (error) {
65
+ console.error(`${LOG} ${error instanceof Error ? error.message : String(error)}`);
66
+ console.error('usage: seq-studio pipeline codegen tables --from <authoring.ts> [--dir <dir>] [--dry-run]');
67
+ return 1;
68
+ }
69
+ const files = spec.generatePerTableStageFiles(authoring);
70
+ const parseErrors = [];
71
+ for (const file of files) {
72
+ const parsed = spec.stageSpecSchema.safeParse(file.spec);
73
+ if (!parsed.success) {
74
+ parseErrors.push(`${file.filename}: ${parsed.error.message}`);
75
+ }
76
+ }
77
+ if (parseErrors.length > 0) {
78
+ console.error(`${LOG} generated specs failed schema validation:`);
79
+ for (const line of parseErrors)
80
+ console.error(` ${line}`);
81
+ return 1;
82
+ }
83
+ if (dryRun) {
84
+ console.log(`${LOG} dry-run: would write ${files.length} stage file(s) to ${dir}`);
85
+ for (const file of files)
86
+ console.log(` ${file.filename}`);
87
+ return 0;
88
+ }
89
+ const targets = files.map((file) => ({
90
+ file,
91
+ target: join(dir, file.filename),
92
+ }));
93
+ const seenTargets = new Set();
94
+ const duplicateTarget = targets.find(({ target }) => {
95
+ if (seenTargets.has(target))
96
+ return true;
97
+ seenTargets.add(target);
98
+ return false;
99
+ });
100
+ if (duplicateTarget) {
101
+ console.error(`${LOG} duplicate output target ${duplicateTarget.target}`);
102
+ return 1;
103
+ }
104
+ if (args.flags.force !== true) {
105
+ const existingTarget = targets.find(({ target }) => existsSync(target));
106
+ if (existingTarget) {
107
+ console.error(`${LOG} ${existingTarget.target} already exists — pass --force to overwrite`);
108
+ return 1;
109
+ }
110
+ }
111
+ await mkdir(dir, { recursive: true });
112
+ for (const { file, target } of targets) {
113
+ await writeFile(target, file.yaml, 'utf8');
114
+ console.log(`${LOG} wrote ${target}`);
115
+ }
116
+ console.log(`${LOG} next: seq-studio pipeline validate ${dir === process.cwd() ? '.' : dir}`);
117
+ return 0;
118
+ }
@@ -12,6 +12,8 @@
12
12
  * the CLI without the package get a clear install hint instead of a crash.
13
13
  */
14
14
  import type { ParsedArgs } from '../process/commands.js';
15
+ /** Conventional ORM contract catalog filename beside stage specs (CI auto-loads this). */
16
+ export declare const ORM_CONTRACTS_FILENAME = "orm-contracts.json";
15
17
  /**
16
18
  * Same classification as the orm delegate: is the pipeline-spec package
17
19
  * itself absent (installable) or did one of its dependencies fail to load?
@@ -53,6 +55,11 @@ export declare function buildExternalAssetsRequest({ source, knownOrigins, token
53
55
  export declare function configuredEnvOrigins(envs: Readonly<Record<string, {
54
56
  url: string;
55
57
  }>>): string[];
58
+ /** Resolve ORM contracts from --orm-contracts or conventional orm-contracts.json. */
59
+ export declare function resolveOrmContractsPath({ dir, flag, }: {
60
+ dir: string;
61
+ flag: unknown;
62
+ }): string | undefined;
56
63
  export declare function pipelineValidateCommand(args: ParsedArgs): Promise<number>;
57
64
  export declare function runPipelineCommand(sub: string | undefined, args: ParsedArgs): Promise<number>;
58
65
  export {};
@@ -19,52 +19,68 @@ import { tryGetAccessToken } from '../auth.js';
19
19
  import { readConfig } from '../config.js';
20
20
  import { renderEntrypointStub, renderStageTemplate, STAGE_TYPES, } from './templates.js';
21
21
  const LOG = '[seq-studio]';
22
+ /** Conventional ORM contract catalog filename beside stage specs (CI auto-loads this). */
23
+ export const ORM_CONTRACTS_FILENAME = 'orm-contracts.json';
22
24
  const PIPELINE_USAGE = `usage:
23
25
  seq-studio pipeline init --type ingestion|transformation|serving <name> [--dir <dir>]
24
26
  scaffold <name>.stage.yml (commented template) + src/ entrypoint stub
25
27
 
26
- seq-studio pipeline validate [dir] [--assets <file|url>] [--json]
28
+ seq-studio pipeline validate [dir] [--assets <file|url>] [--orm-contracts <file|url>] [--json]
27
29
  run the offline spec gate: envelope + body validation, schema_ref
28
30
  resolution, and repo-level graph validation (references, single-writer,
29
31
  cycles, column subsets). --assets supplies a registry asset export for
30
- cross-Pipeline references. Exits 1 on any error-severity finding.
32
+ cross-Pipeline references; --orm-contracts (or orm-contracts.json in dir)
33
+ supplies ORM synced-table contracts for serving satisfies pins. Exits 1 on
34
+ any error-severity finding.
31
35
 
32
- seq-studio pipeline plan --repo pipelines/<slug> --ref <sha|branch> -e <env> [--json]
36
+ seq-studio pipeline codegen tables [--from <authoring.ts>] [--dir <dir>] [--dry-run] [--force]
37
+ emit one <stage>.stage.yml per table from a typed PerTableIngestionAuthoring
38
+ module (default export, authoring, or silverlakeAuthoring export name)
39
+
40
+ seq-studio pipeline plan --repo pipelines/<slug> --ref <sha|branch> -e <env> [--target <id>] [--json]
33
41
  materialize + SDK/graph + compile + live-diff + provision findings
34
42
  (no Databricks CLI / DAB validate on Atlas); exit 1 on destructive findings
35
43
 
36
- seq-studio pipeline deploy --repo pipelines/<slug> --ref <sha> -e <env>
37
- [--approved-by <sub>] [--no-wait] [--json]
44
+ seq-studio pipeline deploy --repo pipelines/<slug> --ref <sha|branch> -e <env>
45
+ [--target <id>] [--approved-by <sub>] [--no-wait] [--json]
38
46
  plan then enqueue Trigger deploy (DAB bundle validate hard-gates before
39
- bundle deploy); production/banksouth require a pinned 40-hex SHA
47
+ bundle deploy); use a full 40-hex SHA for explicit rollback deployments
40
48
 
41
49
  seq-studio pipeline promote --stage <slug> --version <v> -e <env>
42
- [--repo pipelines/<slug>] [--approved-by <you>] [--no-wait]
50
+ [--target <id>] [--repo pipelines/<slug>] [--approved-by <you>] [--no-wait]
43
51
  promote a validated version to the next environment (approvals are
44
52
  self-recorded: --approved-by must name the authenticated caller)
45
53
 
46
- seq-studio pipeline rollback --stage <slug> -e <env> [--repo pipelines/<slug>]
54
+ seq-studio pipeline rollback --stage <slug> -e <env> [--target <id>] [--repo pipelines/<slug>]
47
55
  [--approved-by <you>] [--no-wait]
48
56
  redeploy the previously retired deployment's version (production/
49
57
  banksouth require --approved-by — approvals are explicit even for
50
58
  rollbacks)
51
59
 
60
+ Unless --no-wait is set, deploy, promote, and rollback report status or
61
+ status-detail changes while waiting, then emit a 20-second progress heartbeat.
62
+ Terminal output includes the deployment id and elapsed time; it also includes
63
+ a Trigger run id when the deployment provides one.
64
+
52
65
  seq-studio pipeline adopt --stage <slug> --ref <sha|branch> -e <env>
53
- --native-id <id> [--resource-key <key>] [--kind job|dlt_pipeline]
66
+ [--target <id>] --native-id <id> [--resource-key <key>] [--kind job|dlt_pipeline]
54
67
  --approved-by <you> [--old-source-removal-pr <url>]
55
68
  [--repo pipelines/<slug>] [--json]
56
69
  bind a live Databricks job/pipeline to the stage without recreation
57
70
  (SEQ-2449). Always requires --approved-by. Monorepo-declared keys also
58
71
  require --old-source-removal-pr.
59
72
 
60
- seq-studio pipeline unbind --stage <slug> --ref <sha|branch> -e <env>
73
+ seq-studio pipeline unbind --stage <slug> --ref <sha|branch> -e <env> [--target <id>]
61
74
  --approved-by <you> [--resource-key <key>]
62
75
  [--repo pipelines/<slug>] [--json]
63
76
  release an adopted binding; the remote object stays live (never deleted)
64
77
 
65
- seq-studio pipeline run-now --stage <slug> -e <env> [--repo pipelines/<slug>] [--json]
78
+ seq-studio pipeline run-now --stage <slug> -e <env> [--target <id>] [--repo pipelines/<slug>] [--json]
66
79
  fire the stage's active deployment resource (job run-now / DLT
67
80
  start_update) and print the Databricks run URL
81
+
82
+ -e/--env selects the Atlas connection. --target selects the logical target
83
+ advertised by that deployment; it is inferred when the endpoint exposes one target.
68
84
  `;
69
85
  /**
70
86
  * Same classification as the orm delegate: is the pipeline-spec package
@@ -225,6 +241,34 @@ async function loadExternalAssets(spec, source) {
225
241
  }
226
242
  return spec.externalAssetsExportSchema.parse(JSON.parse(raw));
227
243
  }
244
+ async function loadOrmContracts(spec, source) {
245
+ let raw;
246
+ if (/^https?:\/\//.test(source)) {
247
+ const config = await readConfig();
248
+ const token = await tryGetAccessToken();
249
+ const request = buildExternalAssetsRequest({
250
+ source,
251
+ knownOrigins: configuredEnvOrigins(config.envs),
252
+ token,
253
+ });
254
+ const response = await fetch(request.url, request.init);
255
+ if (!response.ok) {
256
+ throw new Error(`fetching ORM contracts catalog failed: ${response.status} ${response.statusText}`);
257
+ }
258
+ raw = await response.text();
259
+ }
260
+ else {
261
+ raw = await readFile(resolve(source), 'utf8');
262
+ }
263
+ return spec.ormContractCatalogSchema.parse(JSON.parse(raw));
264
+ }
265
+ /** Resolve ORM contracts from --orm-contracts or conventional orm-contracts.json. */
266
+ export function resolveOrmContractsPath({ dir, flag, }) {
267
+ if (typeof flag === 'string')
268
+ return flag;
269
+ const conventional = join(dir, ORM_CONTRACTS_FILENAME);
270
+ return existsSync(conventional) ? conventional : undefined;
271
+ }
228
272
  function printHumanReport(report) {
229
273
  for (const finding of report.findings) {
230
274
  const prefix = finding.severity === 'error' ? 'error' : 'warning';
@@ -296,7 +340,28 @@ export async function pipelineValidateCommand(args) {
296
340
  });
297
341
  }
298
342
  }
299
- const result = spec.validateSpecGraph(pipeline.stages, externalAssets);
343
+ let ormContracts;
344
+ const ormContractsPath = resolveOrmContractsPath({ dir, flag: args.flags['orm-contracts'] });
345
+ if (ormContractsPath) {
346
+ try {
347
+ ormContracts = await loadOrmContracts(spec, ormContractsPath);
348
+ }
349
+ catch (error) {
350
+ return emit({
351
+ ok: false,
352
+ dir: dirArg,
353
+ stages: pipeline.stages.map((stage) => stage.stage),
354
+ findings: [
355
+ {
356
+ severity: 'error',
357
+ code: 'orm_contracts_unreadable',
358
+ message: error instanceof Error ? error.message : String(error),
359
+ },
360
+ ],
361
+ });
362
+ }
363
+ }
364
+ const result = spec.validateSpecGraph(pipeline.stages, externalAssets, ormContracts !== undefined ? { ormContracts } : undefined);
300
365
  return emit({
301
366
  ok: result.ok,
302
367
  dir: dirArg,
@@ -310,6 +375,15 @@ export async function runPipelineCommand(sub, args) {
310
375
  return pipelineInitCommand(args);
311
376
  case 'validate':
312
377
  return pipelineValidateCommand(args);
378
+ case 'codegen': {
379
+ const codegenSub = args.positional[0];
380
+ if (codegenSub === 'tables') {
381
+ const { pipelineCodegenTablesCommand } = await import('./codegen.js');
382
+ return pipelineCodegenTablesCommand({ ...args, positional: args.positional.slice(1) });
383
+ }
384
+ console.error(`${LOG} unknown pipeline codegen target '${codegenSub ?? ''}' — expected: tables`);
385
+ return 1;
386
+ }
313
387
  case 'adopt': {
314
388
  const { pipelineAdoptCommand } = await import('./lifecycle.js');
315
389
  return pipelineAdoptCommand(args);
@@ -37,19 +37,8 @@ export interface DeploymentDetail {
37
37
  id: string;
38
38
  status: string;
39
39
  statusDetail: string | null;
40
+ triggerRunId?: string | null;
40
41
  }
41
- /**
42
- * The CLI's local dev-loop env is named `local` — chosen so `-e local` lines
43
- * up with `seqapi -e local` / `artifact-studio --env local` (see `config.ts`
44
- * `BUILT_IN_ENV_URLS`). There is no `local` in the server's deploy-lifecycle
45
- * enum (`DEPLOY_ENVIRONMENTS` in `atlas/src/server/services/data-pipelines/schema.ts`
46
- * is `dev | staging | production | banksouth`); the server's name for that
47
- * same developer-loop target is `dev` (`targetFactsForEnvironment` treats
48
- * `dev` as the one target exempt from a `lakebase_branch` binding). Map at
49
- * this one boundary — every lifecycle request body funnels through here —
50
- * so the CLI never sends the wire-invalid `local` and every other env name
51
- * passes through unchanged.
52
- */
53
42
  export declare function deployEnvironmentForEnv(env: ResolvedEnv): string;
54
43
  export declare function pipelinePlanCommand(args: ParsedArgs): Promise<number>;
55
44
  export declare function pipelineDeployCommand(args: ParsedArgs): Promise<number>;