@curdx/flow 3.4.0 → 3.5.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/CHANGELOG.md +7 -0
- package/dist/index.mjs +31 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@curdx/flow` are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/) and the project follows [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 3.5.0 — 2026-04-27
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **`ralph-specum` is now a required bundled plugin** — it no longer appears as an optional checkbox in the install multiselect. Instead, it's listed in a dedicated "always installed" header above the prompt, alongside its current state (not installed / up-to-date / update available). When the flow runs, ralph-specum is auto-installed or auto-updated whenever it needs action; up-to-date installs are silently skipped. The other six items (pua, claude-mem, chrome-devtools-mcp, frontend-design, sequential-thinking, context7) remain optional. `--ids X` now also auto-includes required plugins that need action; users can still explicitly run `--ids ralph-specum` to force a reinstall confirmation. Uninstall flow is unchanged — users may still uninstall ralph-specum, and the next install will re-add it.
|
|
10
|
+
- **Internal:** `Pkg` type gains a `required?: boolean` field so future bundled plugins can opt into the same "always installed" semantics without touching install-flow code.
|
|
11
|
+
|
|
5
12
|
## 3.4.0 — 2026-04-27
|
|
6
13
|
|
|
7
14
|
### Added
|
package/dist/index.mjs
CHANGED
|
@@ -30,6 +30,7 @@ var messages = {
|
|
|
30
30
|
"marketplace.refreshed": "\u5DF2\u5237\u65B0 {count} \u4E2A marketplace",
|
|
31
31
|
"marketplace.refreshSkipped": "marketplace \u7F13\u5B58\u4ECD\u662F\u65B0\u9C9C\u7684\uFF0C\u8DF3\u8FC7\u5237\u65B0",
|
|
32
32
|
"install.updating": '\u66F4\u65B0 "{name}" \u5230 v{version}',
|
|
33
|
+
"install.requiredHeader": "\u4EE5\u4E0B\u6761\u76EE\u968F @curdx/flow \u9ED8\u8BA4\u5B89\u88C5\uFF08\u4E0D\u53EF\u53D6\u6D88\uFF09",
|
|
33
34
|
"install.selectPrompt": "\u52FE\u9009\u8981\u5B89\u88C5 / \u91CD\u88C5\u7684\u6761\u76EE\uFF08\u9ED8\u8BA4\u52FE\u9009\u672A\u5B89\u88C5\u7684\uFF09",
|
|
34
35
|
"install.nothingSelected": "\u6CA1\u6709\u9009\u62E9\u4EFB\u4F55\u6761\u76EE\uFF0C\u5DF2\u9000\u51FA\u3002",
|
|
35
36
|
"install.confirmReinstall": '"{name}" \u5DF2\u5B89\u88C5\uFF0C\u662F\u5426\u91CD\u65B0\u5B89\u88C5\uFF08\u5148\u5378\u8F7D\u518D\u5B89\u88C5\uFF09\uFF1F',
|
|
@@ -101,6 +102,7 @@ var messages2 = {
|
|
|
101
102
|
"marketplace.refreshed": "Refreshed {count} marketplace(s)",
|
|
102
103
|
"marketplace.refreshSkipped": "Marketplace caches are fresh, skipping refresh",
|
|
103
104
|
"install.updating": 'Updating "{name}" to v{version}',
|
|
105
|
+
"install.requiredHeader": "Always installed by @curdx/flow (cannot be unchecked)",
|
|
104
106
|
"install.selectPrompt": "Select items to install / reinstall (not-installed are pre-selected)",
|
|
105
107
|
"install.nothingSelected": "Nothing selected. Exiting.",
|
|
106
108
|
"install.confirmReinstall": '"{name}" is already installed. Reinstall (uninstall then install)?',
|
|
@@ -528,6 +530,7 @@ var ralphSpecum = {
|
|
|
528
530
|
name: "ralph-specum",
|
|
529
531
|
description: "curdx-flow (originally tzachbon/smart-ralph) \u2014 spec-driven dev with autonomous task execution",
|
|
530
532
|
type: "plugin",
|
|
533
|
+
required: true,
|
|
531
534
|
slashNamespace: "/ralph-specum:*",
|
|
532
535
|
whenToUse: "for spec-driven multi-task work \u2014 research \u2192 requirements \u2192 design \u2192 tasks \u2192 autonomous execution per task. Use when starting a feature that benefits from upfront spec; skip for one-shot fixes or simple edits.",
|
|
533
536
|
marketplaces: () => [MARKETPLACE_NAME4],
|
|
@@ -860,11 +863,17 @@ function stateLabel(pkg, s) {
|
|
|
860
863
|
}
|
|
861
864
|
}
|
|
862
865
|
async function selectInteractive(states) {
|
|
863
|
-
const
|
|
866
|
+
const requiredPkgs = PKGS.filter((pkg) => pkg.required);
|
|
867
|
+
const optionalPkgs = PKGS.filter((pkg) => !pkg.required);
|
|
868
|
+
if (requiredPkgs.length > 0) {
|
|
869
|
+
const lines = requiredPkgs.map((pkg) => ` ${stateLabel(pkg, states.get(pkg.id))}`);
|
|
870
|
+
p4.note(lines.join("\n"), t("install.requiredHeader"));
|
|
871
|
+
}
|
|
872
|
+
const options = optionalPkgs.map((pkg) => {
|
|
864
873
|
const s = states.get(pkg.id);
|
|
865
874
|
return { value: pkg.id, label: stateLabel(pkg, s), hint: pkg.description };
|
|
866
875
|
});
|
|
867
|
-
const initialValues =
|
|
876
|
+
const initialValues = optionalPkgs.filter((pkg) => {
|
|
868
877
|
const s = states.get(pkg.id);
|
|
869
878
|
return s.kind === "not_installed" || s.kind === "update_available";
|
|
870
879
|
}).map((pkg) => pkg.id);
|
|
@@ -875,7 +884,9 @@ async function selectInteractive(states) {
|
|
|
875
884
|
required: false
|
|
876
885
|
});
|
|
877
886
|
if (p4.isCancel(picked)) return null;
|
|
878
|
-
|
|
887
|
+
const userPicked = picked.map((id) => findPkg(id)).filter((x2) => Boolean(x2));
|
|
888
|
+
const requiredAuto = requiredPkgs.filter((pkg) => states.get(pkg.id)?.kind !== "up_to_date");
|
|
889
|
+
return [...requiredAuto, ...userPicked];
|
|
879
890
|
}
|
|
880
891
|
function selectFromIds(opts) {
|
|
881
892
|
if (opts.all) return [...PKGS];
|
|
@@ -991,6 +1002,13 @@ async function installFlow(opts = {}) {
|
|
|
991
1002
|
p4.log.info(t("install.nothingSelected"));
|
|
992
1003
|
return;
|
|
993
1004
|
}
|
|
1005
|
+
if (opts.ids && opts.ids.length > 0) {
|
|
1006
|
+
for (const pkg of PKGS) {
|
|
1007
|
+
if (pkg.required && !candidates.some((c) => c.id === pkg.id)) {
|
|
1008
|
+
candidates.push(pkg);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
994
1012
|
const stateMap = /* @__PURE__ */ new Map();
|
|
995
1013
|
const sp = p4.spinner();
|
|
996
1014
|
sp.start(t("state.checking"));
|
|
@@ -1006,7 +1024,16 @@ async function installFlow(opts = {}) {
|
|
|
1006
1024
|
}
|
|
1007
1025
|
let targets;
|
|
1008
1026
|
if (explicit) {
|
|
1009
|
-
|
|
1027
|
+
if (opts.ids && opts.ids.length > 0) {
|
|
1028
|
+
const userListedIds = new Set(opts.ids);
|
|
1029
|
+
targets = candidates.filter((pkg) => {
|
|
1030
|
+
if (!pkg.required) return true;
|
|
1031
|
+
if (userListedIds.has(pkg.id)) return true;
|
|
1032
|
+
return stateMap.get(pkg.id)?.kind !== "up_to_date";
|
|
1033
|
+
});
|
|
1034
|
+
} else {
|
|
1035
|
+
targets = candidates;
|
|
1036
|
+
}
|
|
1010
1037
|
} else {
|
|
1011
1038
|
const picked = await selectInteractive(stateMap);
|
|
1012
1039
|
if (picked === null) {
|