@curdx/flow 7.1.2 → 7.1.4
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 +34 -0
- package/README.md +477 -39
- package/README.zh-CN.md +505 -0
- package/dist/analyze-4DE3HVCA.mjs +794 -0
- package/dist/index.mjs +203 -45
- package/package.json +4 -2
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import * as p10 from "@clack/prompts";
|
|
5
|
-
import { defineCommand, runMain } from "citty";
|
|
5
|
+
import { defineCommand as defineCommand2, runMain } from "citty";
|
|
6
6
|
|
|
7
7
|
// src/ui/language.ts
|
|
8
8
|
import * as p from "@clack/prompts";
|
|
@@ -84,7 +84,17 @@ var messages = {
|
|
|
84
84
|
"claudeMd.unchanged": "CLAUDE.md \u5DF2\u662F\u6700\u65B0",
|
|
85
85
|
"claudeMd.removed": "\u5DF2\u4ECE CLAUDE.md \u79FB\u9664 @curdx/flow \u533A\u5757",
|
|
86
86
|
"claudeMd.skipped": "\u5DF2\u8DF3\u8FC7 CLAUDE.md \u540C\u6B65\uFF08--no-claude-md\uFF09",
|
|
87
|
-
"claudeMd.failed": "CLAUDE.md \u540C\u6B65\u5931\u8D25\uFF1A{error}"
|
|
87
|
+
"claudeMd.failed": "CLAUDE.md \u540C\u6B65\u5931\u8D25\uFF1A{error}",
|
|
88
|
+
"analyze.description": "\u89E3\u6790 Claude Code session jsonl + curdx-flow errors.jsonl\uFF0C\u8F93\u51FA markdown \u62A5\u544A",
|
|
89
|
+
"analyze.helpSummary": "analyze \u2014 \u672C\u5730\u89C2\u6D4B\uFF1A\u5408\u5E76 ~/.claude/projects/<cwd-encoded>/<sessionId>.jsonl \u4E0E ~/.claude/curdx-flow/errors.jsonl\uFF0C\u6E32\u67D3 7 \u6BB5 markdown\uFF08hook \u5931\u8D25 / slash command \u9891\u6B21 / subagent \u8C03\u5EA6 / spec \u6F0F\u6597 / hook \u65F6\u5EF6 P50/P95/P99 / schema \u6F02\u79FB / parentUuid \u94FE\u5B8C\u6574\u6027\uFF09",
|
|
90
|
+
"analyze.flags.json": "\u8F93\u51FA JSON \u800C\u975E markdown\uFF08CI \u53CB\u597D\uFF1B\u4E0E --out \u4E92\u65A5\u8BED\u4E49\uFF1AJSON \u4E0D\u5199\u6587\u4EF6\uFF09",
|
|
91
|
+
"analyze.flags.out": "\u628A markdown \u62A5\u544A\u5199\u5165\u6307\u5B9A\u6587\u4EF6\uFF08\u7F3A\u7701\u5199\u5230 stdout\uFF09",
|
|
92
|
+
"analyze.flags.limit": "\u8868\u683C\u6BB5 Top-N \u622A\u65AD\uFF08\u9ED8\u8BA4 10\uFF1B\u4F20 0 \u89C6\u4E3A\u65E0\u610F\u4E49\u56DE\u843D 10\uFF09",
|
|
93
|
+
"analyze.flags.since": "\u53EA\u7EDF\u8BA1\u76F8\u5BF9\u7A97\u53E3\u5185\u7684\u4E8B\u4EF6\uFF0C\u4F8B\u5982 `7d` / `24h` / `30m`\uFF08\u9ED8\u8BA4\u5168\u91CF\uFF1B--since \u4E0E\u589E\u91CF offset \u7F13\u5B58\u5171\u5B58\uFF0C\u7F13\u5B58\u547D\u4E2D\u65F6\u76F4\u63A5 replay \u4E0A\u6B21\u62A5\u544A\uFF09",
|
|
94
|
+
"analyze.flags.project": "\u6307\u5B9A ~/.claude/projects/ \u4E0B\u7684 encoded-cwd \u5B50\u76EE\u5F55\uFF1B\u7F3A\u7701\u6309\u5F53\u524D git \u4ED3\u5E93\u6839\u76EE\u5F55\u63A8\u65AD\uFF08\u975E git \u76EE\u5F55\u9000\u5316\u4E3A\u7A7A\u62A5\u544A + warning\uFF09",
|
|
95
|
+
"analyze.flags.includePrompts": "\u5173\u95ED\u9ED8\u8BA4 redact\uFF0C\u628A\u539F\u59CB prompt \u6587\u672C\u900F\u51FA\uFF08\u4EC5\u672C\u5730\u8C03\u8BD5\uFF0C\u8C28\u614E\u4F7F\u7528\uFF1BD-9 \u767D\u540D\u5355\u9ED8\u8BA4\u88C1\u526A\u6240\u6709\u672A\u5728\u767D\u540D\u5355\u5B57\u6BB5\uFF09",
|
|
96
|
+
"analyze.warning.noProject": "\u672A\u80FD\u4ECE cwd \u63A8\u65AD\u5230 ~/.claude/projects/ \u5B50\u76EE\u5F55\uFF08\u975E git \u4ED3\u5E93\u6216\u65E0\u5BF9\u5E94 session\uFF09\uFF1B\u8F93\u51FA\u7A7A\u62A5\u544A\uFF0C\u8BF7\u7528 --project \u663E\u5F0F\u6307\u5B9A",
|
|
97
|
+
"analyze.warning.schemaFallback": "plugins/curdx-flow/schemas/transcript-events.json \u672A\u627E\u5230\uFF0C\u56DE\u843D\u5230\u5185\u7F6E\u6700\u5C0F\u767D\u540D\u5355\u2014\u2014schema \u6F02\u79FB\u8BCA\u65AD\u53EF\u80FD\u6F0F\u62A5"
|
|
88
98
|
};
|
|
89
99
|
var zh_default = messages;
|
|
90
100
|
|
|
@@ -165,7 +175,17 @@ var messages2 = {
|
|
|
165
175
|
"claudeMd.unchanged": "CLAUDE.md already up to date",
|
|
166
176
|
"claudeMd.removed": "Removed @curdx/flow block from CLAUDE.md",
|
|
167
177
|
"claudeMd.skipped": "Skipped CLAUDE.md sync (--no-claude-md)",
|
|
168
|
-
"claudeMd.failed": "CLAUDE.md sync failed: {error}"
|
|
178
|
+
"claudeMd.failed": "CLAUDE.md sync failed: {error}",
|
|
179
|
+
"analyze.description": "Analyze Claude Code session jsonl + curdx-flow errors.jsonl, output markdown report",
|
|
180
|
+
"analyze.helpSummary": "analyze \u2014 local observability: merge ~/.claude/projects/<cwd-encoded>/<sessionId>.jsonl with ~/.claude/curdx-flow/errors.jsonl into 7 markdown sections (hook failures / slash command frequency / subagent dispatch / spec funnel / hook duration P50/P95/P99 / schema drift / parentUuid chain integrity)",
|
|
181
|
+
"analyze.flags.json": "Emit JSON instead of markdown (CI-friendly; --out is ignored when --json is set)",
|
|
182
|
+
"analyze.flags.out": "Write the markdown report to the given file path (defaults to stdout)",
|
|
183
|
+
"analyze.flags.limit": "Top-N truncation for tabular sections (default 10; 0 falls back to 10)",
|
|
184
|
+
"analyze.flags.since": "Only count events within a relative window such as `7d` / `24h` / `30m` (default: full history; --since coexists with the incremental offset cache, replays the last report when cache hits)",
|
|
185
|
+
"analyze.flags.project": "Pin to a specific encoded-cwd directory under ~/.claude/projects/; defaults to inferring from the current git repository root (non-git directories degrade to an empty report with a warning)",
|
|
186
|
+
"analyze.flags.includePrompts": "Skip default redaction and pass raw prompt text through (local debugging only; D-9 white-list redacts every non-whitelisted field by default)",
|
|
187
|
+
"analyze.warning.noProject": "Could not infer a ~/.claude/projects/ subdirectory from cwd (not a git repo or no matching session); emitting an empty report \u2014 pass --project to override",
|
|
188
|
+
"analyze.warning.schemaFallback": "plugins/curdx-flow/schemas/transcript-events.json not found, falling back to the builtin minimal whitelist \u2014 schema drift diagnostics may underreport"
|
|
169
189
|
};
|
|
170
190
|
var en_default = messages2;
|
|
171
191
|
|
|
@@ -175,6 +195,9 @@ var currentLang = "zh";
|
|
|
175
195
|
function setLang(lang) {
|
|
176
196
|
currentLang = lang;
|
|
177
197
|
}
|
|
198
|
+
function getLang() {
|
|
199
|
+
return currentLang;
|
|
200
|
+
}
|
|
178
201
|
function t(key, vars) {
|
|
179
202
|
const raw = tables[currentLang][key] ?? tables.en[key] ?? key;
|
|
180
203
|
if (!vars) return raw;
|
|
@@ -828,44 +851,111 @@ var BLOCK_RE = /<!-- BEGIN @curdx\/flow v\d+[^>]*-->[\s\S]*?<!-- END @curdx\/flo
|
|
|
828
851
|
function claudeMdPath() {
|
|
829
852
|
return path4.join(os2.homedir(), ".claude", "CLAUDE.md");
|
|
830
853
|
}
|
|
854
|
+
function isZh() {
|
|
855
|
+
return getLang() === "zh";
|
|
856
|
+
}
|
|
831
857
|
function buildCombinationPatterns(ids) {
|
|
832
858
|
const has = (k) => ids.has(k);
|
|
833
|
-
const out = [
|
|
859
|
+
const out = [
|
|
860
|
+
isZh() ? "\u6309\u573A\u666F\u4E32\u8054\uFF0C\u4F18\u5148\u6309\u80FD\u529B\u8FB9\u754C\u8C03\u7528\uFF1Aslash command\u3001MCP\u3001\u63D2\u4EF6 skill \u4E0D\u8981\u6DF7\u5199\u3002" : "Combine tools by capability. Keep slash commands, MCP tools, and plugin skills distinct.",
|
|
861
|
+
""
|
|
862
|
+
];
|
|
834
863
|
if (has("claude-mem") || has("context7") || has("curdx-flow")) {
|
|
835
|
-
out.push("- **\u63A5\u5230\u65B0\u9700\u6C42 / \u65B0 feature
|
|
864
|
+
out.push(isZh() ? "- **\u63A5\u5230\u65B0\u9700\u6C42 / \u65B0 feature**" : "- **Starting a new feature**");
|
|
836
865
|
let step = 1;
|
|
837
|
-
if (has("claude-mem"))
|
|
838
|
-
|
|
866
|
+
if (has("claude-mem")) {
|
|
867
|
+
out.push(
|
|
868
|
+
isZh() ? ` ${step++}. \u5148\u7528 \`/claude-mem:mem-search\` \u67E5\u5386\u53F2\uFF0C\u786E\u8BA4\u4E4B\u524D\u6709\u6CA1\u6709\u7C7B\u4F3C\u5B9E\u73B0\u3001\u8E29\u5751\u6216\u51B3\u7B56\u3002` : ` ${step++}. Start with \`/claude-mem:mem-search\` to check whether this work, decision, or pitfall already exists in memory.`
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
if (has("context7")) {
|
|
872
|
+
out.push(
|
|
873
|
+
isZh() ? ` ${step++}. \u6D89\u53CA\u5916\u90E8\u5E93\u3001SDK\u3001\u6846\u67B6\u6216 API \u65F6\uFF0C\u4F7F\u7528 Context7 MCP \u62C9\u5B98\u65B9\u6700\u65B0\u6587\u6863\u3002` : ` ${step++}. If external libraries, SDKs, frameworks, or APIs are involved, use the Context7 MCP to pull current official docs.`
|
|
874
|
+
);
|
|
875
|
+
}
|
|
839
876
|
const planners = [];
|
|
840
|
-
if (has("claude-mem"))
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
877
|
+
if (has("claude-mem")) {
|
|
878
|
+
planners.push(
|
|
879
|
+
isZh() ? "`/claude-mem:make-plan` \u4EA7\u51FA\u5206\u9636\u6BB5\u8BA1\u5212" : "`/claude-mem:make-plan` for a phased plan"
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
if (has("curdx-flow")) {
|
|
883
|
+
planners.push(
|
|
884
|
+
isZh() ? "`/curdx-flow:new` \u6216\u76F8\u5173 spec flow \u8D77\u5B8C\u6574\u89C4\u683C" : "`/curdx-flow:new` or the spec flow for a full specification"
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
if (planners.length > 0) {
|
|
888
|
+
out.push(
|
|
889
|
+
isZh() ? ` ${step++}. \u591A\u6B65\u9AA4\u3001\u9AD8\u4E0D\u786E\u5B9A\u6027\u3001\u8DE8\u6A21\u5757\u65F6\uFF0C\u518D\u8FDB\u5165 ${planners.join("\uFF0C\u6216 ")}\u3002` : ` ${step++}. Only move into ${planners.join(" or ")} when the work is multi-step, cross-cutting, or uncertain.`
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
out.push(
|
|
893
|
+
isZh() ? ` ${step++}. \u7B80\u5355\u3001\u8303\u56F4\u660E\u786E\u7684\u4E00\u6B21\u6027\u6539\u52A8\uFF0C\u76F4\u63A5\u505A\uFF0C\u4E0D\u8981\u5148\u628A\u6D41\u7A0B\u62C9\u6EE1\u3002` : ` ${step++}. For small, clear one-shot changes, implement directly instead of forcing the full workflow.`
|
|
894
|
+
);
|
|
844
895
|
out.push("");
|
|
845
896
|
}
|
|
846
897
|
const stuckLines = [];
|
|
847
898
|
let s = 1;
|
|
848
|
-
if (has("claude-mem"))
|
|
849
|
-
|
|
850
|
-
|
|
899
|
+
if (has("claude-mem")) {
|
|
900
|
+
stuckLines.push(
|
|
901
|
+
isZh() ? ` ${s++}. \u5148\u7528 \`/claude-mem:mem-search\` \u67E5\u8BB0\u5FC6\uFF0C\u786E\u8BA4\u662F\u4E0D\u662F\u4EE5\u524D\u89E3\u8FC7\u540C\u7C7B bug\u3002` : ` ${s++}. Check \`/claude-mem:mem-search\` first to see whether the same bug was solved before.`
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
if (has("chrome-devtools-mcp")) {
|
|
905
|
+
stuckLines.push(
|
|
906
|
+
isZh() ? ` ${s++}. \u6D4F\u89C8\u5668\u4FA7\u95EE\u9898\u4F7F\u7528 Chrome DevTools MCP\uFF1A\u770B network\u3001console\u3001performance\u3001DOM snapshot\u3002` : ` ${s++}. For browser-side issues, use the Chrome DevTools MCP for network, console, performance, and DOM snapshots.`
|
|
907
|
+
);
|
|
908
|
+
}
|
|
909
|
+
if (has("context7")) {
|
|
910
|
+
stuckLines.push(
|
|
911
|
+
isZh() ? ` ${s++}. \u5982\u679C\u6000\u7591\u662F\u5E93 / API \u884C\u4E3A\u53D8\u5316\uFF0C\u4F7F\u7528 Context7 MCP \u67E5\u5B98\u65B9\u6587\u6863\uFF0C\u4E0D\u8981\u51ED\u8BB0\u5FC6\u3002` : ` ${s++}. If the issue may come from library or API behavior, use the Context7 MCP instead of relying on memory.`
|
|
912
|
+
);
|
|
913
|
+
}
|
|
851
914
|
const stillStuck = [];
|
|
852
|
-
if (has("sequential-thinking"))
|
|
853
|
-
|
|
854
|
-
|
|
915
|
+
if (has("sequential-thinking")) {
|
|
916
|
+
stillStuck.push(
|
|
917
|
+
isZh() ? "\u4F7F\u7528 sequential-thinking MCP \u62C6\u5047\u8BBE" : "use the sequential-thinking MCP to break down hypotheses"
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
if (has("pua")) {
|
|
921
|
+
stillStuck.push(
|
|
922
|
+
isZh() ? "\u518D\u8FDB\u5165 `/pua:pua-loop` \u8FED\u4EE3" : "then enter `/pua:pua-loop` for structured retries"
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
if (stillStuck.length > 0) {
|
|
926
|
+
stuckLines.push(
|
|
927
|
+
isZh() ? ` ${s++}. \u4E24\u8F6E\u4EE5\u4E0A\u4ECD\u5361\u4F4F\uFF0C\u518D ${stillStuck.join("\uFF0C\u6216 ")}\u3002` : ` ${s++}. If you are still stuck after multiple attempts, ${stillStuck.join(" or ")}.`
|
|
928
|
+
);
|
|
929
|
+
}
|
|
855
930
|
if (stuckLines.length > 0) {
|
|
856
|
-
out.push("- **\u9047\u5230 bug / \u5361\u4F4F
|
|
931
|
+
out.push(isZh() ? "- **\u9047\u5230 bug / \u8FDE\u7EED\u5361\u4F4F**" : "- **Debugging and repeated failures**", ...stuckLines, "");
|
|
857
932
|
}
|
|
858
933
|
if (has("frontend-design") || has("chrome-devtools-mcp")) {
|
|
859
|
-
out.push("- **\u505A UI / \u524D\u7AEF\u9875\u9762**");
|
|
860
|
-
if (has("frontend-design"))
|
|
861
|
-
|
|
934
|
+
out.push(isZh() ? "- **\u505A UI / \u524D\u7AEF\u9875\u9762**" : "- **UI and frontend work**");
|
|
935
|
+
if (has("frontend-design")) {
|
|
936
|
+
out.push(
|
|
937
|
+
isZh() ? " - \u4F18\u5148\u4F7F\u7528 `frontend-design` \u63D2\u4EF6\u7684 UI skills\uFF1B\u82E5\u672A\u81EA\u52A8\u89E6\u53D1\uFF0C\u518D\u663E\u5F0F\u8C03\u7528\u5BF9\u5E94 skill\u3002" : " - Prioritize the `frontend-design` plugin skills for UI work; if they do not trigger automatically, invoke the relevant skill explicitly."
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
if (has("chrome-devtools-mcp")) {
|
|
941
|
+
out.push(
|
|
942
|
+
isZh() ? " - \u6E32\u67D3\u5F02\u5E38\u3001\u4EA4\u4E92\u95EE\u9898\u6216\u89C6\u89C9\u56DE\u5F52\uFF0C\u4F7F\u7528 Chrome DevTools MCP \u9A8C\u8BC1\uFF0C\u4E0D\u8981\u53EA\u9760\u8089\u773C\u731C\u3002" : " - For rendering issues, interaction bugs, or visual regressions, verify with the Chrome DevTools MCP instead of relying on visual guesswork alone."
|
|
943
|
+
);
|
|
944
|
+
}
|
|
862
945
|
out.push("");
|
|
863
946
|
}
|
|
864
947
|
if (has("pua") || has("curdx-flow")) {
|
|
865
|
-
out.push("- **\u5927\u578B / \u8DE8\u6A21\u5757 / \u591A agent \u534F\u4F5C**");
|
|
866
|
-
if (has("pua"))
|
|
867
|
-
|
|
868
|
-
|
|
948
|
+
out.push(isZh() ? "- **\u5927\u578B / \u8DE8\u6A21\u5757 / \u591A agent \u534F\u4F5C**" : "- **Large, cross-cutting, or multi-agent work**");
|
|
949
|
+
if (has("pua")) {
|
|
950
|
+
out.push(
|
|
951
|
+
isZh() ? " - \u9700\u8981\u5E76\u884C\u62C6\u89E3\u4E0E\u56E2\u961F\u534F\u4F5C\u65F6\uFF0C\u7528 `/pua:p9`\uFF1B\u66F4\u9AD8\u5C42\u6218\u7565\u89C4\u5212\u518D\u8003\u8651 `/pua:p10`\u3002" : " - Use `/pua:p9` for parallel task decomposition and team coordination; reserve `/pua:p10` for higher-level strategy work."
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
if (has("curdx-flow")) {
|
|
955
|
+
out.push(
|
|
956
|
+
isZh() ? " - \u4E00\u4E2A\u5927\u529F\u80FD\u9700\u8981\u62C6\u6210\u591A\u4E2A\u76F8\u4E92\u4F9D\u8D56\u7684\u89C4\u683C\u65F6\uFF0C\u4F7F\u7528 `/curdx-flow:triage`\u3002" : " - Use `/curdx-flow:triage` when one large feature needs to be split into multiple dependent specs."
|
|
957
|
+
);
|
|
958
|
+
}
|
|
869
959
|
}
|
|
870
960
|
while (out.length > 0 && out[out.length - 1] === "") out.pop();
|
|
871
961
|
return out;
|
|
@@ -873,48 +963,76 @@ function buildCombinationPatterns(ids) {
|
|
|
873
963
|
function buildSkipRules(ids) {
|
|
874
964
|
const has = (k) => ids.has(k);
|
|
875
965
|
const out = [];
|
|
876
|
-
out.push(
|
|
966
|
+
out.push(
|
|
967
|
+
isZh() ? "- \u4E00\u884C\u6539\u52A8\u3001typo\u3001\u7EAF\u91CD\u547D\u540D\u53D8\u91CF\uFF1A\u4E0D\u8981\u5148 plan\uFF0C\u4E0D\u8981\u5148\u5F00 spec\uFF0C\u76F4\u63A5\u6539\u3002" : "- For one-line changes, typos, or pure renames, skip planning and spec flow. Just make the edit."
|
|
968
|
+
);
|
|
877
969
|
const skips = [];
|
|
878
970
|
if (has("pua")) skips.push("`/pua:pua`");
|
|
879
971
|
if (has("sequential-thinking")) skips.push("`sequential-thinking`");
|
|
880
972
|
if (skips.length > 0) {
|
|
881
|
-
out.push(
|
|
973
|
+
out.push(
|
|
974
|
+
isZh() ? `- \u5DF2\u77E5\u786E\u5B9A\u7684 fix\uFF1A\u4E0D\u8981\u5148\u4E0A ${skips.join("\u3001")}\u3002` : `- For a known, deterministic fix, do not reach for ${skips.join(" or ")} first.`
|
|
975
|
+
);
|
|
882
976
|
}
|
|
883
|
-
out.push(
|
|
977
|
+
out.push(
|
|
978
|
+
isZh() ? "- \u7EAF\u6982\u5FF5\u89E3\u91CA\u9898\u53EF\u4EE5\u76F4\u63A5\u7B54\uFF1B\u5982\u679C\u662F\u5728\u95EE\u5F53\u524D\u4ED3\u5E93\u91CC\u7684\u4EE3\u7801\u542B\u4E49\uFF0C\u5148\u8BFB\u76F8\u5173\u6587\u4EF6\u518D\u89E3\u91CA\u3002" : "- Answer pure conceptual explanation questions directly. If the question is about code in this repository, read the relevant files first."
|
|
979
|
+
);
|
|
884
980
|
if (has("curdx-flow")) {
|
|
885
|
-
out.push(
|
|
981
|
+
out.push(
|
|
982
|
+
isZh() ? "- \u5355\u6587\u4EF6\u5C40\u90E8\u91CD\u6784\u6216\u5F88\u5C0F\u8303\u56F4\u7684\u6574\u7406\uFF1A\u901A\u5E38\u4E0D\u8981\u8FDB\u5165 curdx-flow spec \u6D41\u3002" : "- For a single-file refactor or a very local cleanup, usually do not enter the curdx-flow spec workflow."
|
|
983
|
+
);
|
|
886
984
|
}
|
|
887
985
|
return out;
|
|
888
986
|
}
|
|
889
987
|
function buildDecisionTree(ids) {
|
|
890
988
|
const has = (k) => ids.has(k);
|
|
891
989
|
const out = [];
|
|
892
|
-
out.push("1. \u80FD 1\u20132 \u6B65\u641E\u5B9A\uFF1F\u2192 \u76F4\u63A5\u505A");
|
|
893
|
-
out.push(
|
|
990
|
+
out.push(isZh() ? "1. \u80FD 1\u20132 \u6B65\u641E\u5B9A\uFF1F\u2192 \u76F4\u63A5\u505A\u3002" : "1. Can it be finished in 1-2 steps? -> Do it directly.");
|
|
991
|
+
out.push(
|
|
992
|
+
isZh() ? "2. \u591A\u6B65\u9AA4\u4F46\u8DEF\u5F84\u6E05\u6670\uFF1F\u2192 \u62C6\u6210\u7B80\u77ED\u4EFB\u52A1\u5217\u8868\u9010\u4E2A\u63A8\u8FDB\uFF0C\u4E0D\u8981\u9ED8\u8BA4\u8FDB\u5165\u5B8C\u6574 spec \u6D41\u3002" : "2. Is it multi-step but still clear? -> Break it into a short task list and execute without defaulting to the full spec flow."
|
|
993
|
+
);
|
|
894
994
|
const planners = [];
|
|
895
995
|
if (has("curdx-flow")) planners.push("`/curdx-flow:new`");
|
|
896
|
-
if (has("claude-mem")) planners.push("
|
|
996
|
+
if (has("claude-mem")) planners.push("`/claude-mem:make-plan`");
|
|
897
997
|
if (planners.length > 0) {
|
|
898
|
-
out.push(
|
|
998
|
+
out.push(
|
|
999
|
+
isZh() ? `3. \u9700\u6C42\u6A21\u7CCA\u3001\u8DE8\u6A21\u5757\u3001\u9700\u8981\u5206\u9636\u6BB5\u4EA4\u4ED8\uFF1F\u2192 ${planners.join(" \u6216 ")}\u3002` : `3. Is the request ambiguous, cross-cutting, or phase-based? -> ${planners.join(" or ")}.`
|
|
1000
|
+
);
|
|
899
1001
|
}
|
|
900
1002
|
if (has("claude-mem")) {
|
|
901
|
-
out.push(
|
|
1003
|
+
out.push(
|
|
1004
|
+
isZh() ? "4. \u8FD9\u7C7B\u6D3B\u4EE5\u524D\u53EF\u80FD\u505A\u8FC7\uFF1F\u2192 \u5148 `/claude-mem:mem-search`\u3002" : "4. Might this work have been done before? -> Start with `/claude-mem:mem-search`."
|
|
1005
|
+
);
|
|
902
1006
|
}
|
|
903
1007
|
return out;
|
|
904
1008
|
}
|
|
1009
|
+
function buildLanguagePolicy() {
|
|
1010
|
+
if (getLang() !== "zh") return [];
|
|
1011
|
+
return [
|
|
1012
|
+
"- Tool and model interaction must be in English.",
|
|
1013
|
+
"- All user-facing responses must be in Simplified Chinese."
|
|
1014
|
+
];
|
|
1015
|
+
}
|
|
905
1016
|
function renderBlock(items) {
|
|
906
1017
|
const installedIds = new Set(items.map((i) => i.id));
|
|
907
1018
|
const sections = [
|
|
908
|
-
["##
|
|
909
|
-
[
|
|
910
|
-
|
|
1019
|
+
["## Language Policy\uFF08\u8BED\u8A00\u89C4\u5219\uFF09", buildLanguagePolicy()],
|
|
1020
|
+
[
|
|
1021
|
+
isZh() ? "## Tool Combination Patterns\uFF08\u7EC4\u5408\u5DE5\u4F5C\u6D41\uFF09" : "## Tool Combination Patterns",
|
|
1022
|
+
buildCombinationPatterns(installedIds)
|
|
1023
|
+
],
|
|
1024
|
+
[isZh() ? "## Skip Rules\uFF08\u9632\u8FC7\u5EA6\u5DE5\u5177\u5316\uFF09" : "## Skip Rules", buildSkipRules(installedIds)],
|
|
1025
|
+
[isZh() ? "## Decision Tree\uFF08\u9047\u5230\u6A21\u7CCA\u8BF7\u6C42\u65F6\uFF09" : "## Decision Tree", buildDecisionTree(installedIds)]
|
|
911
1026
|
];
|
|
912
1027
|
const lines = [BEGIN_MARKER];
|
|
913
1028
|
for (const [heading, body] of sections) {
|
|
914
1029
|
if (body.length === 0) continue;
|
|
915
1030
|
lines.push(heading, "", ...body, "");
|
|
916
1031
|
}
|
|
917
|
-
lines.push(
|
|
1032
|
+
lines.push(
|
|
1033
|
+
isZh() ? "\u8FD0\u884C `npx @curdx/flow` \u4EE5 install / update / uninstall\u3002" : "Run `npx @curdx/flow` to install / update / uninstall.",
|
|
1034
|
+
END_MARKER
|
|
1035
|
+
);
|
|
918
1036
|
return lines.join("\n");
|
|
919
1037
|
}
|
|
920
1038
|
function withEol(s, eol) {
|
|
@@ -1554,6 +1672,45 @@ async function mainMenu() {
|
|
|
1554
1672
|
}
|
|
1555
1673
|
}
|
|
1556
1674
|
|
|
1675
|
+
// src/flows/analyze.ts
|
|
1676
|
+
import { defineCommand } from "citty";
|
|
1677
|
+
var analyzeCmd = defineCommand({
|
|
1678
|
+
meta: {
|
|
1679
|
+
name: "analyze",
|
|
1680
|
+
description: "Analyze Claude Code session jsonl + curdx-flow errors.jsonl into a markdown report"
|
|
1681
|
+
},
|
|
1682
|
+
args: {
|
|
1683
|
+
out: {
|
|
1684
|
+
type: "string",
|
|
1685
|
+
description: "Output file path (default: stdout)"
|
|
1686
|
+
},
|
|
1687
|
+
json: {
|
|
1688
|
+
type: "boolean",
|
|
1689
|
+
description: "Emit JSON instead of markdown"
|
|
1690
|
+
},
|
|
1691
|
+
limit: {
|
|
1692
|
+
type: "string",
|
|
1693
|
+
description: "Top-N truncation for tabular sections (default: 10)"
|
|
1694
|
+
},
|
|
1695
|
+
"include-prompts": {
|
|
1696
|
+
type: "boolean",
|
|
1697
|
+
description: "Skip prompt redaction (D-9 white-list passthrough disabled \u2014 local debugging only)"
|
|
1698
|
+
}
|
|
1699
|
+
},
|
|
1700
|
+
async run({ args }) {
|
|
1701
|
+
const limitRaw = args.limit;
|
|
1702
|
+
const limit = typeof limitRaw === "string" && limitRaw.length > 0 ? Number(limitRaw) : void 0;
|
|
1703
|
+
const { runAnalyze } = await import("./analyze-4DE3HVCA.mjs");
|
|
1704
|
+
await runAnalyze({
|
|
1705
|
+
out: typeof args.out === "string" ? args.out : void 0,
|
|
1706
|
+
json: Boolean(args.json),
|
|
1707
|
+
limit: Number.isFinite(limit) ? limit : void 0,
|
|
1708
|
+
includePrompts: Boolean(args["include-prompts"])
|
|
1709
|
+
});
|
|
1710
|
+
}
|
|
1711
|
+
});
|
|
1712
|
+
var analyze_default = analyzeCmd;
|
|
1713
|
+
|
|
1557
1714
|
// src/index.ts
|
|
1558
1715
|
function parseLang(v) {
|
|
1559
1716
|
return v === "zh" || v === "en" ? v : void 0;
|
|
@@ -1569,7 +1726,7 @@ var sharedArgs = {
|
|
|
1569
1726
|
description: "Skip syncing the @curdx/flow block in ~/.claude/CLAUDE.md"
|
|
1570
1727
|
}
|
|
1571
1728
|
};
|
|
1572
|
-
var installCmd =
|
|
1729
|
+
var installCmd = defineCommand2({
|
|
1573
1730
|
meta: { name: "install", description: "Install, reinstall, or update plugins / MCP servers" },
|
|
1574
1731
|
args: {
|
|
1575
1732
|
...sharedArgs,
|
|
@@ -1592,7 +1749,7 @@ var installCmd = defineCommand({
|
|
|
1592
1749
|
p10.outro(t("app.outro"));
|
|
1593
1750
|
}
|
|
1594
1751
|
});
|
|
1595
|
-
var uninstallCmd =
|
|
1752
|
+
var uninstallCmd = defineCommand2({
|
|
1596
1753
|
meta: { name: "uninstall", description: "Uninstall installed plugins / MCP servers" },
|
|
1597
1754
|
args: {
|
|
1598
1755
|
...sharedArgs,
|
|
@@ -1611,7 +1768,7 @@ var uninstallCmd = defineCommand({
|
|
|
1611
1768
|
p10.outro(t("app.outro"));
|
|
1612
1769
|
}
|
|
1613
1770
|
});
|
|
1614
|
-
var updateCmd =
|
|
1771
|
+
var updateCmd = defineCommand2({
|
|
1615
1772
|
meta: { name: "update", description: "Update installed plugins" },
|
|
1616
1773
|
args: {
|
|
1617
1774
|
...sharedArgs,
|
|
@@ -1630,7 +1787,7 @@ var updateCmd = defineCommand({
|
|
|
1630
1787
|
p10.outro(t("app.outro"));
|
|
1631
1788
|
}
|
|
1632
1789
|
});
|
|
1633
|
-
var statusCmd =
|
|
1790
|
+
var statusCmd = defineCommand2({
|
|
1634
1791
|
meta: { name: "status", description: "Show install status" },
|
|
1635
1792
|
args: {
|
|
1636
1793
|
...sharedArgs,
|
|
@@ -1643,8 +1800,8 @@ var statusCmd = defineCommand({
|
|
|
1643
1800
|
if (!args.json) p10.outro(t("app.outro"));
|
|
1644
1801
|
}
|
|
1645
1802
|
});
|
|
1646
|
-
var SUBCOMMANDS = /* @__PURE__ */ new Set(["install", "uninstall", "update", "status"]);
|
|
1647
|
-
var root =
|
|
1803
|
+
var SUBCOMMANDS = /* @__PURE__ */ new Set(["install", "uninstall", "update", "status", "analyze"]);
|
|
1804
|
+
var root = defineCommand2({
|
|
1648
1805
|
meta: {
|
|
1649
1806
|
name: "@curdx/flow",
|
|
1650
1807
|
version: "3.3.2",
|
|
@@ -1655,7 +1812,8 @@ var root = defineCommand({
|
|
|
1655
1812
|
install: installCmd,
|
|
1656
1813
|
uninstall: uninstallCmd,
|
|
1657
1814
|
update: updateCmd,
|
|
1658
|
-
status: statusCmd
|
|
1815
|
+
status: statusCmd,
|
|
1816
|
+
analyze: analyze_default
|
|
1659
1817
|
}
|
|
1660
1818
|
// No root run() — citty 0.1.6 calls parent.run AFTER a matching subcommand,
|
|
1661
1819
|
// which would render the menu after a subcommand finishes. We dispatch the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curdx/flow",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.4",
|
|
4
4
|
"description": "Interactive installer for Claude Code plugins and MCP servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": "./dist/index.mjs",
|
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
"build": "tsup",
|
|
16
16
|
"build:hooks": "node scripts/build-hooks.mjs",
|
|
17
17
|
"check:hooks-fresh": "node scripts/check-hooks-fresh.mjs",
|
|
18
|
+
"check:bundle": "node scripts/check-bundle-size.mjs",
|
|
18
19
|
"dev": "tsup --watch",
|
|
19
20
|
"test:hooks": "npm run build:hooks && vitest run tests/hooks --passWithNoTests",
|
|
21
|
+
"test:analyze": "vitest run tests/analyze",
|
|
20
22
|
"start": "node ./dist/index.mjs",
|
|
21
23
|
"typecheck": "tsc --noEmit",
|
|
22
|
-
"verify": "npm run typecheck && npm run check-versions && npm run check:hooks-fresh && npm run test:hooks",
|
|
24
|
+
"verify": "npm run typecheck && npm run check-versions && npm run check:hooks-fresh && npm run build && npm run check:bundle && npm run test:hooks && npm run test:analyze",
|
|
23
25
|
"check-versions": "node scripts/check-versions.mjs",
|
|
24
26
|
"bump-version": "node scripts/bump-version.mjs",
|
|
25
27
|
"prepublishOnly": "node scripts/check-versions.mjs && npm run typecheck && npm run check:hooks-fresh && npm run build"
|