@tomflow/proflow-platform-cli 0.1.42 → 0.1.44

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.
@@ -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.42";
9
+ readonly moduleVersion: "0.1.44";
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.42";
19
+ readonly moduleVersion: "0.1.44";
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.42";
29
+ moduleVersion: "0.1.44";
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.42";
43
+ readonly moduleVersion: "0.1.44";
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.42";
53
+ moduleVersion: "0.1.44";
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.42";
66
+ readonly moduleVersion: "0.1.44";
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.42";
76
+ readonly moduleVersion: "0.1.44";
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.42";
6
+ readonly moduleVersion: "0.1.44";
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.42",
6
+ moduleVersion: "0.1.44",
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
@@ -11,6 +11,7 @@ import { observeWorkspaceInstalledVersion, preflightWorkspacePackageManager, rem
11
11
  import { cleanOwnedPnpmPolicy, observeMinimumReleaseAgeExclude, recordPnpmPolicyOwnership, } from "./install/pnpm-policy.js";
12
12
  import { installModulesThin, observeDocs, observeStatuses, setupModulesThin, startModulesThin, stopModulesThin, uninstallModulesThin, } from "./lifecycle/index.js";
13
13
  import { ensureWorkspaceStateIsGitIgnored } from "./persistence/git-isolation.js";
14
+ import { clearStartOwner, registerStartOwner, requestStartOwnerStop, } from "./persistence/start-owner.js";
14
15
  import { ensureWorkspaceMetadata } from "./persistence/workspace-metadata.js";
15
16
  import { reportProgress } from "./progress.js";
16
17
  import { discoverRegistryModules, PRO_FLOW_PACKAGE_PREFIX, } from "./registry/index.js";
@@ -1148,15 +1149,71 @@ export function renderHumanResult(result, options = {}) {
1148
1149
  return `${theme.success("✓ 已经卸载")}${result.workspaceRoot ? `\n${theme.muted("Workspace")} ${result.workspaceRoot}` : ""}`;
1149
1150
  return `${result.status === "SUCCEEDED" ? theme.success("✓") : theme.failure("✕")} ${labels[result.command] ?? result.command}${result.status === "SUCCEEDED" ? "成功" : "未完成"}${result.workspaceRoot ? `\n${theme.muted("Workspace")} ${result.workspaceRoot}` : ""}`;
1150
1151
  }
1152
+ function ownsStartedRuntime(result) {
1153
+ if (result.command !== "start" || !isRecord(result.data))
1154
+ return false;
1155
+ const results = Array.isArray(result.data.results)
1156
+ ? result.data.results.filter(isRecord)
1157
+ : [];
1158
+ return results.some((item) => item.command === "start" &&
1159
+ Array.isArray(item.observedEffects) &&
1160
+ item.observedEffects.length > 0 &&
1161
+ isRecord(item.result) &&
1162
+ item.result.status === "SUCCEEDED");
1163
+ }
1151
1164
  if (import.meta.main) {
1152
1165
  const argv = process.argv.slice(2);
1153
1166
  const reporter = createTerminalProgressReporter();
1167
+ let parsedForOwner;
1168
+ let ownerRoot;
1169
+ try {
1170
+ parsedForOwner = parseArgs(argv);
1171
+ if (parsedForOwner.command === "start" || parsedForOwner.command === "stop")
1172
+ ownerRoot = await canonicalWorkspace(process.cwd(), parsedForOwner.workspace);
1173
+ }
1174
+ catch {
1175
+ // runCli owns normal usage/workspace error rendering.
1176
+ }
1177
+ if (parsedForOwner?.command === "stop" && ownerRoot) {
1178
+ reportProgress(reporter, {
1179
+ command: "stop",
1180
+ phase: "owner",
1181
+ status: "STARTED",
1182
+ message: "正在请求当前平台运行进程停止",
1183
+ });
1184
+ const requested = await requestStartOwnerStop(ownerRoot);
1185
+ reportProgress(reporter, {
1186
+ command: "stop",
1187
+ phase: "owner",
1188
+ status: requested === "TIMEOUT" ? "WARNING" : "SUCCEEDED",
1189
+ message: requested === "STOPPED"
1190
+ ? "平台运行进程已停止"
1191
+ : "未发现需要接管的前台运行进程",
1192
+ });
1193
+ }
1154
1194
  const result = await runCli(argv, {
1155
1195
  onProgress: reporter,
1156
1196
  ...(process.stdin.isTTY && process.stdout.isTTY
1157
1197
  ? { setupInteraction: createClackSetupInteraction() }
1158
1198
  : {}),
1159
1199
  });
1200
+ if (parsedForOwner?.command === "start" &&
1201
+ ownerRoot &&
1202
+ result.status === "SUCCEEDED" &&
1203
+ ownsStartedRuntime(result)) {
1204
+ await registerStartOwner(ownerRoot);
1205
+ let stopping = false;
1206
+ const gracefulStop = async () => {
1207
+ if (stopping)
1208
+ return;
1209
+ stopping = true;
1210
+ const stopped = await runCli(["stop", "--workspace", ownerRoot]);
1211
+ await clearStartOwner(ownerRoot);
1212
+ process.exit(stopped.status === "SUCCEEDED" ? 0 : 1);
1213
+ };
1214
+ process.once("SIGTERM", () => void gracefulStop());
1215
+ process.once("SIGINT", () => void gracefulStop());
1216
+ }
1160
1217
  reporter.close();
1161
1218
  const color = process.stdout.isTTY === true &&
1162
1219
  process.env.NO_COLOR === undefined &&
@@ -222,27 +222,85 @@ export async function setupModulesThin(catalog, modules, workspaceRoot, target,
222
222
  .map((moduleRef) => byRef.get(moduleRef))
223
223
  .filter((module) => module !== undefined);
224
224
  let completed = true;
225
- for (const [index, module] of modulesInOrder.entries()) {
226
- reportProgress(reporter, {
227
- command: "setup",
228
- phase: "setup",
229
- kind: "detail",
230
- retention: "REPLACE",
231
- current: index + 1,
232
- total: modulesInOrder.length,
233
- moduleRef: module.moduleRef,
234
- status: "STARTED",
235
- message: module.moduleRef,
236
- });
237
- const status = await dispatchModuleCommand(catalog, module, "status", context(workspaceRoot));
238
- if (!succeeded(status.result)) {
239
- results.push(status);
240
- completed = false;
241
- break;
225
+ const temporaryRuntimeRefs = [];
226
+ const temporaryRuntimeSet = new Set();
227
+ const dependencyClosure = (moduleRef) => {
228
+ const closure = new Set();
229
+ const visit = (ref) => {
230
+ for (const dependency of dependenciesByRef.get(ref) ?? []) {
231
+ if (closure.has(dependency))
232
+ continue;
233
+ closure.add(dependency);
234
+ visit(dependency);
235
+ }
236
+ };
237
+ visit(moduleRef);
238
+ return closure;
239
+ };
240
+ const ensureSetupRuntimeDependencies = async (module) => {
241
+ if (module.kind !== "agent-package")
242
+ return true;
243
+ const closure = dependencyClosure(module.moduleRef);
244
+ for (const dependencyRef of graph.order) {
245
+ if (!closure.has(dependencyRef))
246
+ continue;
247
+ const dependency = byRef.get(dependencyRef);
248
+ if (dependency?.kind !== "service")
249
+ continue;
250
+ const status = await dispatchModuleCommand(catalog, dependency, "status", context(workspaceRoot));
251
+ if (!succeeded(status.result)) {
252
+ blockers.push({
253
+ moduleRef: dependencyRef,
254
+ setupStatus: "FAILED",
255
+ reason: status.result.error?.message ?? "临时运行依赖状态检查失败",
256
+ });
257
+ completed = false;
258
+ return false;
259
+ }
260
+ const observed = moduleStatusObservationSchema.parse(status.result.data);
261
+ if (observed.setupStatus !== "READY") {
262
+ const issue = observed.issues?.find((item) => item.scope === "SETUP");
263
+ blockers.push({
264
+ moduleRef: dependencyRef,
265
+ setupStatus: observed.setupStatus,
266
+ ...(issue
267
+ ? { reason: issue.message, nextCommand: issue.nextCommand }
268
+ : {}),
269
+ });
270
+ completed = false;
271
+ return false;
272
+ }
273
+ if (observed.runtimeStatus === "RUNNING" ||
274
+ observed.runtimeStatus === "NOT_APPLICABLE")
275
+ continue;
276
+ if (observed.runtimeStatus !== "STOPPED") {
277
+ blockers.push({
278
+ moduleRef: dependencyRef,
279
+ setupStatus: "FAILED",
280
+ reason: `临时运行依赖 ${dependencyRef} 处于 ${observed.runtimeStatus}`,
281
+ });
282
+ completed = false;
283
+ return false;
284
+ }
285
+ const started = await dispatchModuleCommand(catalog, dependency, "start", context(workspaceRoot));
286
+ if (!succeeded(started.result)) {
287
+ blockers.push({
288
+ moduleRef: dependencyRef,
289
+ setupStatus: "FAILED",
290
+ reason: started.result.error?.message ?? `临时启动 ${dependencyRef} 失败`,
291
+ });
292
+ completed = false;
293
+ return false;
294
+ }
295
+ if (!temporaryRuntimeSet.has(dependencyRef)) {
296
+ temporaryRuntimeSet.add(dependencyRef);
297
+ temporaryRuntimeRefs.push(dependencyRef);
298
+ }
242
299
  }
243
- const observed = moduleStatusObservationSchema.parse(status.result.data);
244
- if (observed.setupStatus === "READY" && target === undefined) {
245
- skipped.push({ moduleRef: module.moduleRef, reason: "READY" });
300
+ return true;
301
+ };
302
+ try {
303
+ for (const [index, module] of modulesInOrder.entries()) {
246
304
  reportProgress(reporter, {
247
305
  command: "setup",
248
306
  phase: "setup",
@@ -251,53 +309,93 @@ export async function setupModulesThin(catalog, modules, workspaceRoot, target,
251
309
  current: index + 1,
252
310
  total: modulesInOrder.length,
253
311
  moduleRef: module.moduleRef,
254
- status: "SKIPPED",
312
+ status: "STARTED",
255
313
  message: module.moduleRef,
256
314
  });
257
- continue;
258
- }
259
- await beforeSetup?.(module.moduleRef);
260
- const setup = await dispatchModuleCommand(catalog, module, "setup", context(workspaceRoot, target?.input));
261
- results.push(setup);
262
- reportProgress(reporter, {
263
- command: "setup",
264
- phase: "setup",
265
- kind: "detail",
266
- retention: "REPLACE",
267
- current: index + 1,
268
- total: modulesInOrder.length,
269
- moduleRef: module.moduleRef,
270
- status: succeeded(setup.result)
271
- ? "SUCCEEDED"
272
- : setup.result.status === "ACTION_REQUIRED"
273
- ? "ACTION_REQUIRED"
274
- : "FAILED",
275
- message: module.moduleRef,
276
- });
277
- if (!succeeded(setup.result)) {
278
- completed = false;
279
- }
280
- const reconciled = await dispatchModuleCommand(catalog, module, "status", context(workspaceRoot));
281
- if (!succeeded(reconciled.result)) {
282
- results.push(reconciled);
283
- completed = false;
284
- }
285
- else {
286
- const reconciledStatus = moduleStatusObservationSchema.parse(reconciled.result.data);
287
- if (reconciledStatus.setupStatus !== "READY") {
288
- const issue = reconciledStatus.issues?.find((item) => item.scope === "SETUP");
289
- blockers.push({
315
+ const status = await dispatchModuleCommand(catalog, module, "status", context(workspaceRoot));
316
+ if (!succeeded(status.result)) {
317
+ results.push(status);
318
+ completed = false;
319
+ break;
320
+ }
321
+ const observed = moduleStatusObservationSchema.parse(status.result.data);
322
+ if (observed.setupStatus === "READY" && target === undefined) {
323
+ skipped.push({ moduleRef: module.moduleRef, reason: "READY" });
324
+ reportProgress(reporter, {
325
+ command: "setup",
326
+ phase: "setup",
327
+ kind: "detail",
328
+ retention: "REPLACE",
329
+ current: index + 1,
330
+ total: modulesInOrder.length,
290
331
  moduleRef: module.moduleRef,
291
- setupStatus: reconciledStatus.setupStatus,
292
- ...(issue === undefined
293
- ? {}
294
- : { reason: issue.message, nextCommand: issue.nextCommand }),
332
+ status: "SKIPPED",
333
+ message: module.moduleRef,
295
334
  });
335
+ continue;
336
+ }
337
+ if (!(await ensureSetupRuntimeDependencies(module)))
338
+ break;
339
+ await beforeSetup?.(module.moduleRef);
340
+ const setup = await dispatchModuleCommand(catalog, module, "setup", context(workspaceRoot, target?.input));
341
+ results.push(setup);
342
+ reportProgress(reporter, {
343
+ command: "setup",
344
+ phase: "setup",
345
+ kind: "detail",
346
+ retention: "REPLACE",
347
+ current: index + 1,
348
+ total: modulesInOrder.length,
349
+ moduleRef: module.moduleRef,
350
+ status: succeeded(setup.result)
351
+ ? "SUCCEEDED"
352
+ : setup.result.status === "ACTION_REQUIRED"
353
+ ? "ACTION_REQUIRED"
354
+ : "FAILED",
355
+ message: module.moduleRef,
356
+ });
357
+ if (!succeeded(setup.result)) {
296
358
  completed = false;
297
359
  }
360
+ const reconciled = await dispatchModuleCommand(catalog, module, "status", context(workspaceRoot));
361
+ if (!succeeded(reconciled.result)) {
362
+ results.push(reconciled);
363
+ completed = false;
364
+ }
365
+ else {
366
+ const reconciledStatus = moduleStatusObservationSchema.parse(reconciled.result.data);
367
+ if (reconciledStatus.setupStatus !== "READY") {
368
+ const issue = reconciledStatus.issues?.find((item) => item.scope === "SETUP");
369
+ blockers.push({
370
+ moduleRef: module.moduleRef,
371
+ setupStatus: reconciledStatus.setupStatus,
372
+ ...(issue === undefined
373
+ ? {}
374
+ : { reason: issue.message, nextCommand: issue.nextCommand }),
375
+ });
376
+ completed = false;
377
+ }
378
+ }
379
+ if (!succeeded(setup.result) || blockers.length > 0)
380
+ break;
381
+ }
382
+ }
383
+ finally {
384
+ for (const dependencyRef of [...temporaryRuntimeRefs].reverse()) {
385
+ const dependency = byRef.get(dependencyRef);
386
+ if (!dependency)
387
+ continue;
388
+ const stopped = await dispatchModuleCommand(catalog, dependency, "stop", context(workspaceRoot));
389
+ if (!succeeded(stopped.result)) {
390
+ completed = false;
391
+ blockers.push({
392
+ moduleRef: dependencyRef,
393
+ setupStatus: "FAILED",
394
+ reason: stopped.result.error?.message ??
395
+ `临时运行依赖 ${dependencyRef} 清理失败`,
396
+ });
397
+ }
298
398
  }
299
- if (!succeeded(setup.result) || blockers.length > 0)
300
- break;
301
399
  }
302
400
  return {
303
401
  phase: "setup",
@@ -0,0 +1,3 @@
1
+ export declare function registerStartOwner(root: string): Promise<void>;
2
+ export declare function clearStartOwner(root: string, pid?: number): Promise<void>;
3
+ export declare function requestStartOwnerStop(root: string): Promise<"ABSENT" | "STOPPED" | "UNVERIFIED" | "TIMEOUT">;
@@ -0,0 +1,118 @@
1
+ import { execFile } from "node:child_process";
2
+ import { readFile, realpath, rm } from "node:fs/promises";
3
+ import { join, relative } from "node:path";
4
+ import { atomicWrite } from "../paths.js";
5
+ const CONTRACT = "proflow.platform-start-owner.v1";
6
+ const ownerFile = (root) => join(root, ".proflow", "runtime", "platform-cli", "start-owner.json");
7
+ function processAlive(pid) {
8
+ try {
9
+ process.kill(pid, 0);
10
+ return true;
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ }
16
+ async function commandLine(pid) {
17
+ return new Promise((resolveCommand) => {
18
+ execFile("ps", ["-p", String(pid), "-o", "command="], { timeout: 2_000, encoding: "utf8" }, (error, stdout) => resolveCommand(error ? undefined : String(stdout).trim()));
19
+ });
20
+ }
21
+ function parseRecord(value) {
22
+ if (!value || typeof value !== "object" || Array.isArray(value))
23
+ return undefined;
24
+ const item = value;
25
+ if (item.contract !== CONTRACT ||
26
+ typeof item.pid !== "number" ||
27
+ !Number.isInteger(item.pid) ||
28
+ item.pid <= 0 ||
29
+ typeof item.workspaceRoot !== "string" ||
30
+ typeof item.processCwd !== "string" ||
31
+ typeof item.argv1 !== "string" ||
32
+ typeof item.entrypointRealpath !== "string" ||
33
+ typeof item.startedAt !== "string" ||
34
+ Number.isNaN(Date.parse(item.startedAt)))
35
+ return undefined;
36
+ return item;
37
+ }
38
+ async function readOwner(root) {
39
+ try {
40
+ return parseRecord(JSON.parse(await readFile(ownerFile(root), "utf8")));
41
+ }
42
+ catch {
43
+ return undefined;
44
+ }
45
+ }
46
+ async function ownerMatchesProcess(record) {
47
+ if (!processAlive(record.pid))
48
+ return false;
49
+ let observedEntrypoint;
50
+ try {
51
+ observedEntrypoint = await realpath(record.argv1);
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ if (observedEntrypoint !== record.entrypointRealpath)
57
+ return false;
58
+ const observed = await commandLine(record.pid);
59
+ if (!observed)
60
+ return false;
61
+ const relativeArgv = relative(record.processCwd, record.argv1);
62
+ const entrypointMatches = [
63
+ record.argv1,
64
+ relativeArgv,
65
+ `./${relativeArgv}`,
66
+ ].some((candidate) => candidate.length > 0 && observed.includes(candidate));
67
+ return entrypointMatches && /(?:^|\s)start(?:\s|$)/.test(observed);
68
+ }
69
+ async function waitForExit(pid, timeoutMs = 60_000) {
70
+ const deadline = Date.now() + timeoutMs;
71
+ while (Date.now() < deadline) {
72
+ if (!processAlive(pid))
73
+ return true;
74
+ await new Promise((resolveWait) => setTimeout(resolveWait, 100));
75
+ }
76
+ return !processAlive(pid);
77
+ }
78
+ export async function registerStartOwner(root) {
79
+ const argv1 = process.argv[1];
80
+ if (!argv1)
81
+ throw new Error("platform start entrypoint is unavailable");
82
+ const record = {
83
+ contract: CONTRACT,
84
+ pid: process.pid,
85
+ workspaceRoot: root,
86
+ processCwd: process.cwd(),
87
+ argv1,
88
+ entrypointRealpath: await realpath(argv1),
89
+ startedAt: new Date().toISOString(),
90
+ };
91
+ await atomicWrite(ownerFile(root), `${JSON.stringify(record, null, 2)}\n`);
92
+ }
93
+ export async function clearStartOwner(root, pid = process.pid) {
94
+ const current = await readOwner(root);
95
+ if (current?.pid !== pid)
96
+ return;
97
+ await rm(ownerFile(root), { force: true });
98
+ }
99
+ export async function requestStartOwnerStop(root) {
100
+ const record = await readOwner(root);
101
+ if (!record)
102
+ return "ABSENT";
103
+ if (record.workspaceRoot !== root || !(await ownerMatchesProcess(record))) {
104
+ if (!processAlive(record.pid))
105
+ await rm(ownerFile(root), { force: true });
106
+ return "UNVERIFIED";
107
+ }
108
+ try {
109
+ process.kill(record.pid, "SIGTERM");
110
+ }
111
+ catch {
112
+ return "UNVERIFIED";
113
+ }
114
+ if (!(await waitForExit(record.pid)))
115
+ return "TIMEOUT";
116
+ await rm(ownerFile(root), { force: true });
117
+ return "STOPPED";
118
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/proflow-platform-cli",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -28,8 +28,8 @@
28
28
  "@tomflow/proflow-module-contract": "^0.1.13"
29
29
  },
30
30
  "devDependencies": {
31
- "@tomflow/proflow-deployment-conformance": "^0.1.13",
32
- "@tomflow/proflow-module-template": "^0.1.10"
31
+ "@tomflow/proflow-module-template": "^0.1.10",
32
+ "@tomflow/proflow-deployment-conformance": "^0.1.13"
33
33
  },
34
34
  "description": "Thin Platform CLI for Module discovery, documentation, package synchronization and lifecycle orchestration.",
35
35
  "keywords": [
@@ -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.42",
6
+ "moduleVersion": "0.1.44",
7
7
  "kind": "cli",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",
package/CHANGELOG.md DELETED
@@ -1,85 +0,0 @@
1
- # @tomflow/proflow-platform-cli
2
-
3
- ## 0.1.42
4
-
5
- ### Patch Changes
6
-
7
- - Repack the Deployment Closeout release from freshly rebuilt artifacts and enforce build + publishability before every canonical publish.
8
-
9
- ## 0.1.41
10
-
11
- ### Patch Changes
12
-
13
- - Harden Deployment Closeout: fail closed on partial installs and package-manager conflicts, normalize Git workspace isolation, make Dev Tunnel status fast and resumable without fabricating login failures, and align Browser Extension setup/conformance behavior.
14
-
15
- ## 0.1.40
16
-
17
- ### Patch Changes
18
-
19
- - Ignore governed non-Module tool packages during Registry module discovery so Fresh install remains fixed at 23 active modules.
20
-
21
- ## 0.1.39
22
-
23
- ### Patch Changes
24
-
25
- - Add professional setup orchestration, Provider FAST/THINK input, recoverable managed Dev Tunnel provisioning, Browser installation guidance, and precise status diagnostics.
26
-
27
- ## 0.1.38
28
-
29
- ### Patch Changes
30
-
31
- - Retire the obsolete Carrier package and Browser standalone management CLI, make Platform setup/status preserve owner and dependency semantics, and enforce read-only status observation across the final Real-3 deployment closeout.
32
-
33
- ## 0.1.37
34
-
35
- ### Patch Changes
36
-
37
- - Ship the Phase 3 browser, tunnel, model automation, platform readiness, and documentation closure as one verifiable platform snapshot.
38
-
39
- ## 0.1.36
40
-
41
- ### Patch Changes
42
-
43
- - Distinguish dependency blocking from verified failure, expose Module-owned status diagnostics, remove automatic docs paging, consolidate start checks, add contextual help, and clarify uninstall output.
44
-
45
- ## 0.1.35
46
-
47
- ### Patch Changes
48
-
49
- - Render retryable package-manager warnings as warnings instead of failed subprocess events.
50
-
51
- ## 0.1.34
52
-
53
- ### Patch Changes
54
-
55
- - Upgrade the ProFlow terminal experience, stream Registry and package-manager progress, publish structured Chinese Module documentation, and provide numbered package-owned Setup assistants.
56
-
57
- ## 0.1.33
58
-
59
- ### Patch Changes
60
-
61
- - Keep lifecycle summary totals mutually exclusive when a no-effect external runtime is skipped.
62
-
63
- ## 0.1.32
64
-
65
- ### Patch Changes
66
-
67
- - Report successful lifecycle calls with no owned stop effect as skipped instead of claiming an external runtime was stopped.
68
-
69
- ## 0.1.31
70
-
71
- ### Patch Changes
72
-
73
- - Make every setup command directly runnable from a workspace and render setup failures without Node stack traces.
74
-
75
- ## 0.1.30
76
-
77
- ### Patch Changes
78
-
79
- - Use a stable progress marker in non-interactive logs instead of a frozen spinner frame.
80
-
81
- ## 0.1.29
82
-
83
- ### Patch Changes
84
-
85
- - Improve terminal progress and localized status output, publish readable Chinese module docs, and add guided setup assistants for external resources.