@curdx/flow 2.3.9 → 2.3.11
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/cli/README.md +6 -1
- package/cli/doctor-workflow.js +45 -0
- package/cli/install-companions.js +1 -1
- package/cli/install-context7-config.js +5 -3
- package/cli/install-required-plugins.js +2 -2
- package/cli/lib/config.js +1 -1
- package/cli/lib/doctor-report.js +21 -0
- package/cli/uninstall-actions.js +38 -1
- package/cli/upgrade-workflow.js +1 -1
- package/cli/upgrade.js +42 -14
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Claude Code Discipline Layer — spec-driven workflow + goal-backward verification + Karpathy 4 principles enforced via gates. Stops Claude from faking \"done\" on non-trivial features.",
|
|
9
|
-
"version": "2.3.
|
|
9
|
+
"version": "2.3.11"
|
|
10
10
|
},
|
|
11
11
|
"allowCrossMarketplaceDependenciesOn": [
|
|
12
12
|
"context7-marketplace"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"name": "curdx-flow",
|
|
17
17
|
"source": "./",
|
|
18
18
|
"description": "Claude Code Discipline Layer — spec-driven workflow + goal-backward verification + Karpathy 4 principles enforced via gates. Stops Claude from faking \"done\" on non-trivial features.",
|
|
19
|
-
"version": "2.3.
|
|
19
|
+
"version": "2.3.11",
|
|
20
20
|
"author": {
|
|
21
21
|
"name": "wdx",
|
|
22
22
|
"email": "bydongxin@gmail.com"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "curdx-flow",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.11",
|
|
4
4
|
"description": "Claude Code Discipline Layer — spec-driven workflow + goal-backward verification + Karpathy 4 principles enforced via gates. Stops Claude from faking \"done\" on non-trivial features.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "wdx",
|
package/cli/README.md
CHANGED
|
@@ -63,9 +63,14 @@ This keeps the CLI scoped to install-time and lifecycle operations only — anyt
|
|
|
63
63
|
|
|
64
64
|
`claude plugin marketplace update` + `claude plugin update --scope user` for every installed curdx-flow-related plugin.
|
|
65
65
|
|
|
66
|
+
After updating, `upgrade` also reconciles retired Context7 install artifacts:
|
|
67
|
+
|
|
68
|
+
- removes the old user-level `context7` MCP if the official `context7-plugin` already owns it
|
|
69
|
+
- removes any stale `context7ApiKey` entry from `~/.claude/curdx-flow-config.json`
|
|
70
|
+
|
|
66
71
|
### `uninstall [-y] [--keep-recommended] [--purge]`
|
|
67
72
|
|
|
68
|
-
Inverse of `install`. By default removes only the curdx-flow plugin. Recommended plugins are kept unless selected interactively. With `--purge`, also removes third-party marketplaces
|
|
73
|
+
Inverse of `install`. By default removes only the curdx-flow plugin. Recommended plugins are kept unless selected interactively. With `--purge`, also removes third-party marketplaces, the `~/.local/bin/bun` / `~/.local/bin/uv` symlinks created by install, and any retired Context7 user-level MCP / stored API key left behind by older CurDX-Flow releases.
|
|
69
74
|
|
|
70
75
|
## Why a CLI?
|
|
71
76
|
|
package/cli/doctor-workflow.js
CHANGED
|
@@ -2,7 +2,9 @@ import fs from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
|
|
5
|
+
import { removeMcp } from "./lib/claude-ops.js";
|
|
5
6
|
import { readProjectClaudeSettings } from "./lib/doctor-claude-settings.js";
|
|
7
|
+
import { CONFIG_FILE, readConfig, writeConfig } from "./lib/config.js";
|
|
6
8
|
import { inspectRuntimeEnvironment } from "./lib/doctor-runtime-environment.js";
|
|
7
9
|
import {
|
|
8
10
|
claudeVersion,
|
|
@@ -310,6 +312,7 @@ export async function collectDoctorData(
|
|
|
310
312
|
readProjectTeamConfigImpl = readProjectTeamConfig,
|
|
311
313
|
readProjectClaudeSettingsImpl = readProjectClaudeSettings,
|
|
312
314
|
readBundledPluginRuntimeDefaultsImpl = readBundledPluginRuntimeDefaults,
|
|
315
|
+
readConfigImpl = readConfig,
|
|
313
316
|
} = {}
|
|
314
317
|
) {
|
|
315
318
|
const claudeVersionValue = claudeVersionImpl();
|
|
@@ -338,6 +341,10 @@ export async function collectDoctorData(
|
|
|
338
341
|
projectTeamConfig: await readProjectTeamConfigImpl(cwd),
|
|
339
342
|
projectClaudeSettings: await readProjectClaudeSettingsImpl(cwd),
|
|
340
343
|
bundledPluginRuntimeDefaults: await readBundledPluginRuntimeDefaultsImpl(),
|
|
344
|
+
legacyInstallState: {
|
|
345
|
+
configPath: CONFIG_FILE,
|
|
346
|
+
hasLegacyContext7ApiKey: Object.prototype.hasOwnProperty.call(readConfigImpl(), "context7ApiKey"),
|
|
347
|
+
},
|
|
341
348
|
};
|
|
342
349
|
}
|
|
343
350
|
|
|
@@ -345,9 +352,47 @@ export async function applyDoctorFixes(
|
|
|
345
352
|
doctorData,
|
|
346
353
|
{
|
|
347
354
|
ensureClaudeMemRuntimesImpl = ensureClaudeMemRuntimes,
|
|
355
|
+
removeMcpImpl = removeMcp,
|
|
356
|
+
readConfigImpl = readConfig,
|
|
357
|
+
writeConfigImpl = writeConfig,
|
|
348
358
|
} = {}
|
|
349
359
|
) {
|
|
350
360
|
const fixes = [];
|
|
361
|
+
const context7PluginOwnsMcp = doctorData.mcps.some(
|
|
362
|
+
(entry) => entry.name === "context7" && entry.plugin === "context7-plugin"
|
|
363
|
+
);
|
|
364
|
+
const hasLegacyUserContext7Mcp =
|
|
365
|
+
doctorData.userMcpConfig instanceof Map && doctorData.userMcpConfig.has("context7");
|
|
366
|
+
|
|
367
|
+
if (context7PluginOwnsMcp && hasLegacyUserContext7Mcp) {
|
|
368
|
+
const result = await removeMcpImpl({ name: "context7" });
|
|
369
|
+
if (result.code === 0) {
|
|
370
|
+
doctorData.userMcpConfig.delete("context7");
|
|
371
|
+
doctorData.mcps = doctorData.mcps.filter(
|
|
372
|
+
(entry) => !(entry.name === "context7" && entry.plugin == null)
|
|
373
|
+
);
|
|
374
|
+
fixes.push({
|
|
375
|
+
kind: "legacy-context7-user-mcp-removed",
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (doctorData.legacyInstallState?.hasLegacyContext7ApiKey) {
|
|
381
|
+
const config = readConfigImpl();
|
|
382
|
+
if (Object.prototype.hasOwnProperty.call(config, "context7ApiKey")) {
|
|
383
|
+
delete config.context7ApiKey;
|
|
384
|
+
writeConfigImpl(config);
|
|
385
|
+
doctorData.legacyInstallState = {
|
|
386
|
+
...doctorData.legacyInstallState,
|
|
387
|
+
hasLegacyContext7ApiKey: false,
|
|
388
|
+
};
|
|
389
|
+
fixes.push({
|
|
390
|
+
kind: "legacy-context7-api-key-removed",
|
|
391
|
+
configPath: CONFIG_FILE,
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
351
396
|
const claudeMemEnabled = doctorData.plugins.some(
|
|
352
397
|
(plugin) => plugin.name === "claude-mem" && plugin.status === "enabled"
|
|
353
398
|
);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* install-required-plugins.js — required Claude Code companion plugins
|
|
9
9
|
* install-bundled-mcps.js — user-level MCP registration
|
|
10
10
|
* install-recommended-plugins.js — optional recommended plugins
|
|
11
|
-
* install-context7-config.js —
|
|
11
|
+
* install-context7-config.js — legacy Context7 state reconciliation (private to required)
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reconcile legacy Context7 install state after the official plugin is
|
|
3
|
-
* installed. Private to the required-plugins concern; not
|
|
4
|
-
* install-companions.js.
|
|
3
|
+
* installed or refreshed. Private to the required-plugins concern; not
|
|
4
|
+
* re-exported from install-companions.js.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { removeMcp } from "./lib/claude-ops.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
writeConfig,
|
|
14
14
|
} from "./utils.js";
|
|
15
15
|
|
|
16
|
-
export async function
|
|
16
|
+
export async function reconcileLegacyContext7InstallState(
|
|
17
17
|
plugin,
|
|
18
18
|
language,
|
|
19
19
|
config,
|
|
@@ -76,3 +76,5 @@ export async function installContext7Config(
|
|
|
76
76
|
removedStoredApiKey,
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
|
+
|
|
80
|
+
export const installContext7Config = reconcileLegacyContext7InstallState;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { addPluginMarketplace, installPlugin } from "./lib/claude-ops.js";
|
|
7
7
|
import { REQUIRED_PLUGINS } from "./registry.js";
|
|
8
8
|
import { color, log, resultLastLine } from "./utils.js";
|
|
9
|
-
import {
|
|
9
|
+
import { reconcileLegacyContext7InstallState } from "./install-context7-config.js";
|
|
10
10
|
|
|
11
11
|
export async function addRequiredPluginMarketplaces({ logWarnings = true } = {}) {
|
|
12
12
|
for (const plugin of REQUIRED_PLUGINS) {
|
|
@@ -36,7 +36,7 @@ export async function installRequiredPlugins({
|
|
|
36
36
|
console.log(` ${color.green("✓")} ${plugin.name} installed`);
|
|
37
37
|
|
|
38
38
|
if (plugin.name === "context7-plugin") {
|
|
39
|
-
await
|
|
39
|
+
await reconcileLegacyContext7InstallState(plugin, language, config);
|
|
40
40
|
}
|
|
41
41
|
} else {
|
|
42
42
|
console.log(
|
package/cli/lib/config.js
CHANGED
|
@@ -3,7 +3,7 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
|
|
5
5
|
const CONFIG_DIR = join(homedir(), ".claude");
|
|
6
|
-
const CONFIG_FILE = join(CONFIG_DIR, "curdx-flow-config.json");
|
|
6
|
+
export const CONFIG_FILE = join(CONFIG_DIR, "curdx-flow-config.json");
|
|
7
7
|
|
|
8
8
|
export function readConfig() {
|
|
9
9
|
if (!existsSync(CONFIG_FILE)) {
|
package/cli/lib/doctor-report.js
CHANGED
|
@@ -224,6 +224,7 @@ export function buildDoctorReport({
|
|
|
224
224
|
projectTeamConfig,
|
|
225
225
|
projectClaudeSettings,
|
|
226
226
|
bundledPluginRuntimeDefaults,
|
|
227
|
+
legacyInstallState,
|
|
227
228
|
}) {
|
|
228
229
|
const lines = [];
|
|
229
230
|
const sections = [];
|
|
@@ -402,6 +403,12 @@ export function buildDoctorReport({
|
|
|
402
403
|
"migration: claude plugin update curdx-flow@curdx-flow-marketplace",
|
|
403
404
|
"then restart Claude Code",
|
|
404
405
|
]
|
|
406
|
+
: duplicate.pluginEntry.plugin === "context7-plugin" && duplicate.name === "context7"
|
|
407
|
+
? [
|
|
408
|
+
"official Context7 plugin already owns the context7 MCP server",
|
|
409
|
+
"run: npx @curdx/flow doctor --fix",
|
|
410
|
+
`or run manually: claude mcp remove --scope user ${duplicate.name}`,
|
|
411
|
+
]
|
|
405
412
|
: [
|
|
406
413
|
`remove the duplicate user-level server if plugin:${duplicate.pluginEntry.plugin} should own it`,
|
|
407
414
|
`run: claude mcp remove --scope user ${duplicate.name}`,
|
|
@@ -415,6 +422,20 @@ export function buildDoctorReport({
|
|
|
415
422
|
}
|
|
416
423
|
}
|
|
417
424
|
|
|
425
|
+
if (legacyInstallState?.hasLegacyContext7ApiKey) {
|
|
426
|
+
const legacySection = createSection("Legacy installer state:");
|
|
427
|
+
pushSectionLine(
|
|
428
|
+
legacySection,
|
|
429
|
+
"warn",
|
|
430
|
+
"legacy Context7 API key stored in curdx-flow install config",
|
|
431
|
+
[
|
|
432
|
+
`path: ${legacyInstallState.configPath}`,
|
|
433
|
+
"this key belonged to the retired user-level Context7 MCP install flow and is no longer used by the official context7-plugin",
|
|
434
|
+
"run: npx @curdx/flow doctor --fix",
|
|
435
|
+
]
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
|
|
418
439
|
if (claudeMemEnabled && runtimeStatus) {
|
|
419
440
|
const runtimeSection = createSection("Runtime (claude-mem dependencies):");
|
|
420
441
|
for (const [name, status] of Object.entries(runtimeStatus)) {
|
package/cli/uninstall-actions.js
CHANGED
|
@@ -3,6 +3,7 @@ import { join } from "node:path";
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
|
|
5
5
|
import { REQUIRED_PLUGINS, RECOMMENDED_PLUGINS, BUNDLED_MCPS } from "./registry.js";
|
|
6
|
+
import { readConfig, writeConfig } from "./lib/config.js";
|
|
6
7
|
import {
|
|
7
8
|
removeMcp,
|
|
8
9
|
removePluginMarketplace,
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
resultLastLine,
|
|
17
18
|
resultOutput,
|
|
18
19
|
} from "./utils.js";
|
|
20
|
+
import { reconcileLegacyContext7InstallState } from "./install-context7-config.js";
|
|
19
21
|
import {
|
|
20
22
|
UNINSTALL_STEP_COUNT,
|
|
21
23
|
getInstalledTargets,
|
|
@@ -124,7 +126,7 @@ export async function maybeRemoveBundledMcps(
|
|
|
124
126
|
} = {}
|
|
125
127
|
) {
|
|
126
128
|
logImpl.blank();
|
|
127
|
-
logImpl.info("Required MCP servers (
|
|
129
|
+
logImpl.info("Required user-level MCP servers (sequential-thinking)");
|
|
128
130
|
if (shouldKeepBundledMcpsImpl({ yes, keepRecommended })) {
|
|
129
131
|
logImpl.info(
|
|
130
132
|
color.dim("--yes or --keep-recommended: keeping user-level MCPs (remove manually with `claude mcp remove <name>`)")
|
|
@@ -193,6 +195,10 @@ export async function maybePurgeRuntimeArtifacts(
|
|
|
193
195
|
{
|
|
194
196
|
purgeManagedMarketplacesImpl = purgeManagedMarketplaces,
|
|
195
197
|
removeManagedSymlinksImpl = removeManagedSymlinks,
|
|
198
|
+
readConfigImpl = readConfig,
|
|
199
|
+
writeConfigImpl = writeConfig,
|
|
200
|
+
removeMcpImpl = removeMcp,
|
|
201
|
+
readUserMcpConfigImpl,
|
|
196
202
|
logImpl = log,
|
|
197
203
|
} = {}
|
|
198
204
|
) {
|
|
@@ -210,6 +216,13 @@ export async function maybePurgeRuntimeArtifacts(
|
|
|
210
216
|
|
|
211
217
|
await purgeManagedMarketplacesImpl();
|
|
212
218
|
removeManagedSymlinksImpl();
|
|
219
|
+
await purgeLegacyContext7InstallState({
|
|
220
|
+
readConfigImpl,
|
|
221
|
+
writeConfigImpl,
|
|
222
|
+
removeMcpImpl,
|
|
223
|
+
readUserMcpConfigImpl,
|
|
224
|
+
logImpl,
|
|
225
|
+
});
|
|
213
226
|
}
|
|
214
227
|
|
|
215
228
|
export async function maybeRemoveProjectState(
|
|
@@ -304,6 +317,30 @@ function removeManagedSymlinks(
|
|
|
304
317
|
}
|
|
305
318
|
}
|
|
306
319
|
|
|
320
|
+
async function purgeLegacyContext7InstallState(
|
|
321
|
+
{
|
|
322
|
+
readConfigImpl = readConfig,
|
|
323
|
+
writeConfigImpl = writeConfig,
|
|
324
|
+
removeMcpImpl = removeMcp,
|
|
325
|
+
readUserMcpConfigImpl,
|
|
326
|
+
logImpl = log,
|
|
327
|
+
} = {}
|
|
328
|
+
) {
|
|
329
|
+
const config = readConfigImpl();
|
|
330
|
+
const language = config?.language === "zh" ? "zh" : "en";
|
|
331
|
+
await reconcileLegacyContext7InstallState(
|
|
332
|
+
{ name: "context7-plugin" },
|
|
333
|
+
language,
|
|
334
|
+
config,
|
|
335
|
+
{
|
|
336
|
+
writeConfigImpl,
|
|
337
|
+
removeMcpImpl,
|
|
338
|
+
readUserMcpConfigImpl,
|
|
339
|
+
logImpl,
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
|
|
307
344
|
function toUninstallTarget(entry) {
|
|
308
345
|
return {
|
|
309
346
|
name: entry.name,
|
package/cli/upgrade-workflow.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { claudeVersion, color, listPlugins, log, resultLastLine } from "./utils.js";
|
|
2
2
|
|
|
3
|
-
export const UPGRADE_STEP_COUNT =
|
|
3
|
+
export const UPGRADE_STEP_COUNT = 3;
|
|
4
4
|
|
|
5
5
|
export function ensureClaudeCliAvailableForUpgrade(
|
|
6
6
|
{ claudeVersionImpl = claudeVersion, logImpl = log, exitImpl = process.exit } = {}
|
package/cli/upgrade.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* upgrade command — update curdx-flow + recommended plugins to latest.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { log } from "./utils.js";
|
|
5
|
+
import { log, readConfig } from "./utils.js";
|
|
6
|
+
import { reconcileLegacyContext7InstallState } from "./install-context7-config.js";
|
|
6
7
|
import {
|
|
7
8
|
PLUGINS_TO_UPDATE,
|
|
8
9
|
MARKETPLACES_TO_REFRESH,
|
|
@@ -21,43 +22,70 @@ import {
|
|
|
21
22
|
UPGRADE_STEP_COUNT,
|
|
22
23
|
} from "./upgrade-workflow.js";
|
|
23
24
|
|
|
24
|
-
export async function upgrade(
|
|
25
|
-
|
|
25
|
+
export async function upgrade(
|
|
26
|
+
args = [],
|
|
27
|
+
{
|
|
28
|
+
updatePluginImpl = updatePlugin,
|
|
29
|
+
updatePluginMarketplaceImpl = updatePluginMarketplace,
|
|
30
|
+
ensureClaudeCliAvailableForUpgradeImpl = ensureClaudeCliAvailableForUpgrade,
|
|
31
|
+
getInstalledPluginNamesImpl = getInstalledPluginNames,
|
|
32
|
+
readConfigImpl = readConfig,
|
|
33
|
+
reconcileLegacyContext7InstallStateImpl = reconcileLegacyContext7InstallState,
|
|
34
|
+
logImpl = log,
|
|
35
|
+
} = {}
|
|
36
|
+
) {
|
|
37
|
+
logImpl.title("⬆️ CurdX-Flow upgrade");
|
|
26
38
|
|
|
27
|
-
|
|
39
|
+
ensureClaudeCliAvailableForUpgradeImpl({ logImpl });
|
|
28
40
|
|
|
29
41
|
// Refresh marketplaces first (derived from cli/registry.js)
|
|
30
42
|
await refreshMarketplaces(MARKETPLACES_TO_REFRESH, {
|
|
31
|
-
updatePluginMarketplaceImpl
|
|
43
|
+
updatePluginMarketplaceImpl,
|
|
44
|
+
logImpl,
|
|
32
45
|
});
|
|
33
46
|
|
|
34
47
|
// Update each plugin
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const installedNames =
|
|
48
|
+
logImpl.blank();
|
|
49
|
+
logImpl.step(2, UPGRADE_STEP_COUNT, "Updating installed plugins...");
|
|
50
|
+
const installedNames = getInstalledPluginNamesImpl();
|
|
38
51
|
|
|
39
52
|
for (const spec of PLUGINS_TO_UPDATE) {
|
|
40
53
|
const pluginName = getPluginNameFromSpec(spec);
|
|
41
54
|
if (!installedNames.has(pluginName)) {
|
|
42
|
-
|
|
55
|
+
logImpl.info(` ${pluginName.padEnd(22)} not installed, skipping`);
|
|
43
56
|
continue;
|
|
44
57
|
}
|
|
45
58
|
|
|
46
|
-
const result = await
|
|
59
|
+
const result = await updatePluginImpl(spec);
|
|
47
60
|
const status = classifyPluginUpdateResult(result);
|
|
48
61
|
|
|
49
62
|
if (status.status === "updated") {
|
|
50
|
-
|
|
63
|
+
logImpl.ok(` ${pluginName.padEnd(22)} ${status.message}`);
|
|
51
64
|
continue;
|
|
52
65
|
}
|
|
53
66
|
|
|
54
67
|
if (status.status === "unchanged") {
|
|
55
|
-
|
|
68
|
+
logImpl.info(` ${pluginName.padEnd(22)} ${status.message}`);
|
|
56
69
|
continue;
|
|
57
70
|
}
|
|
58
71
|
|
|
59
|
-
|
|
72
|
+
logImpl.warn(` ${pluginName.padEnd(22)} ${status.message}`);
|
|
60
73
|
}
|
|
61
74
|
|
|
62
|
-
|
|
75
|
+
logImpl.blank();
|
|
76
|
+
logImpl.step(3, UPGRADE_STEP_COUNT, "Reconciling legacy Context7 state...");
|
|
77
|
+
if (installedNames.has("context7-plugin")) {
|
|
78
|
+
const config = readConfigImpl();
|
|
79
|
+
const language = config?.language === "zh" ? "zh" : "en";
|
|
80
|
+
await reconcileLegacyContext7InstallStateImpl(
|
|
81
|
+
{ name: "context7-plugin" },
|
|
82
|
+
language,
|
|
83
|
+
config,
|
|
84
|
+
{ logImpl }
|
|
85
|
+
);
|
|
86
|
+
} else {
|
|
87
|
+
logImpl.info(" context7-plugin not installed, skipping");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
printUpgradeSummary({ logImpl });
|
|
63
91
|
}
|