@tomflow/proflow-platform-cli 0.1.28 → 0.1.30

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/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @tomflow/proflow-platform-cli
2
+
3
+ ## 0.1.30
4
+
5
+ ### Patch Changes
6
+
7
+ - Use a stable progress marker in non-interactive logs instead of a frozen spinner frame.
8
+
9
+ ## 0.1.29
10
+
11
+ ### Patch Changes
12
+
13
+ - Improve terminal progress and localized status output, publish readable Chinese module docs, and add guided setup assistants for external resources.
package/DOCS.md CHANGED
@@ -1,27 +1,11 @@
1
- # @tomflow/proflow-platform-cli — Module Docs
1
+ # platform-cli
2
2
 
3
- Module ref: `platform-cli`
4
- Domain: `deployment-governance`
5
- Kind: `cli`
3
+ Platform CLI(平台命令行)是 ProFlow 的统一管理入口,负责发现模块、安装依赖、汇总状态和按依赖顺序启动或停止模块。
6
4
 
7
- Thin Platform CLI for Module discovery, documentation, package synchronization and lifecycle orchestration.
5
+ ## 推荐流程
8
6
 
9
- ## Standard management surface
7
+ `platform install` `platform status` → `platform docs` → `platform setup` → `platform start`
10
8
 
11
- `install / uninstall / status / setup / docs / start / stop`
9
+ ## 边界
12
10
 
13
- ## Provides
14
-
15
- - None.
16
-
17
- ## Requires
18
-
19
- - None.
20
-
21
- ## Public setup inputs
22
-
23
- - None. Deterministic/private values and cross-Module shared facts are not public configuration.
24
-
25
- ## Ownership boundary
26
-
27
- Module business APIs and any module-specific extra commands remain package-owned. Platform does not proxy or interpret them. Current human/external preparation is documented in `SETUP.md`.
11
+ Platform CLI 只负责调用和汇总,不读取模块私有配置,也不替模块解释外部服务。具体配置由对应模块的 Setup(配置向导)完成。
@@ -6,7 +6,7 @@ export declare const behaviorAdapter: {
6
6
  readonly ok: true;
7
7
  readonly status: "SUCCEEDED";
8
8
  readonly moduleRef: "platform-cli";
9
- readonly moduleVersion: "0.1.28";
9
+ readonly moduleVersion: "0.1.30";
10
10
  };
11
11
  observedEffects: never[];
12
12
  }>;
@@ -16,7 +16,7 @@ export declare const behaviorAdapter: {
16
16
  readonly ok: true;
17
17
  readonly status: "SUCCEEDED";
18
18
  readonly moduleRef: "platform-cli";
19
- readonly moduleVersion: "0.1.28";
19
+ readonly moduleVersion: "0.1.30";
20
20
  };
21
21
  observedEffects: never[];
22
22
  }>;
@@ -26,7 +26,7 @@ export declare const behaviorAdapter: {
26
26
  ok: true;
27
27
  status: "SUCCEEDED";
28
28
  moduleRef: "platform-cli";
29
- moduleVersion: "0.1.28";
29
+ moduleVersion: "0.1.30";
30
30
  data: {
31
31
  readonly setupStatus: "READY";
32
32
  readonly runtimeStatus: "NOT_APPLICABLE";
@@ -40,7 +40,7 @@ export declare const behaviorAdapter: {
40
40
  readonly ok: true;
41
41
  readonly status: "SUCCEEDED";
42
42
  readonly moduleRef: "platform-cli";
43
- readonly moduleVersion: "0.1.28";
43
+ readonly moduleVersion: "0.1.30";
44
44
  };
45
45
  observedEffects: never[];
46
46
  }>;
@@ -50,7 +50,7 @@ export declare const behaviorAdapter: {
50
50
  ok: true;
51
51
  status: "SUCCEEDED";
52
52
  moduleRef: "platform-cli";
53
- moduleVersion: "0.1.28";
53
+ moduleVersion: "0.1.30";
54
54
  data: {
55
55
  docs: string;
56
56
  };
@@ -63,7 +63,7 @@ export declare const behaviorAdapter: {
63
63
  readonly ok: true;
64
64
  readonly status: "SUCCEEDED";
65
65
  readonly moduleRef: "platform-cli";
66
- readonly moduleVersion: "0.1.28";
66
+ readonly moduleVersion: "0.1.30";
67
67
  };
68
68
  observedEffects: never[];
69
69
  }>;
@@ -73,7 +73,7 @@ export declare const behaviorAdapter: {
73
73
  readonly ok: true;
74
74
  readonly status: "SUCCEEDED";
75
75
  readonly moduleRef: "platform-cli";
76
- readonly moduleVersion: "0.1.28";
76
+ readonly moduleVersion: "0.1.30";
77
77
  };
78
78
  observedEffects: never[];
79
79
  }>;
@@ -3,7 +3,7 @@ export declare const descriptor: {
3
3
  readonly contractVersion: "1.0.0";
4
4
  readonly moduleRef: "platform-cli";
5
5
  readonly packageName: "@tomflow/proflow-platform-cli";
6
- readonly moduleVersion: "0.1.28";
6
+ readonly moduleVersion: "0.1.30";
7
7
  readonly kind: "cli";
8
8
  readonly templateVersion: "1.0.0";
9
9
  readonly platformCompatibility: ">=1.0.0 <2.0.0";
@@ -3,7 +3,7 @@ export const descriptor = {
3
3
  contractVersion: "1.0.0",
4
4
  moduleRef: "platform-cli",
5
5
  packageName: "@tomflow/proflow-platform-cli",
6
- moduleVersion: "0.1.28",
6
+ moduleVersion: "0.1.30",
7
7
  kind: "cli",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
package/dist/src/cli.js CHANGED
@@ -130,8 +130,14 @@ function batchStatus(result) {
130
130
  return "FAILED";
131
131
  }
132
132
  async function handleStatus(root, runtime) {
133
+ reportProgress(runtime.onProgress, {
134
+ command: "status",
135
+ phase: "status",
136
+ status: "STARTED",
137
+ message: "正在读取模块状态",
138
+ });
133
139
  const { catalog, modules } = await buildContext(root);
134
- const observed = await observeStatuses(catalog, modules, root, runtime.onProgress);
140
+ const observed = await observeStatuses(catalog, modules, root);
135
141
  const byRef = new Map(modules.map((module) => [module.moduleRef, module]));
136
142
  const output = observed.map((item) => {
137
143
  if (item.result.status !== "SUCCEEDED")
@@ -149,11 +155,23 @@ async function handleStatus(root, runtime) {
149
155
  runtimeStatus: parsed.data.runtimeStatus,
150
156
  };
151
157
  });
158
+ reportProgress(runtime.onProgress, {
159
+ command: "status",
160
+ phase: "status",
161
+ status: "SUCCEEDED",
162
+ message: `已读取 ${output.length} 个模块状态`,
163
+ });
152
164
  return outcome("status", "SUCCEEDED", root, { modules: output });
153
165
  }
154
166
  async function handleDocs(root, runtime) {
167
+ reportProgress(runtime.onProgress, {
168
+ command: "docs",
169
+ phase: "docs",
170
+ status: "STARTED",
171
+ message: "正在整理模块文档",
172
+ });
155
173
  const { catalog, modules: resolvedModules } = await buildContext(root);
156
- const docs = await observeDocs(catalog, resolvedModules, root, runtime.onProgress);
174
+ const docs = await observeDocs(catalog, resolvedModules, root);
157
175
  const byRef = new Map(resolvedModules.map((module) => [module.moduleRef, module]));
158
176
  const modules = [];
159
177
  const errors = [];
@@ -174,6 +192,14 @@ async function handleDocs(root, runtime) {
174
192
  docs: parsed.data.docs,
175
193
  });
176
194
  }
195
+ reportProgress(runtime.onProgress, {
196
+ command: "docs",
197
+ phase: "docs",
198
+ status: errors.length === 0 ? "SUCCEEDED" : "FAILED",
199
+ message: errors.length === 0
200
+ ? `已整理 ${modules.length} 份模块文档`
201
+ : `${errors.length} 份模块文档读取失败`,
202
+ });
177
203
  return outcome("docs", errors.length === 0 ? "SUCCEEDED" : "FAILED", root, {
178
204
  modules,
179
205
  errors,
@@ -223,6 +249,12 @@ async function handleInstall(root, runtime) {
223
249
  ? {}
224
250
  : { runner: runtime.registryRunner }),
225
251
  });
252
+ reportProgress(runtime.onProgress, {
253
+ command: "install",
254
+ phase: "registry",
255
+ status: "SUCCEEDED",
256
+ message: `已发现 ${discovered.candidates.length} 个注册模块`,
257
+ });
226
258
  if (discovered.rejected.length > 0)
227
259
  throw new PlatformError("REGISTRY_RESPONSE_INVALID", `registry contains rejected ProFlow packages: ${discovered.rejected.map((item) => `${item.packageName}:${item.reason}`).join(", ")}`);
228
260
  if (discovered.candidates.length === 0)
@@ -324,11 +356,23 @@ async function handleUninstall(root, runtime) {
324
356
  });
325
357
  }
326
358
  async function handleSetup(root, parsed, runtime) {
359
+ reportProgress(runtime.onProgress, {
360
+ command: "setup",
361
+ phase: "setup",
362
+ status: "STARTED",
363
+ message: "正在分析模块配置",
364
+ });
327
365
  const { catalog, modules } = await buildContext(root);
328
366
  const target = parsed.moduleRef === undefined
329
367
  ? undefined
330
368
  : { moduleRef: parsed.moduleRef };
331
- const result = await setupModulesThin(catalog, modules, root, target, runtime.onProgress);
369
+ const result = await setupModulesThin(catalog, modules, root, target, undefined);
370
+ reportProgress(runtime.onProgress, {
371
+ command: "setup",
372
+ phase: "setup",
373
+ status: result.completed ? "SUCCEEDED" : "ACTION_REQUIRED",
374
+ message: result.completed ? "模块配置已就绪" : "配置清单已生成",
375
+ });
332
376
  return outcome("setup", batchStatus(result), root, result);
333
377
  }
334
378
  async function handleStart(root, runtime) {
@@ -417,17 +461,52 @@ function renderStatus(data) {
417
461
  FAILED: "运行失败",
418
462
  NOT_APPLICABLE: "无独立进程",
419
463
  };
420
- return [
421
- "ProFlow 模块状态",
422
- "",
423
- "模块 版本 配置状态 运行状态",
424
- ...data.modules
425
- .filter(isRecord)
426
- .map((raw) => `${String(raw.moduleRef).padEnd(28)} ${String(raw.version).padEnd(10)} ${(setupLabels[String(raw.setupStatus)] ?? "未知").padEnd(10)} ${runtimeLabels[String(raw.runtimeStatus)] ?? "未知"}`),
427
- "",
428
- "需要操作:运行 platform setup",
429
- "失败:运行 platform setup 查看原因和修复步骤",
430
- ].join("\n");
464
+ const modules = data.modules.filter(isRecord);
465
+ const lines = ["ProFlow 状态", ""];
466
+ for (const raw of modules) {
467
+ const moduleRef = String(raw.moduleRef);
468
+ const setupStatus = String(raw.setupStatus);
469
+ const runtimeStatus = String(raw.runtimeStatus);
470
+ const failed = setupStatus === "FAILED" || runtimeStatus === "FAILED";
471
+ const actionRequired = setupStatus === "ACTION_REQUIRED";
472
+ const icon = failed
473
+ ? "✕"
474
+ : actionRequired
475
+ ? "◆"
476
+ : runtimeStatus === "RUNNING"
477
+ ? "●"
478
+ : runtimeStatus === "NOT_APPLICABLE"
479
+ ? "○"
480
+ : "✓";
481
+ lines.push(`${icon} ${moduleRef.padEnd(30)} ${String(raw.version).padEnd(9)} ${setupLabels[setupStatus] ?? "未知"} · ${runtimeLabels[runtimeStatus] ?? "未知"}`);
482
+ if (failed) {
483
+ lines.push(` 原因:${setupStatus === "FAILED" ? "模块配置检查失败" : "模块运行状态异常"}`, ` 下一步:platform setup --module ${moduleRef}`);
484
+ }
485
+ else if (actionRequired) {
486
+ lines.push(" 原因:模块尚未完成配置", ` 下一步:platform setup --module ${moduleRef}`);
487
+ }
488
+ }
489
+ const ready = modules.filter((item) => item.setupStatus === "READY").length;
490
+ const action = modules.filter((item) => item.setupStatus === "ACTION_REQUIRED").length;
491
+ const failed = modules.filter((item) => item.setupStatus === "FAILED").length;
492
+ lines.push("", `汇总:${ready} 已就绪 · ${action} 需要操作 · ${failed} 失败`);
493
+ return lines.join("\n");
494
+ }
495
+ function renderTerminalMarkdown(source) {
496
+ return source
497
+ .split(/\r?\n/)
498
+ .map((line) => {
499
+ const heading = line.match(/^#{1,6}\s+(.+)$/);
500
+ if (heading?.[1])
501
+ return heading[1].replaceAll("`", "");
502
+ const bullet = line.match(/^\s*-\s+(.+)$/);
503
+ if (bullet?.[1])
504
+ return ` • ${bullet[1].replaceAll("`", "")}`;
505
+ return line.replaceAll("`", "");
506
+ })
507
+ .join("\n")
508
+ .replace(/\n{3,}/g, "\n\n")
509
+ .trim();
431
510
  }
432
511
  function renderDocs(data) {
433
512
  if (!isRecord(data) || !Array.isArray(data.modules))
@@ -435,7 +514,7 @@ function renderDocs(data) {
435
514
  const lines = ["ProFlow 模块文档"];
436
515
  for (const raw of data.modules)
437
516
  if (isRecord(raw))
438
- lines.push("", `## ${String(raw.moduleRef)} @ ${String(raw.version)}`, String(raw.docs ?? ""));
517
+ lines.push("", "─".repeat(72), `${String(raw.moduleRef)} ${String(raw.version)}`, "", renderTerminalMarkdown(String(raw.docs ?? "")));
439
518
  if (Array.isArray(data.errors) && data.errors.length > 0)
440
519
  lines.push("", "文档读取失败:", ...data.errors
441
520
  .filter(isRecord)
@@ -497,24 +576,24 @@ function renderSetup(data) {
497
576
  blocked += 1;
498
577
  else
499
578
  needsAction += 1;
500
- lines.push(moduleRef);
579
+ lines.push(`${status === "FAILED" ? "✕" : "◆"} ${moduleRef}`);
501
580
  const plan = moduleSetupPlanDataSchema.safeParse(raw.result.data);
502
581
  if (plan.success) {
503
582
  for (const [index, step] of plan.data.steps.entries()) {
504
- lines.push(` [${step.state} ${index + 1}/${plan.data.steps.length}] ${step.title}`);
505
- lines.push(` 人工执行:${step.execution.interactive}`);
506
- lines.push(` AI 执行:${step.execution.nonInteractive}`);
583
+ lines.push(` ${index + 1}. ${step.title}`);
584
+ lines.push(` 运行:${step.execution.interactive}`);
585
+ lines.push(` 自动执行:${step.execution.nonInteractive}`);
507
586
  if (step.requiredInputs.length > 0)
508
- lines.push(` 需要输入:${step.requiredInputs.map((item) => item.description).join("、")}`);
509
- lines.push(` 验证:${step.verify}`);
510
- lines.push(` 完成条件:${step.successCondition}`);
587
+ lines.push(` 需要:${step.requiredInputs.map((item) => item.description).join("、")}`);
588
+ lines.push(` 验证:${step.verify}`);
589
+ lines.push(` 完成:${step.successCondition}`);
511
590
  if (step.blockedReason)
512
- lines.push(` 原因:${step.blockedReason}`);
591
+ lines.push(` 原因:${step.blockedReason}`);
513
592
  }
514
593
  lines.push("");
515
594
  continue;
516
595
  }
517
- lines.push(` [${status === "FAILED" ? "BLOCKED" : "TODO"} 1/1] ${status === "FAILED" ? "等待上游服务信息" : "完成模块配置"}`);
596
+ lines.push(` 1. ${status === "FAILED" ? "等待上游服务信息" : "完成模块配置"}`);
518
597
  const error = raw.result.error;
519
598
  if (status !== "FAILED") {
520
599
  const commands = setupCommands[moduleRef] ?? {
@@ -615,9 +694,9 @@ export function renderHumanResult(result) {
615
694
  }
616
695
  if (import.meta.main) {
617
696
  const argv = process.argv.slice(2);
618
- const result = await runCli(argv, {
619
- onProgress: createTerminalProgressReporter(),
620
- });
697
+ const reporter = createTerminalProgressReporter();
698
+ const result = await runCli(argv, { onProgress: reporter });
699
+ reporter.close();
621
700
  process.stdout.write(`${renderHumanResult(result)}\n`);
622
701
  if (result.status !== "SUCCEEDED")
623
702
  process.exitCode = 1;
@@ -1,2 +1,5 @@
1
1
  import type { PlatformProgressReporter } from "./progress.ts";
2
- export declare function createTerminalProgressReporter(stream?: NodeJS.WriteStream): PlatformProgressReporter;
2
+ export type TerminalProgressReporter = PlatformProgressReporter & {
3
+ close(): void;
4
+ };
5
+ export declare function createTerminalProgressReporter(stream?: NodeJS.WriteStream): TerminalProgressReporter;
@@ -6,10 +6,9 @@ const colors = {
6
6
  dim: "\u001b[2m",
7
7
  reset: "\u001b[0m",
8
8
  };
9
- function progressLine(event, color) {
10
- const prefix = event.current && event.total
11
- ? `[${String(event.current).padStart(2, "0")}/${event.total}] `
12
- : "";
9
+ const spinnerFrames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
10
+ function progressLine(event, color, spinner = "") {
11
+ const prefix = event.current && event.total ? `${event.current}/${event.total} · ` : "";
13
12
  const suffix = event.status === "SUCCEEDED"
14
13
  ? "完成"
15
14
  : event.status === "ACTION_REQUIRED"
@@ -19,20 +18,48 @@ function progressLine(event, color) {
19
18
  : event.status === "SKIPPED"
20
19
  ? "跳过"
21
20
  : "";
22
- if (!color || suffix === "")
23
- return `${prefix}${event.message}${suffix ? `… ${suffix}` : "…"}`;
21
+ const symbol = event.status === "STARTED"
22
+ ? spinner
23
+ : event.status === "SUCCEEDED"
24
+ ? "✓"
25
+ : event.status === "FAILED"
26
+ ? "✕"
27
+ : event.status === "ACTION_REQUIRED"
28
+ ? "◆"
29
+ : "○";
30
+ if (!color)
31
+ return `${symbol ? `${symbol} ` : ""}${prefix}${event.message}${suffix ? ` · ${suffix}` : ""}`;
24
32
  const tone = event.status === "SUCCEEDED"
25
33
  ? colors.green
26
34
  : event.status === "FAILED"
27
35
  ? colors.red
28
36
  : colors.yellow;
29
- return `${colors.dim}${prefix}${colors.reset}${event.message} ${tone}${suffix}${colors.reset}`;
37
+ return `${tone}${symbol}${colors.reset} ${colors.dim}${prefix}${colors.reset}${event.message}${suffix ? ` · ${tone}${suffix}${colors.reset}` : ""}`;
30
38
  }
31
39
  export function createTerminalProgressReporter(stream = process.stderr) {
32
40
  const interactive = stream.isTTY === true;
33
- const color = interactive && !("NO_COLOR" in process.env);
34
- return (event) => {
35
- const line = progressLine(event, color);
41
+ const color = interactive &&
42
+ process.env.NO_COLOR === undefined &&
43
+ process.env.TERM !== "dumb";
44
+ let timer;
45
+ let frame = 0;
46
+ let active;
47
+ const clearSpinner = () => {
48
+ if (timer)
49
+ clearInterval(timer);
50
+ timer = undefined;
51
+ };
52
+ const paint = () => {
53
+ if (!active)
54
+ return;
55
+ cursorTo(stream, 0);
56
+ clearLine(stream, 0);
57
+ stream.write(progressLine(active, color, spinnerFrames[frame++ % spinnerFrames.length]));
58
+ };
59
+ const reporter = ((event) => {
60
+ clearSpinner();
61
+ active = event.status === "STARTED" ? event : undefined;
62
+ const line = progressLine(event, color, interactive ? spinnerFrames[frame++ % spinnerFrames.length] : "›");
36
63
  if (!interactive) {
37
64
  stream.write(`${line}\n`);
38
65
  return;
@@ -40,7 +67,26 @@ export function createTerminalProgressReporter(stream = process.stderr) {
40
67
  cursorTo(stream, 0);
41
68
  clearLine(stream, 0);
42
69
  stream.write(line);
43
- if (event.status !== "STARTED")
70
+ if (event.status === "STARTED") {
71
+ timer = setInterval(paint, 80);
72
+ timer.unref();
73
+ return;
74
+ }
75
+ const compactModuleProgress = event.current !== undefined &&
76
+ event.total !== undefined &&
77
+ event.current < event.total &&
78
+ event.status !== "FAILED" &&
79
+ event.status !== "ACTION_REQUIRED";
80
+ if (!compactModuleProgress)
44
81
  stream.write("\n");
82
+ });
83
+ reporter.close = () => {
84
+ clearSpinner();
85
+ if (interactive && active) {
86
+ cursorTo(stream, 0);
87
+ clearLine(stream, 0);
88
+ }
89
+ active = undefined;
45
90
  };
91
+ return reporter;
46
92
  }
package/package.json CHANGED
@@ -1,48 +1,48 @@
1
1
  {
2
- "name": "@tomflow/proflow-platform-cli",
3
- "version": "0.1.28",
4
- "type": "module",
5
- "publishConfig": {
6
- "access": "public"
7
- },
8
- "exports": {
9
- ".": "./dist/src/index.js",
10
- "./cli": "./dist/src/cli.js",
11
- "./command": "./dist/src/command.js",
12
- "./deployment/adapter": "./dist/deployment/adapter.js",
13
- "./deployment/descriptor": "./dist/deployment/descriptor.js"
14
- },
15
- "bin": {
16
- "platform": "./dist/src/cli.js"
17
- },
18
- "files": [
19
- "dist",
20
- "proflow.module.json",
21
- "conformance.json",
22
- "README.md",
23
- "DOCS.md",
24
- "SETUP.md"
25
- ],
26
- "scripts": {
27
- "test": "node --test tests/**/*.test.ts",
28
- "typecheck": "tsc --noEmit"
29
- },
30
- "dependencies": {
31
- "@tomflow/proflow-module-contract": "^0.1.9"
32
- },
33
- "devDependencies": {
34
- "@tomflow/proflow-deployment-conformance": "^0.1.7",
35
- "@tomflow/proflow-module-template": "^0.1.7"
36
- },
37
- "description": "Thin Platform CLI for Module discovery, documentation, package synchronization and lifecycle orchestration.",
38
- "keywords": [
39
- "proflow",
40
- "proflow-module",
41
- "deployment-governance"
42
- ],
43
- "proflow": {
44
- "module": true,
45
- "descriptor": "./dist/deployment/descriptor.js",
46
- "manifest": "./proflow.module.json"
47
- }
48
- }
2
+ "name": "@tomflow/proflow-platform-cli",
3
+ "version": "0.1.30",
4
+ "type": "module",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "exports": {
9
+ ".": "./dist/src/index.js",
10
+ "./cli": "./dist/src/cli.js",
11
+ "./command": "./dist/src/command.js",
12
+ "./deployment/adapter": "./dist/deployment/adapter.js",
13
+ "./deployment/descriptor": "./dist/deployment/descriptor.js"
14
+ },
15
+ "bin": {
16
+ "platform": "./dist/src/cli.js"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "proflow.module.json",
21
+ "conformance.json",
22
+ "README.md",
23
+ "DOCS.md",
24
+ "SETUP.md"
25
+ ],
26
+ "dependencies": {
27
+ "@tomflow/proflow-module-contract": "^0.1.10"
28
+ },
29
+ "devDependencies": {
30
+ "@tomflow/proflow-deployment-conformance": "^0.1.8",
31
+ "@tomflow/proflow-module-template": "^0.1.8"
32
+ },
33
+ "description": "Thin Platform CLI for Module discovery, documentation, package synchronization and lifecycle orchestration.",
34
+ "keywords": [
35
+ "proflow",
36
+ "proflow-module",
37
+ "deployment-governance"
38
+ ],
39
+ "proflow": {
40
+ "module": true,
41
+ "descriptor": "./dist/deployment/descriptor.js",
42
+ "manifest": "./proflow.module.json"
43
+ },
44
+ "scripts": {
45
+ "test": "node --test tests/**/*.test.ts",
46
+ "typecheck": "tsc --noEmit"
47
+ }
48
+ }
@@ -3,7 +3,7 @@
3
3
  "contractVersion": "1.0.0",
4
4
  "moduleRef": "platform-cli",
5
5
  "packageName": "@tomflow/proflow-platform-cli",
6
- "moduleVersion": "0.1.28",
6
+ "moduleVersion": "0.1.30",
7
7
  "kind": "cli",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",