@curdx/flow 7.1.19 → 7.1.20

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 CHANGED
@@ -2,6 +2,18 @@
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
+ ## 7.1.20 — 2026-05-11
6
+
7
+ ### Changed
8
+
9
+ - **Companion capabilities are now the default required bundle.** `pua`, `claude-mem`, `chrome-devtools-mcp`, `frontend-design`, `sequential-thinking`, and `context7` are marked `required` in the installer alongside `curdx-flow`, so interactive installs show them as always installed and `--ids` installs auto-include missing required companions.
10
+ - **Official plugin dependency metadata added.** `curdx-flow` now declares plugin dependencies for `pua`, `claude-mem`, `chrome-devtools-mcp`, and `frontend-design`, and the root marketplace explicitly allows those cross-marketplace dependencies.
11
+ - **Capability routing marks bundled companions as `core-required`.** Smart-route recommendations still trigger only when relevant, but recommended bundled capabilities are no longer suppressed by narrow availability filters.
12
+
13
+ ### Tests
14
+
15
+ - Added registry and manifest regression coverage for the required bundle, expanded capability-router expectations, rebuilt hook bundles, and tightened `claudecc` smoke checks for `core-required` recommendations.
16
+
5
17
  ## 7.1.19 — 2026-05-11
6
18
 
7
19
  ### Added
package/README.md CHANGED
@@ -123,7 +123,7 @@ The same npm package delivers both products. The installer reads its descriptor
123
123
 
124
124
  - **Node.js** ≥ 20.12 ([download](https://nodejs.org))
125
125
  - **Claude Code CLI** installed and on `PATH` ([install instructions](https://docs.anthropic.com/en/docs/claude-code))
126
- - *(Optional)* **Bun** ≥ 1.0 — auto-detected; the installer offers to install it if you choose `claude-mem`
126
+ - *(Optional)* **Bun** ≥ 1.0 — auto-detected; the installer offers to install it for the default `claude-mem` companion
127
127
 
128
128
  ### Install
129
129
 
@@ -131,7 +131,7 @@ The same npm package delivers both products. The installer reads its descriptor
131
131
  npx @curdx/flow
132
132
  ```
133
133
 
134
- On first run, you pick a language (中文 / English), then select what to install. The bundled `curdx-flow` plugin (the spec workflow itself) is always installed. Everything else is opt-in.
134
+ On first run, you pick a language (中文 / English). The full curdx-flow bundle is installed by default: `curdx-flow`, `pua`, `claude-mem`, `chrome-devtools-mcp`, `frontend-design`, `sequential-thinking`, and `context7`. If a companion has a local prerequisite that is missing, the installer reports the skip reason and continues so the core workflow remains usable.
135
135
 
136
136
  That language choice also controls the managed `~/.claude/CLAUDE.md` block that flow writes. The block is rendered in the selected language, and when you choose `zh` it additionally injects a language policy telling Claude to keep tool/model interaction in English while replying to the user in Simplified Chinese.
137
137
 
@@ -428,9 +428,9 @@ Most workflow frameworks address this by adding more agents, more orchestration,
428
428
 
429
429
  No. flow runs **inside** Claude Code as a plugin. You still use the Claude Code CLI / IDE extension to chat; flow adds the `/curdx-flow:*` commands, subagents, hooks, and the bundled marketplace.
430
430
 
431
- #### Can I use flow without installing the marketplace plugins?
431
+ #### Can I use flow without the companion capabilities?
432
432
 
433
- Yes. The bundled `curdx-flow` plugin is the spec workflow itself; everything else (claude-mem, chrome-devtools-mcp, …) is opt-in. `npx @curdx/flow install` lets you pick.
433
+ The default installer treats the companion capabilities as required because routing depends on them for memory, current docs, frontend design, browser verification, structured reasoning, and retry/parallel recovery. If a local prerequisite is missing, that item may be skipped with a visible reason, but the next `npx @curdx/flow install` run will try to restore it.
434
434
 
435
435
  #### Do I need to commit the spec files?
436
436
 
package/dist/index.mjs CHANGED
@@ -514,6 +514,7 @@ var pua = {
514
514
  name: "pua",
515
515
  description: "tanweai/pua \u2014 Chinese Claude Code skills bundle",
516
516
  type: "plugin",
517
+ required: true,
517
518
  slashNamespace: "/pua:*",
518
519
  whenToUse: "auto-fires on 2+ failures or user frustration; sub-modes p7 / p9 / pro / loop. Skip on first-attempt failures or when a known fix is executing.",
519
520
  marketplaces: () => [MARKETPLACE_NAME],
@@ -609,6 +610,7 @@ var claudeMem = {
609
610
  name: "claude-mem",
610
611
  description: "thedotmack/claude-mem \u2014 persistent cross-session memory for Claude Code",
611
612
  type: "plugin",
613
+ required: true,
612
614
  slashNamespace: "/claude-mem:*",
613
615
  whenToUse: 'for cross-session memory search ("did we solve this before?"), phased planning (`make-plan`), or phased execution (`do`).',
614
616
  marketplaces: () => [MARKETPLACE_NAME2],
@@ -668,6 +670,7 @@ var chromeDevtoolsMcp = {
668
670
  name: "chrome-devtools-mcp",
669
671
  description: "ChromeDevTools/chrome-devtools-mcp \u2014 drive a real Chrome from Claude Code",
670
672
  type: "plugin",
673
+ required: true,
671
674
  whenToUse: "when debugging code that runs in a browser: perf traces, network / console inspection, DOM / CSS issues. Prefer snapshot over screenshot.",
672
675
  prereqCheck: async (t2) => {
673
676
  const major = Number(process.versions.node.split(".")[0] ?? "0");
@@ -697,6 +700,7 @@ var frontendDesign = {
697
700
  name: "frontend-design",
698
701
  description: "Anthropic official \u2014 UI/frontend design helpers",
699
702
  type: "plugin",
703
+ required: true,
700
704
  whenToUse: "auto-fires when building UI / web components / pages. Best where visual personality matters (landing, marketing, portfolio).",
701
705
  isInstalled: () => isPluginInstalled(PLUGIN_ID4),
702
706
  install: (ctx) => installPluginById(PLUGIN_ID4, ctx),
@@ -742,6 +746,7 @@ var sequentialThinking = {
742
746
  name: "sequential-thinking",
743
747
  description: "modelcontextprotocol/server-sequential-thinking \u2014 structured reasoning helper",
744
748
  type: "mcp",
749
+ required: true,
745
750
  whenToUse: "for complex multi-step problems where assumptions may shift (architecture comparison, risk-assessed migrations, prod-only debugging). Skip for simple queries.",
746
751
  isInstalled: () => isMcpInstalled(MCP_NAME),
747
752
  install: async (ctx) => {
@@ -783,6 +788,7 @@ var context7 = {
783
788
  name: "context7",
784
789
  description: "upstash/context7 \u2014 up-to-date docs from any library (HTTP MCP, optional API key)",
785
790
  type: "mcp",
791
+ required: true,
786
792
  whenToUse: "for any library / SDK / framework / API / Claude Code docs lookup. Use instead of web search.",
787
793
  isInstalled: () => isMcpInstalled(MCP_NAME2),
788
794
  configPrompts: async ({ t: t2 }) => {
@@ -913,7 +919,15 @@ var ORDER = [
913
919
  "sequential-thinking",
914
920
  "pua"
915
921
  ];
916
- var DOCS_RE = /\b(api|sdk|library|libraries|framework|docs?|documentation|version|upgrade|dependency|dependencies|claude code|plugin|mcp|hook|hooks|skill|skills|agent|agents|react|vue|spring|spring boot|spring cloud|next\.?js|vite|webpack|npm|node)\b|最新|文档|依赖|框架|插件|官方|联网|搜索/i;
922
+ var CORE_REQUIRED = /* @__PURE__ */ new Set([
923
+ "context7",
924
+ "claude-mem",
925
+ "frontend-design",
926
+ "chrome-devtools-mcp",
927
+ "sequential-thinking",
928
+ "pua"
929
+ ]);
930
+ var EXTERNAL_DOCS_RE = /\b(api|sdk|library|libraries|framework|version|upgrade|dependency|dependencies|official docs?|latest docs?|claude code|plugin|mcp|hook|hooks|skill|skills|agent|agents|react|vue|spring|spring boot|spring cloud|next\.?js|vite|webpack|npm|node)\b|最新|依赖|框架|插件|官方|联网|搜索|文档.*(最新|官方|API|SDK|框架|插件|依赖)/i;
917
931
  var MEMORY_RE = /\b(previous|before|again|remember|memory|history|similar|repeated|regression|already solved|same bug|past decision)\b|之前|上次|记得|历史|做过|又|重复|老问题/i;
918
932
  var UI_RE = /\b(ui|ux|frontend|front-end|browser|chrome|dom|css|html|layout|component|page|form|modal|responsive|visual|render|react|vue|vite|next\.?js|screenshot|interaction)\b|前端|页面|浏览器|样式|交互|组件|布局|视觉|截图/i;
919
933
  var BROWSER_VERIFY_RE = /\b(browser|chrome|dom|css|network|console|performance|render|screenshot|e2e|playwright|visual regression|interaction)\b|浏览器|控制台|网络|性能|渲染|截图|端到端/i;
@@ -928,11 +942,14 @@ function hasAny(values, candidates) {
928
942
  const set = new Set((values ?? []).map((v) => v.toLowerCase()));
929
943
  return candidates.some((candidate) => set.has(candidate.toLowerCase()));
930
944
  }
931
- function capabilityAllowed(id, available) {
932
- return available === null || available.has(id);
945
+ function capabilityAvailability(id, available) {
946
+ if (CORE_REQUIRED.has(id)) return "core-required";
947
+ if (available === null) return "check-if-installed";
948
+ return available.has(id) ? "known-available" : null;
933
949
  }
934
950
  function pushRecommendation(out, available, id, phase, reason, instruction) {
935
- if (!capabilityAllowed(id, available)) return;
951
+ const availability = capabilityAvailability(id, available);
952
+ if (availability === null) return;
936
953
  if (out.some((rec) => rec.id === id)) return;
937
954
  const cap = CAPABILITIES[id];
938
955
  out.push({
@@ -941,6 +958,7 @@ function pushRecommendation(out, available, id, phase, reason, instruction) {
941
958
  type: cap.type,
942
959
  invocation: cap.invocation,
943
960
  phase,
961
+ availability,
944
962
  reason,
945
963
  instruction
946
964
  });
@@ -960,16 +978,17 @@ function recommendToolCapabilities(input) {
960
978
  if (missingRoots > 0) {
961
979
  return recs;
962
980
  }
963
- const localLowRisk = LOW_RISK_LOCAL_RE.test(goal) && route === "direct-change";
981
+ const externalDocsRelevant = EXTERNAL_DOCS_RE.test(goal);
982
+ const localLowRisk = LOW_RISK_LOCAL_RE.test(goal) && route === "direct-change" && !externalDocsRelevant;
964
983
  if (localLowRisk) {
965
984
  return recs;
966
985
  }
967
986
  const hasFrontend = UI_RE.test(goal) || hasAny(topologyKinds, ["frontend-app"]) || hasAny(topologyFrameworks, ["react", "vue", "next.js", "vite"]);
968
987
  const browserRuntime = BROWSER_VERIFY_RE.test(goal) || hasFrontend;
969
- const complex = COMPLEX_RE.test(goal) || risk === "high" || risk === "critical" || route === "full-spec" || route === "epic-split";
988
+ const complex = COMPLEX_RE.test(goal) && route !== "direct-change" || risk === "high" || risk === "critical" || route === "full-spec" || route === "epic-split";
970
989
  const stuck = STUCK_RE.test(goal);
971
990
  const parallel = PARALLEL_RE.test(goal) || route === "epic-split";
972
- if (DOCS_RE.test(goal)) {
991
+ if (externalDocsRelevant) {
973
992
  pushRecommendation(
974
993
  recs,
975
994
  available,
@@ -1045,25 +1064,25 @@ function renderInstalledCapabilityRules(availableCapabilities) {
1045
1064
  }
1046
1065
  function renderCapabilityDecisionTree(availableCapabilities) {
1047
1066
  const available = new Set(availableCapabilities);
1048
- const lines = [
1049
- "1. Can the edit be finished safely from local code in 1-2 steps? -> Do it directly."
1067
+ const rules = [
1068
+ "Can the edit be finished safely from local code in 1-2 steps? -> Do it directly."
1050
1069
  ];
1051
1070
  if (available.has("context7")) {
1052
- lines.push("2. Does correctness depend on external docs, SDKs, APIs, or Claude Code behavior? -> use the Context7 MCP before editing.");
1071
+ rules.push("Does correctness depend on external docs, SDKs, APIs, or Claude Code behavior? -> use the Context7 MCP before editing.");
1053
1072
  }
1054
1073
  if (available.has("claude-mem")) {
1055
- lines.push("3. Might similar work, a prior decision, or a repeated failure exist? -> Start with `/claude-mem:mem-search`.");
1074
+ rules.push("Might similar work, a prior decision, or a repeated failure exist? -> Start with `/claude-mem:mem-search`.");
1056
1075
  }
1057
1076
  if (available.has("frontend-design") || available.has("chrome-devtools-mcp")) {
1058
- lines.push("4. Is visible frontend behavior in scope? -> Use frontend-design for UI decisions and Chrome DevTools MCP for runtime proof when installed.");
1077
+ rules.push("Is visible frontend behavior in scope? -> Use frontend-design for UI decisions and Chrome DevTools MCP for runtime proof when installed.");
1059
1078
  }
1060
1079
  if (available.has("sequential-thinking")) {
1061
- lines.push("5. Is the work high-risk, architectural, or assumption-heavy? -> Use sequential-thinking after reading the relevant code.");
1080
+ rules.push("Is the work high-risk, architectural, or assumption-heavy? -> Use sequential-thinking after reading the relevant code.");
1062
1081
  }
1063
1082
  if (available.has("pua")) {
1064
- lines.push("6. Are there multiple failed attempts or truly independent parallel slices? -> Use `/pua:pua-loop` for recovery or `/pua:p9` for bounded parallel planning.");
1083
+ rules.push("Are there multiple failed attempts or truly independent parallel slices? -> Use `/pua:pua-loop` for recovery or `/pua:p9` for bounded parallel planning.");
1065
1084
  }
1066
- return lines;
1085
+ return rules.map((rule, idx) => `${idx + 1}. ${rule}`);
1067
1086
  }
1068
1087
  function parseList(value) {
1069
1088
  if (!value) return [];
@@ -1133,7 +1152,7 @@ function buildSkipRules(ids) {
1133
1152
  function buildDecisionTree(ids) {
1134
1153
  const out = renderCapabilityDecisionTree([...ids]);
1135
1154
  if (ids.has("curdx-flow")) {
1136
- out.push("7. Is the request ambiguous, cross-cutting, phase-based, or multi-root? -> Run /curdx-flow:start.");
1155
+ out.push(`${out.length + 1}. Is the request ambiguous, cross-cutting, phase-based, or multi-root? -> Run /curdx-flow:start.`);
1137
1156
  }
1138
1157
  return out;
1139
1158
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curdx/flow",
3
- "version": "7.1.19",
3
+ "version": "7.1.20",
4
4
  "description": "Interactive installer for Claude Code plugins and MCP servers",
5
5
  "type": "module",
6
6
  "bin": "./dist/index.mjs",