@curdx/flow 3.4.0 → 4.0.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 +20 -0
- package/README.md +4 -2
- package/dist/index.mjs +55 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
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
|
+
## 4.0.0 — 2026-04-27
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- **Plugin renamed `ralph-specum` → `curdx-flow`.** The bundled spec-driven workflow plugin now lives under the `curdx-flow` brand, slash namespace `/curdx-flow:*`, full slug `curdx-flow@curdx`. The marketplace identifier was simultaneously shortened from `curdx-flow` to `curdx` (the GitHub repo source `curdx/curdx-flow` is unchanged). All in-plugin slash references, env vars (`RALPH_SPECUM_*` → `CURDX_FLOW_*`), and labels were updated accordingly.
|
|
10
|
+
- **Auto-migration:** the installer now detects legacy `ralph-specum@curdx-flow` and `ralph-specum@smart-ralph` installs and uninstalls them automatically before installing the new slug, so users on v3.4 / v3.5 transparently transition. Your `specs/` directory and any in-progress spec state files are not touched — the rename is purely a plugin-identity change.
|
|
11
|
+
- **Manual fallback:** if you'd rather run the migration yourself, execute `claude plugin uninstall ralph-specum@curdx-flow` (or `@smart-ralph`) before re-running `npx @curdx/flow install`. The old marketplace `curdx-flow` may remain registered alongside the new `curdx` marketplace; this is harmless and you can `claude plugin marketplace remove curdx-flow` if you want to clean up.
|
|
12
|
+
|
|
13
|
+
### Notes
|
|
14
|
+
|
|
15
|
+
- The plugin's authorship and license lineage (smart-ralph by tzachbon → ralph-specum fork → curdx-flow) is recorded in `plugins/curdx-flow/NOTICE.md`. MIT License preserved.
|
|
16
|
+
- `.claude-plugin/marketplace.json` now declares one plugin: `curdx-flow` v4.9.1 sourced from `./plugins/curdx-flow`.
|
|
17
|
+
|
|
18
|
+
## 3.5.0 — 2026-04-27
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **`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.
|
|
23
|
+
- **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.
|
|
24
|
+
|
|
5
25
|
## 3.4.0 — 2026-04-27
|
|
6
26
|
|
|
7
27
|
### Added
|
package/README.md
CHANGED
|
@@ -31,11 +31,13 @@ npx @curdx/flow --lang en # override language
|
|
|
31
31
|
| `claude-mem` | plugin | `thedotmack/claude-mem` |
|
|
32
32
|
| `chrome-devtools-mcp` | plugin | `ChromeDevTools/chrome-devtools-mcp` |
|
|
33
33
|
| `frontend-design` | plugin | `claude-plugins-official` (built-in) |
|
|
34
|
-
| `
|
|
34
|
+
| `curdx-flow` | plugin | bundled in this repo (always installed) — spec-driven dev with autonomous task execution (originally [tzachbon/smart-ralph](https://github.com/tzachbon/smart-ralph), MIT, intermediate fork: ralph-specum) |
|
|
35
35
|
| `sequential-thinking` | mcp | `@modelcontextprotocol/server-sequential-thinking` |
|
|
36
36
|
| `context7` | mcp | HTTP — `https://mcp.context7.com/mcp` (optional API key) |
|
|
37
37
|
|
|
38
|
-
>
|
|
38
|
+
> Migration notes:
|
|
39
|
+
> - If you installed the upstream `ralph-specum@smart-ralph` build, run `claude plugin uninstall ralph-specum@smart-ralph` before upgrading.
|
|
40
|
+
> - If you installed `ralph-specum@curdx-flow` (curdx-flow v3.4.0 / v3.5.0), run `claude plugin uninstall ralph-specum@curdx-flow` and re-run `npx @curdx/flow install`. The plugin is now `curdx-flow@curdx` with slash namespace `/curdx-flow:*`.
|
|
39
41
|
|
|
40
42
|
## What it writes to your filesystem
|
|
41
43
|
|
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)?',
|
|
@@ -518,17 +520,27 @@ var frontendDesign = {
|
|
|
518
520
|
};
|
|
519
521
|
var frontend_design_default = frontendDesign;
|
|
520
522
|
|
|
521
|
-
// src/registry/plugins/
|
|
522
|
-
var PLUGIN_ID5 = "
|
|
523
|
-
var PLUGIN_NAME3 = "
|
|
524
|
-
var MARKETPLACE_NAME4 = "curdx
|
|
523
|
+
// src/registry/plugins/curdx-flow.ts
|
|
524
|
+
var PLUGIN_ID5 = "curdx-flow@curdx";
|
|
525
|
+
var PLUGIN_NAME3 = "curdx-flow";
|
|
526
|
+
var MARKETPLACE_NAME4 = "curdx";
|
|
525
527
|
var MARKETPLACE_SOURCE4 = "curdx/curdx-flow";
|
|
526
|
-
var
|
|
527
|
-
|
|
528
|
-
|
|
528
|
+
var LEGACY_PLUGIN_IDS = ["ralph-specum@curdx-flow", "ralph-specum@smart-ralph"];
|
|
529
|
+
async function uninstallLegacyIfPresent(ctx) {
|
|
530
|
+
for (const legacyId of LEGACY_PLUGIN_IDS) {
|
|
531
|
+
if (await isPluginInstalled(legacyId)) {
|
|
532
|
+
ctx.log.message(`Removing legacy plugin ${legacyId} (renamed to ${PLUGIN_ID5})\u2026`);
|
|
533
|
+
await uninstallPluginById(legacyId, ctx);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
var curdxFlow = {
|
|
538
|
+
id: "curdx-flow",
|
|
539
|
+
name: "curdx-flow",
|
|
529
540
|
description: "curdx-flow (originally tzachbon/smart-ralph) \u2014 spec-driven dev with autonomous task execution",
|
|
530
541
|
type: "plugin",
|
|
531
|
-
|
|
542
|
+
required: true,
|
|
543
|
+
slashNamespace: "/curdx-flow:*",
|
|
532
544
|
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
545
|
marketplaces: () => [MARKETPLACE_NAME4],
|
|
534
546
|
isInstalled: () => isPluginInstalled(PLUGIN_ID5),
|
|
@@ -539,13 +551,17 @@ var ralphSpecum = {
|
|
|
539
551
|
},
|
|
540
552
|
latestVersion: () => getMarketplacePluginVersion(MARKETPLACE_NAME4, PLUGIN_NAME3),
|
|
541
553
|
install: async (ctx) => {
|
|
554
|
+
await uninstallLegacyIfPresent(ctx);
|
|
542
555
|
await ensureMarketplace(MARKETPLACE_NAME4, MARKETPLACE_SOURCE4, ctx);
|
|
543
556
|
await installPluginById(PLUGIN_ID5, ctx);
|
|
544
557
|
},
|
|
545
558
|
uninstall: (ctx) => uninstallPluginById(PLUGIN_ID5, ctx),
|
|
546
|
-
update: (ctx) =>
|
|
559
|
+
update: async (ctx) => {
|
|
560
|
+
await uninstallLegacyIfPresent(ctx);
|
|
561
|
+
await updatePluginById(PLUGIN_ID5, ctx);
|
|
562
|
+
}
|
|
547
563
|
};
|
|
548
|
-
var
|
|
564
|
+
var curdx_flow_default = curdxFlow;
|
|
549
565
|
|
|
550
566
|
// src/registry/mcps/sequential-thinking.ts
|
|
551
567
|
var MCP_NAME = "sequential-thinking";
|
|
@@ -644,7 +660,7 @@ var PKGS = [
|
|
|
644
660
|
claude_mem_default,
|
|
645
661
|
chrome_devtools_mcp_default,
|
|
646
662
|
frontend_design_default,
|
|
647
|
-
|
|
663
|
+
curdx_flow_default,
|
|
648
664
|
sequential_thinking_default,
|
|
649
665
|
context7_default
|
|
650
666
|
];
|
|
@@ -860,11 +876,17 @@ function stateLabel(pkg, s) {
|
|
|
860
876
|
}
|
|
861
877
|
}
|
|
862
878
|
async function selectInteractive(states) {
|
|
863
|
-
const
|
|
879
|
+
const requiredPkgs = PKGS.filter((pkg) => pkg.required);
|
|
880
|
+
const optionalPkgs = PKGS.filter((pkg) => !pkg.required);
|
|
881
|
+
if (requiredPkgs.length > 0) {
|
|
882
|
+
const lines = requiredPkgs.map((pkg) => ` ${stateLabel(pkg, states.get(pkg.id))}`);
|
|
883
|
+
p4.note(lines.join("\n"), t("install.requiredHeader"));
|
|
884
|
+
}
|
|
885
|
+
const options = optionalPkgs.map((pkg) => {
|
|
864
886
|
const s = states.get(pkg.id);
|
|
865
887
|
return { value: pkg.id, label: stateLabel(pkg, s), hint: pkg.description };
|
|
866
888
|
});
|
|
867
|
-
const initialValues =
|
|
889
|
+
const initialValues = optionalPkgs.filter((pkg) => {
|
|
868
890
|
const s = states.get(pkg.id);
|
|
869
891
|
return s.kind === "not_installed" || s.kind === "update_available";
|
|
870
892
|
}).map((pkg) => pkg.id);
|
|
@@ -875,7 +897,9 @@ async function selectInteractive(states) {
|
|
|
875
897
|
required: false
|
|
876
898
|
});
|
|
877
899
|
if (p4.isCancel(picked)) return null;
|
|
878
|
-
|
|
900
|
+
const userPicked = picked.map((id) => findPkg(id)).filter((x2) => Boolean(x2));
|
|
901
|
+
const requiredAuto = requiredPkgs.filter((pkg) => states.get(pkg.id)?.kind !== "up_to_date");
|
|
902
|
+
return [...requiredAuto, ...userPicked];
|
|
879
903
|
}
|
|
880
904
|
function selectFromIds(opts) {
|
|
881
905
|
if (opts.all) return [...PKGS];
|
|
@@ -991,6 +1015,13 @@ async function installFlow(opts = {}) {
|
|
|
991
1015
|
p4.log.info(t("install.nothingSelected"));
|
|
992
1016
|
return;
|
|
993
1017
|
}
|
|
1018
|
+
if (opts.ids && opts.ids.length > 0) {
|
|
1019
|
+
for (const pkg of PKGS) {
|
|
1020
|
+
if (pkg.required && !candidates.some((c) => c.id === pkg.id)) {
|
|
1021
|
+
candidates.push(pkg);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
994
1025
|
const stateMap = /* @__PURE__ */ new Map();
|
|
995
1026
|
const sp = p4.spinner();
|
|
996
1027
|
sp.start(t("state.checking"));
|
|
@@ -1006,7 +1037,16 @@ async function installFlow(opts = {}) {
|
|
|
1006
1037
|
}
|
|
1007
1038
|
let targets;
|
|
1008
1039
|
if (explicit) {
|
|
1009
|
-
|
|
1040
|
+
if (opts.ids && opts.ids.length > 0) {
|
|
1041
|
+
const userListedIds = new Set(opts.ids);
|
|
1042
|
+
targets = candidates.filter((pkg) => {
|
|
1043
|
+
if (!pkg.required) return true;
|
|
1044
|
+
if (userListedIds.has(pkg.id)) return true;
|
|
1045
|
+
return stateMap.get(pkg.id)?.kind !== "up_to_date";
|
|
1046
|
+
});
|
|
1047
|
+
} else {
|
|
1048
|
+
targets = candidates;
|
|
1049
|
+
}
|
|
1010
1050
|
} else {
|
|
1011
1051
|
const picked = await selectInteractive(stateMap);
|
|
1012
1052
|
if (picked === null) {
|