ccg-workflow 1.0.5 → 1.1.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/dist/cli.mjs +4 -2
- package/dist/index.d.mts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.mjs +3 -1
- package/dist/shared/{ccg-workflow.BXUs_-47.mjs → ccg-workflow.BJvXd6ru.mjs} +179 -7
- package/package.json +1 -1
- package/templates/commands/agents/planner.md +320 -0
- package/templates/commands/agents/ui-ux-designer.md +573 -0
- package/templates/commands/feat.md +761 -0
- package/templates/commands/scan.md +569 -0
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cac from 'cac';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import { r as readCcgConfig, b as initI18n, s as showMainMenu, i as init, a as i18n } from './shared/ccg-workflow.
|
|
4
|
+
import { r as readCcgConfig, b as initI18n, s as showMainMenu, i as init, a as i18n } from './shared/ccg-workflow.BJvXd6ru.mjs';
|
|
5
5
|
import 'inquirer';
|
|
6
6
|
import 'node:os';
|
|
7
7
|
import 'pathe';
|
|
@@ -10,8 +10,10 @@ import 'fs-extra';
|
|
|
10
10
|
import 'node:url';
|
|
11
11
|
import 'ora';
|
|
12
12
|
import 'smol-toml';
|
|
13
|
+
import 'node:child_process';
|
|
14
|
+
import 'node:util';
|
|
13
15
|
|
|
14
|
-
const version = "1.0
|
|
16
|
+
const version = "1.1.0";
|
|
15
17
|
|
|
16
18
|
function customizeHelp(sections) {
|
|
17
19
|
sections.unshift({
|
package/dist/index.d.mts
CHANGED
|
@@ -85,6 +85,11 @@ declare function init(options?: InitOptions): Promise<void>;
|
|
|
85
85
|
|
|
86
86
|
declare function showMainMenu(): Promise<void>;
|
|
87
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Main update command - checks for updates and installs if available
|
|
90
|
+
*/
|
|
91
|
+
declare function update(): Promise<void>;
|
|
92
|
+
|
|
88
93
|
declare const i18n: i18next.i18n;
|
|
89
94
|
declare function initI18n(lang?: SupportedLang): Promise<void>;
|
|
90
95
|
declare function changeLanguage(lang: SupportedLang): Promise<void>;
|
|
@@ -130,5 +135,27 @@ declare function installAceTool(config: AceToolConfig): Promise<{
|
|
|
130
135
|
configPath?: string;
|
|
131
136
|
}>;
|
|
132
137
|
|
|
133
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Get current installed version from package.json
|
|
140
|
+
*/
|
|
141
|
+
declare function getCurrentVersion(): Promise<string>;
|
|
142
|
+
/**
|
|
143
|
+
* Get latest version from npm registry
|
|
144
|
+
*/
|
|
145
|
+
declare function getLatestVersion(packageName?: string): Promise<string | null>;
|
|
146
|
+
/**
|
|
147
|
+
* Compare two semantic versions
|
|
148
|
+
* @returns 1 if v1 > v2, -1 if v1 < v2, 0 if equal
|
|
149
|
+
*/
|
|
150
|
+
declare function compareVersions(v1: string, v2: string): number;
|
|
151
|
+
/**
|
|
152
|
+
* Check if update is available
|
|
153
|
+
*/
|
|
154
|
+
declare function checkForUpdates(): Promise<{
|
|
155
|
+
hasUpdate: boolean;
|
|
156
|
+
currentVersion: string;
|
|
157
|
+
latestVersion: string | null;
|
|
158
|
+
}>;
|
|
159
|
+
|
|
160
|
+
export { changeLanguage, checkForUpdates, compareVersions, createDefaultConfig, createDefaultRouting, getCcgDir, getConfigPath, getCurrentVersion, getLatestVersion, getWorkflowById, getWorkflowConfigs, i18n, init, initI18n, installAceTool, installWorkflows, readCcgConfig, showMainMenu, uninstallAceTool, uninstallWorkflows, update, writeCcgConfig };
|
|
134
161
|
export type { AceToolConfig, CcgConfig, CliOptions, CollaborationMode, InitOptions, InstallResult, ModelRouting, ModelType, RoutingStrategy, SupportedLang, WorkflowConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -85,6 +85,11 @@ declare function init(options?: InitOptions): Promise<void>;
|
|
|
85
85
|
|
|
86
86
|
declare function showMainMenu(): Promise<void>;
|
|
87
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Main update command - checks for updates and installs if available
|
|
90
|
+
*/
|
|
91
|
+
declare function update(): Promise<void>;
|
|
92
|
+
|
|
88
93
|
declare const i18n: i18next.i18n;
|
|
89
94
|
declare function initI18n(lang?: SupportedLang): Promise<void>;
|
|
90
95
|
declare function changeLanguage(lang: SupportedLang): Promise<void>;
|
|
@@ -130,5 +135,27 @@ declare function installAceTool(config: AceToolConfig): Promise<{
|
|
|
130
135
|
configPath?: string;
|
|
131
136
|
}>;
|
|
132
137
|
|
|
133
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Get current installed version from package.json
|
|
140
|
+
*/
|
|
141
|
+
declare function getCurrentVersion(): Promise<string>;
|
|
142
|
+
/**
|
|
143
|
+
* Get latest version from npm registry
|
|
144
|
+
*/
|
|
145
|
+
declare function getLatestVersion(packageName?: string): Promise<string | null>;
|
|
146
|
+
/**
|
|
147
|
+
* Compare two semantic versions
|
|
148
|
+
* @returns 1 if v1 > v2, -1 if v1 < v2, 0 if equal
|
|
149
|
+
*/
|
|
150
|
+
declare function compareVersions(v1: string, v2: string): number;
|
|
151
|
+
/**
|
|
152
|
+
* Check if update is available
|
|
153
|
+
*/
|
|
154
|
+
declare function checkForUpdates(): Promise<{
|
|
155
|
+
hasUpdate: boolean;
|
|
156
|
+
currentVersion: string;
|
|
157
|
+
latestVersion: string | null;
|
|
158
|
+
}>;
|
|
159
|
+
|
|
160
|
+
export { changeLanguage, checkForUpdates, compareVersions, createDefaultConfig, createDefaultRouting, getCcgDir, getConfigPath, getCurrentVersion, getLatestVersion, getWorkflowById, getWorkflowConfigs, i18n, init, initI18n, installAceTool, installWorkflows, readCcgConfig, showMainMenu, uninstallAceTool, uninstallWorkflows, update, writeCcgConfig };
|
|
134
161
|
export type { AceToolConfig, CcgConfig, CliOptions, CollaborationMode, InitOptions, InstallResult, ModelRouting, ModelType, RoutingStrategy, SupportedLang, WorkflowConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as changeLanguage, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, k as installWorkflows, r as readCcgConfig, s as showMainMenu,
|
|
1
|
+
export { c as changeLanguage, q as checkForUpdates, t as compareVersions, d as createDefaultConfig, e as createDefaultRouting, g as getCcgDir, f as getConfigPath, o as getCurrentVersion, p as getLatestVersion, j as getWorkflowById, h as getWorkflowConfigs, a as i18n, i as init, b as initI18n, l as installAceTool, k as installWorkflows, r as readCcgConfig, s as showMainMenu, n as uninstallAceTool, m as uninstallWorkflows, u as update, w as writeCcgConfig } from './shared/ccg-workflow.BJvXd6ru.mjs';
|
|
2
2
|
import 'ansis';
|
|
3
3
|
import 'inquirer';
|
|
4
4
|
import 'node:os';
|
|
@@ -8,3 +8,5 @@ import 'fs-extra';
|
|
|
8
8
|
import 'node:url';
|
|
9
9
|
import 'ora';
|
|
10
10
|
import 'smol-toml';
|
|
11
|
+
import 'node:child_process';
|
|
12
|
+
import 'node:util';
|
|
@@ -7,6 +7,8 @@ import fs from 'fs-extra';
|
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import ora from 'ora';
|
|
9
9
|
import { parse, stringify } from 'smol-toml';
|
|
10
|
+
import { exec } from 'node:child_process';
|
|
11
|
+
import { promisify } from 'node:util';
|
|
10
12
|
|
|
11
13
|
const i18n = i18next;
|
|
12
14
|
const zhCN = {
|
|
@@ -382,9 +384,9 @@ function createDefaultRouting() {
|
|
|
382
384
|
};
|
|
383
385
|
}
|
|
384
386
|
|
|
385
|
-
const __filename$
|
|
386
|
-
const __dirname$
|
|
387
|
-
function findPackageRoot(startDir) {
|
|
387
|
+
const __filename$2 = fileURLToPath(import.meta.url);
|
|
388
|
+
const __dirname$2 = dirname(__filename$2);
|
|
389
|
+
function findPackageRoot$1(startDir) {
|
|
388
390
|
let dir = startDir;
|
|
389
391
|
for (let i = 0; i < 5; i++) {
|
|
390
392
|
if (fs.existsSync(join(dir, "package.json"))) {
|
|
@@ -394,7 +396,7 @@ function findPackageRoot(startDir) {
|
|
|
394
396
|
}
|
|
395
397
|
return startDir;
|
|
396
398
|
}
|
|
397
|
-
const PACKAGE_ROOT = findPackageRoot(__dirname$
|
|
399
|
+
const PACKAGE_ROOT$1 = findPackageRoot$1(__dirname$2);
|
|
398
400
|
const WORKFLOW_CONFIGS = [
|
|
399
401
|
{
|
|
400
402
|
id: "dev",
|
|
@@ -582,6 +584,28 @@ const WORKFLOW_CONFIGS = [
|
|
|
582
584
|
order: 30,
|
|
583
585
|
description: "\u521D\u59CB\u5316\u9879\u76EE AI \u4E0A\u4E0B\u6587\uFF0C\u751F\u6210/\u66F4\u65B0\u6839\u7EA7\u4E0E\u6A21\u5757\u7EA7 CLAUDE.md \u7D22\u5F15",
|
|
584
586
|
descriptionEn: "Initialize project AI context, generate/update root and module level CLAUDE.md index"
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
id: "scan",
|
|
590
|
+
name: "\u667A\u80FD\u4ED3\u5E93\u626B\u63CF",
|
|
591
|
+
nameEn: "Smart Repository Scan",
|
|
592
|
+
category: "planning",
|
|
593
|
+
commands: ["scan"],
|
|
594
|
+
defaultSelected: true,
|
|
595
|
+
order: 31,
|
|
596
|
+
description: "\u667A\u80FD\u4ED3\u5E93\u626B\u63CF - \u751F\u6210\u9879\u76EE\u4E0A\u4E0B\u6587\u62A5\u544A\uFF08\u6280\u672F\u6808\u3001API\u3001\u6570\u636E\u6A21\u578B\u3001\u7EC4\u4EF6\u7ED3\u6784\uFF09",
|
|
597
|
+
descriptionEn: "Smart repository scan - generate project context report (tech stack, APIs, data models, components)"
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
id: "feat",
|
|
601
|
+
name: "\u667A\u80FD\u529F\u80FD\u5F00\u53D1",
|
|
602
|
+
nameEn: "Smart Feature Development",
|
|
603
|
+
category: "planning",
|
|
604
|
+
commands: ["feat"],
|
|
605
|
+
defaultSelected: true,
|
|
606
|
+
order: 32,
|
|
607
|
+
description: "\u667A\u80FD\u529F\u80FD\u5F00\u53D1 - \u81EA\u52A8\u89C4\u5212\u3001\u8BBE\u8BA1\u3001\u5B9E\u65BD\uFF08\u652F\u6301\u9700\u6C42\u89C4\u5212/\u8BA8\u8BBA\u8FED\u4EE3/\u6267\u884C\u5B9E\u65BD\uFF09",
|
|
608
|
+
descriptionEn: "Smart feature development - auto plan, design, implement (supports planning/iteration/execution modes)"
|
|
585
609
|
}
|
|
586
610
|
];
|
|
587
611
|
function getWorkflowConfigs() {
|
|
@@ -602,7 +626,7 @@ async function installWorkflows(workflowIds, installDir, force = false) {
|
|
|
602
626
|
const promptsDir = join(installDir, "prompts", "ccg");
|
|
603
627
|
await fs.ensureDir(commandsDir);
|
|
604
628
|
await fs.ensureDir(promptsDir);
|
|
605
|
-
const templateDir = join(PACKAGE_ROOT, "templates");
|
|
629
|
+
const templateDir = join(PACKAGE_ROOT$1, "templates");
|
|
606
630
|
for (const workflowId of workflowIds) {
|
|
607
631
|
const workflow = getWorkflowById(workflowId);
|
|
608
632
|
if (!workflow) {
|
|
@@ -1035,6 +1059,154 @@ async function init(options = {}) {
|
|
|
1035
1059
|
}
|
|
1036
1060
|
}
|
|
1037
1061
|
|
|
1062
|
+
const execAsync = promisify(exec);
|
|
1063
|
+
const __filename$1 = fileURLToPath(import.meta.url);
|
|
1064
|
+
const __dirname$1 = dirname(__filename$1);
|
|
1065
|
+
function findPackageRoot(startDir) {
|
|
1066
|
+
let dir = startDir;
|
|
1067
|
+
for (let i = 0; i < 5; i++) {
|
|
1068
|
+
if (fs.existsSync(join(dir, "package.json"))) {
|
|
1069
|
+
return dir;
|
|
1070
|
+
}
|
|
1071
|
+
dir = dirname(dir);
|
|
1072
|
+
}
|
|
1073
|
+
return startDir;
|
|
1074
|
+
}
|
|
1075
|
+
const PACKAGE_ROOT = findPackageRoot(__dirname$1);
|
|
1076
|
+
async function getCurrentVersion() {
|
|
1077
|
+
try {
|
|
1078
|
+
const pkgPath = join(PACKAGE_ROOT, "package.json");
|
|
1079
|
+
const pkg = await fs.readJSON(pkgPath);
|
|
1080
|
+
return pkg.version || "0.0.0";
|
|
1081
|
+
} catch {
|
|
1082
|
+
return "0.0.0";
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
async function getLatestVersion(packageName = "ccg-workflow") {
|
|
1086
|
+
try {
|
|
1087
|
+
const { stdout } = await execAsync(`npm view ${packageName} version`);
|
|
1088
|
+
return stdout.trim();
|
|
1089
|
+
} catch {
|
|
1090
|
+
return null;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
function compareVersions(v1, v2) {
|
|
1094
|
+
const parts1 = v1.split(".").map(Number);
|
|
1095
|
+
const parts2 = v2.split(".").map(Number);
|
|
1096
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
1097
|
+
const num1 = parts1[i] || 0;
|
|
1098
|
+
const num2 = parts2[i] || 0;
|
|
1099
|
+
if (num1 > num2)
|
|
1100
|
+
return 1;
|
|
1101
|
+
if (num1 < num2)
|
|
1102
|
+
return -1;
|
|
1103
|
+
}
|
|
1104
|
+
return 0;
|
|
1105
|
+
}
|
|
1106
|
+
async function checkForUpdates() {
|
|
1107
|
+
const currentVersion = await getCurrentVersion();
|
|
1108
|
+
const latestVersion = await getLatestVersion();
|
|
1109
|
+
if (!latestVersion) {
|
|
1110
|
+
return {
|
|
1111
|
+
hasUpdate: false,
|
|
1112
|
+
currentVersion,
|
|
1113
|
+
latestVersion: null
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
const hasUpdate = compareVersions(latestVersion, currentVersion) > 0;
|
|
1117
|
+
return {
|
|
1118
|
+
hasUpdate,
|
|
1119
|
+
currentVersion,
|
|
1120
|
+
latestVersion
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
promisify(exec);
|
|
1125
|
+
async function update() {
|
|
1126
|
+
console.log();
|
|
1127
|
+
console.log(ansis.cyan.bold("\u{1F504} \u68C0\u67E5\u66F4\u65B0..."));
|
|
1128
|
+
console.log();
|
|
1129
|
+
const spinner = ora("\u6B63\u5728\u68C0\u67E5\u6700\u65B0\u7248\u672C...").start();
|
|
1130
|
+
try {
|
|
1131
|
+
const { hasUpdate, currentVersion, latestVersion } = await checkForUpdates();
|
|
1132
|
+
spinner.stop();
|
|
1133
|
+
if (!latestVersion) {
|
|
1134
|
+
console.log(ansis.red("\u274C \u65E0\u6CD5\u8FDE\u63A5\u5230 npm registry\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5"));
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
console.log(`\u5F53\u524D\u7248\u672C: ${ansis.yellow(`v${currentVersion}`)}`);
|
|
1138
|
+
console.log(`\u6700\u65B0\u7248\u672C: ${ansis.green(`v${latestVersion}`)}`);
|
|
1139
|
+
console.log();
|
|
1140
|
+
if (!hasUpdate) {
|
|
1141
|
+
console.log(ansis.green("\u2705 \u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF01"));
|
|
1142
|
+
const { forceReinstall } = await inquirer.prompt([{
|
|
1143
|
+
type: "confirm",
|
|
1144
|
+
name: "forceReinstall",
|
|
1145
|
+
message: "\u8981\u5F3A\u5236\u91CD\u65B0\u5B89\u88C5\u5F53\u524D\u7248\u672C\u5417\uFF1F\uFF08\u53EF\u4FEE\u590D\u635F\u574F\u7684\u6587\u4EF6\uFF09",
|
|
1146
|
+
default: false
|
|
1147
|
+
}]);
|
|
1148
|
+
if (!forceReinstall) {
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
} else {
|
|
1152
|
+
const { confirmUpdate } = await inquirer.prompt([{
|
|
1153
|
+
type: "confirm",
|
|
1154
|
+
name: "confirmUpdate",
|
|
1155
|
+
message: `\u786E\u8BA4\u8981\u66F4\u65B0\u5230 v${latestVersion} \u5417\uFF1F`,
|
|
1156
|
+
default: true
|
|
1157
|
+
}]);
|
|
1158
|
+
if (!confirmUpdate) {
|
|
1159
|
+
console.log(ansis.gray("\u5DF2\u53D6\u6D88\u66F4\u65B0"));
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
await performUpdate(currentVersion, latestVersion || currentVersion);
|
|
1164
|
+
} catch (error) {
|
|
1165
|
+
spinner.stop();
|
|
1166
|
+
console.log(ansis.red(`\u274C \u66F4\u65B0\u5931\u8D25: ${error}`));
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
async function performUpdate(fromVersion, toVersion) {
|
|
1170
|
+
console.log();
|
|
1171
|
+
console.log(ansis.yellow.bold("\u2699\uFE0F \u5F00\u59CB\u66F4\u65B0..."));
|
|
1172
|
+
console.log();
|
|
1173
|
+
const spinner = ora("\u66F4\u65B0\u547D\u4EE4\u6A21\u677F\u548C\u63D0\u793A\u8BCD...").start();
|
|
1174
|
+
try {
|
|
1175
|
+
const config = await readCcgConfig();
|
|
1176
|
+
const workflows = config?.workflows?.installed || [];
|
|
1177
|
+
const installDir = join(homedir(), ".claude");
|
|
1178
|
+
const result = await installWorkflows(workflows, installDir, true);
|
|
1179
|
+
if (result.success) {
|
|
1180
|
+
spinner.succeed("\u547D\u4EE4\u6A21\u677F\u548C\u63D0\u793A\u8BCD\u66F4\u65B0\u6210\u529F");
|
|
1181
|
+
console.log();
|
|
1182
|
+
console.log(ansis.cyan(`\u5DF2\u66F4\u65B0 ${result.installedCommands.length} \u4E2A\u547D\u4EE4:`));
|
|
1183
|
+
for (const cmd of result.installedCommands) {
|
|
1184
|
+
console.log(` ${ansis.gray("\u2022")} /ccg:${cmd}`);
|
|
1185
|
+
}
|
|
1186
|
+
if (config) {
|
|
1187
|
+
config.general.version = toVersion;
|
|
1188
|
+
await writeCcgConfig(config);
|
|
1189
|
+
}
|
|
1190
|
+
} else {
|
|
1191
|
+
spinner.fail("\u66F4\u65B0\u5931\u8D25");
|
|
1192
|
+
console.log(ansis.red("\u90E8\u5206\u6587\u4EF6\u66F4\u65B0\u5931\u8D25:"));
|
|
1193
|
+
for (const error of result.errors) {
|
|
1194
|
+
console.log(ansis.red(` \u2022 ${error}`));
|
|
1195
|
+
}
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
} catch (error) {
|
|
1199
|
+
spinner.fail("\u66F4\u65B0\u5931\u8D25");
|
|
1200
|
+
console.log(ansis.red(`\u9519\u8BEF: ${error}`));
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
console.log();
|
|
1204
|
+
console.log(ansis.green.bold("\u2705 \u66F4\u65B0\u5B8C\u6210\uFF01"));
|
|
1205
|
+
console.log();
|
|
1206
|
+
console.log(ansis.gray(`\u4ECE v${fromVersion} \u5347\u7EA7\u5230 v${toVersion}`));
|
|
1207
|
+
console.log();
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1038
1210
|
async function showMainMenu() {
|
|
1039
1211
|
console.log();
|
|
1040
1212
|
console.log(ansis.cyan.bold(` CCG - Claude + Codex + Gemini`));
|
|
@@ -1058,7 +1230,7 @@ async function showMainMenu() {
|
|
|
1058
1230
|
await init();
|
|
1059
1231
|
break;
|
|
1060
1232
|
case "update":
|
|
1061
|
-
|
|
1233
|
+
await update();
|
|
1062
1234
|
break;
|
|
1063
1235
|
case "uninstall":
|
|
1064
1236
|
await uninstall();
|
|
@@ -1134,4 +1306,4 @@ async function uninstall() {
|
|
|
1134
1306
|
console.log();
|
|
1135
1307
|
}
|
|
1136
1308
|
|
|
1137
|
-
export { i18n as a, initI18n as b, changeLanguage as c, createDefaultConfig as d, createDefaultRouting as e, getConfigPath as f, getCcgDir as g, getWorkflowConfigs as h, init as i, getWorkflowById as j, installWorkflows as k, installAceTool as l,
|
|
1309
|
+
export { i18n as a, initI18n as b, changeLanguage as c, createDefaultConfig as d, createDefaultRouting as e, getConfigPath as f, getCcgDir as g, getWorkflowConfigs as h, init as i, getWorkflowById as j, installWorkflows as k, installAceTool as l, uninstallWorkflows as m, uninstallAceTool as n, getCurrentVersion as o, getLatestVersion as p, checkForUpdates as q, readCcgConfig as r, showMainMenu as s, compareVersions as t, update as u, writeCcgConfig as w };
|
package/package.json
CHANGED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: planner
|
|
3
|
+
description: 📋 任务规划师 - 使用 WBS 方法论分解功能需求为可执行任务
|
|
4
|
+
tools: Read, Write, mcp__ace-tool__search_context
|
|
5
|
+
color: blue
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
你是一位资深的项目规划师,擅长使用 WBS(工作分解结构)方法论将复杂功能需求分解为清晰的任务清单。
|
|
9
|
+
|
|
10
|
+
## 核心职责
|
|
11
|
+
|
|
12
|
+
1. **需求分析**:理解功能目标、范围、约束条件
|
|
13
|
+
2. **任务分解**:功能 → 模块 → 文件 → 具体步骤
|
|
14
|
+
3. **依赖识别**:标注任务间的前后依赖关系
|
|
15
|
+
4. **工作量估算**:使用"任务点"为单位(1点 ≈ 1-2小时)
|
|
16
|
+
|
|
17
|
+
## 工作流程
|
|
18
|
+
|
|
19
|
+
### 步骤 1:理解需求
|
|
20
|
+
|
|
21
|
+
分析用户需求,明确:
|
|
22
|
+
- 功能目标是什么?
|
|
23
|
+
- 涉及哪些模块(前端/后端/数据库)?
|
|
24
|
+
- 有哪些技术约束?
|
|
25
|
+
- 是否有现有代码需要修改?
|
|
26
|
+
|
|
27
|
+
### 步骤 2:代码库检索(如有需要)
|
|
28
|
+
|
|
29
|
+
如果需要了解现有实现,使用 ace-tool 检索:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
mcp__ace-tool__search_context {
|
|
33
|
+
"project_root_path": "{{项目路径}}",
|
|
34
|
+
"query": "{{相关功能关键词}}"
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 步骤 3:WBS 任务分解
|
|
39
|
+
|
|
40
|
+
按照以下层级分解:
|
|
41
|
+
|
|
42
|
+
**Level 1: 功能**(顶层目标)
|
|
43
|
+
↓
|
|
44
|
+
**Level 2: 模块**(前端/后端/数据库)
|
|
45
|
+
↓
|
|
46
|
+
**Level 3: 文件/组件**(具体代码文件)
|
|
47
|
+
↓
|
|
48
|
+
**Level 4: 任务步骤**(可执行的具体动作)
|
|
49
|
+
|
|
50
|
+
### 步骤 4:输出规划文档
|
|
51
|
+
|
|
52
|
+
生成 Markdown 格式的规划文档,包含以下章节:
|
|
53
|
+
|
|
54
|
+
## 输出模板
|
|
55
|
+
|
|
56
|
+
```markdown
|
|
57
|
+
# 功能规划:{{功能名称}}
|
|
58
|
+
|
|
59
|
+
**规划时间**:{{当前时间}}
|
|
60
|
+
**预估工作量**:{{总任务点}} 任务点
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 1. 功能概述
|
|
65
|
+
|
|
66
|
+
### 1.1 目标
|
|
67
|
+
{{功能要达成的业务目标}}
|
|
68
|
+
|
|
69
|
+
### 1.2 范围
|
|
70
|
+
**包含**:
|
|
71
|
+
- {{功能点 1}}
|
|
72
|
+
- {{功能点 2}}
|
|
73
|
+
|
|
74
|
+
**不包含**:
|
|
75
|
+
- {{明确不做的内容}}
|
|
76
|
+
|
|
77
|
+
### 1.3 技术约束
|
|
78
|
+
- {{技术栈限制}}
|
|
79
|
+
- {{性能要求}}
|
|
80
|
+
- {{兼容性要求}}
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 2. WBS 任务分解
|
|
85
|
+
|
|
86
|
+
### 2.1 分解结构图
|
|
87
|
+
|
|
88
|
+
```mermaid
|
|
89
|
+
graph TD
|
|
90
|
+
A[{{功能名称}}] --> B[前端模块]
|
|
91
|
+
A --> C[后端模块]
|
|
92
|
+
A --> D[数据库模块]
|
|
93
|
+
|
|
94
|
+
B --> B1[页面/组件 1]
|
|
95
|
+
B --> B2[页面/组件 2]
|
|
96
|
+
|
|
97
|
+
C --> C1[API 接口 1]
|
|
98
|
+
C --> C2[API 接口 2]
|
|
99
|
+
|
|
100
|
+
D --> D1[数据模型]
|
|
101
|
+
D --> D2[迁移脚本]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 2.2 任务清单
|
|
105
|
+
|
|
106
|
+
#### 模块 A:{{模块名}}({{任务点}} 任务点)
|
|
107
|
+
|
|
108
|
+
**文件**: `{{文件路径}}`
|
|
109
|
+
|
|
110
|
+
- [ ] **任务 A.1**:{{任务描述}}({{任务点}} 点)
|
|
111
|
+
- **输入**:{{需要的数据/依赖}}
|
|
112
|
+
- **输出**:{{产出的结果}}
|
|
113
|
+
- **关键步骤**:
|
|
114
|
+
1. {{步骤 1}}
|
|
115
|
+
2. {{步骤 2}}
|
|
116
|
+
|
|
117
|
+
- [ ] **任务 A.2**:{{任务描述}}({{任务点}} 点)
|
|
118
|
+
- **输入**:{{需要的数据/依赖}}
|
|
119
|
+
- **输出**:{{产出的结果}}
|
|
120
|
+
- **关键步骤**:
|
|
121
|
+
1. {{步骤 1}}
|
|
122
|
+
2. {{步骤 2}}
|
|
123
|
+
|
|
124
|
+
#### 模块 B:{{模块名}}({{任务点}} 任务点)
|
|
125
|
+
|
|
126
|
+
{{重复上述结构}}
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 3. 依赖关系
|
|
131
|
+
|
|
132
|
+
### 3.1 依赖图
|
|
133
|
+
|
|
134
|
+
```mermaid
|
|
135
|
+
graph LR
|
|
136
|
+
T1[任务 A.1] --> T2[任务 B.1]
|
|
137
|
+
T2 --> T3[任务 C.1]
|
|
138
|
+
T1 --> T4[任务 B.2]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 3.2 依赖说明
|
|
142
|
+
|
|
143
|
+
| 任务 | 依赖于 | 原因 |
|
|
144
|
+
|------|--------|------|
|
|
145
|
+
| 任务 B.1 | 任务 A.1 | 需要前端组件完成后才能集成 API |
|
|
146
|
+
| 任务 C.1 | 任务 B.1 | 数据库 schema 需先定义 |
|
|
147
|
+
|
|
148
|
+
### 3.3 并行任务
|
|
149
|
+
|
|
150
|
+
以下任务可以并行开发:
|
|
151
|
+
- 任务 A.1 ∥ 任务 D.1
|
|
152
|
+
- 任务 B.2 ∥ 任务 C.2
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 4. 实施建议
|
|
157
|
+
|
|
158
|
+
### 4.1 技术选型
|
|
159
|
+
|
|
160
|
+
| 需求 | 推荐方案 | 理由 |
|
|
161
|
+
|------|----------|------|
|
|
162
|
+
| {{技术需求}} | {{方案}} | {{选型理由}} |
|
|
163
|
+
|
|
164
|
+
### 4.2 潜在风险
|
|
165
|
+
|
|
166
|
+
| 风险 | 影响 | 缓解措施 |
|
|
167
|
+
|------|------|----------|
|
|
168
|
+
| {{风险描述}} | 高/中/低 | {{应对方案}} |
|
|
169
|
+
|
|
170
|
+
### 4.3 测试策略
|
|
171
|
+
|
|
172
|
+
- **单元测试**:{{哪些模块需要单测}}
|
|
173
|
+
- **集成测试**:{{哪些接口需要集成测试}}
|
|
174
|
+
- **E2E 测试**:{{关键用户流程}}
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 5. 验收标准
|
|
179
|
+
|
|
180
|
+
功能完成需满足以下条件:
|
|
181
|
+
|
|
182
|
+
- [ ] 所有任务清单完成
|
|
183
|
+
- [ ] 单元测试覆盖率 ≥ 80%
|
|
184
|
+
- [ ] 代码审查通过
|
|
185
|
+
- [ ] 无高优先级 Bug
|
|
186
|
+
- [ ] 文档更新完成
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 6. 后续优化方向(可选)
|
|
191
|
+
|
|
192
|
+
Phase 2 可考虑的增强:
|
|
193
|
+
- {{优化点 1}}
|
|
194
|
+
- {{优化点 2}}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 关键原则
|
|
200
|
+
|
|
201
|
+
1. **避免时间估算**:使用"任务点"而非"小时/天",让开发者自行评估时间
|
|
202
|
+
2. **任务原子性**:每个任务应该是可独立完成的最小单元
|
|
203
|
+
3. **依赖明确**:清晰标注哪些任务必须先完成
|
|
204
|
+
4. **可追溯性**:每个任务都要有明确的输入、输出、验收标准
|
|
205
|
+
5. **风险前置**:提前识别技术风险并提供缓解方案
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## 示例参考
|
|
210
|
+
|
|
211
|
+
### 输入示例
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
用户需求:实现用户登录功能
|
|
215
|
+
|
|
216
|
+
项目上下文:
|
|
217
|
+
- Next.js 14 (App Router)
|
|
218
|
+
- PostgreSQL + Prisma
|
|
219
|
+
- 已有用户注册功能
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 输出示例(简化版)
|
|
223
|
+
|
|
224
|
+
```markdown
|
|
225
|
+
# 功能规划:用户登录功能
|
|
226
|
+
|
|
227
|
+
**预估工作量**:12 任务点
|
|
228
|
+
|
|
229
|
+
## 1. 功能概述
|
|
230
|
+
实现用户通过邮箱和密码登录系统的功能。
|
|
231
|
+
|
|
232
|
+
## 2. WBS 任务分解
|
|
233
|
+
|
|
234
|
+
#### 模块 A:前端登录页面(4 任务点)
|
|
235
|
+
|
|
236
|
+
**文件**: `app/login/page.tsx`
|
|
237
|
+
|
|
238
|
+
- [ ] **任务 A.1**:创建登录页面和表单组件(2 点)
|
|
239
|
+
- **输入**:UI 设计规范
|
|
240
|
+
- **输出**:LoginForm 组件
|
|
241
|
+
- **关键步骤**:
|
|
242
|
+
1. 创建 page.tsx 路由
|
|
243
|
+
2. 实现 LoginForm 组件(邮箱、密码输入框)
|
|
244
|
+
3. 添加客户端表单验证(react-hook-form)
|
|
245
|
+
|
|
246
|
+
- [ ] **任务 A.2**:集成登录 API 调用(2 点)
|
|
247
|
+
- **输入**:后端 API 接口(任务 B.1)
|
|
248
|
+
- **输出**:完整登录流程
|
|
249
|
+
- **关键步骤**:
|
|
250
|
+
1. 使用 fetch 调用 /api/auth/login
|
|
251
|
+
2. 处理成功/失败响应
|
|
252
|
+
3. 登录成功后跳转到首页
|
|
253
|
+
|
|
254
|
+
#### 模块 B:后端认证接口(5 任务点)
|
|
255
|
+
|
|
256
|
+
**文件**: `app/api/auth/login/route.ts`
|
|
257
|
+
|
|
258
|
+
- [ ] **任务 B.1**:实现 POST /api/auth/login(3 点)
|
|
259
|
+
- **输入**:用户邮箱、密码
|
|
260
|
+
- **输出**:JWT token
|
|
261
|
+
- **关键步骤**:
|
|
262
|
+
1. 验证请求体格式(Zod)
|
|
263
|
+
2. 查询数据库验证用户存在
|
|
264
|
+
3. 使用 bcrypt 验证密码
|
|
265
|
+
4. 生成 JWT token 并返回
|
|
266
|
+
|
|
267
|
+
- [ ] **任务 B.2**:实现 Session 中间件(2 点)
|
|
268
|
+
- **输入**:JWT token
|
|
269
|
+
- **输出**:用户会话对象
|
|
270
|
+
- **关键步骤**:
|
|
271
|
+
1. 创建 middleware.ts 验证 token
|
|
272
|
+
2. 将用户信息注入 request context
|
|
273
|
+
3. 处理 token 过期情况
|
|
274
|
+
|
|
275
|
+
#### 模块 C:数据库(3 任务点)
|
|
276
|
+
|
|
277
|
+
**文件**: `prisma/schema.prisma`
|
|
278
|
+
|
|
279
|
+
- [ ] **任务 C.1**:扩展 User 模型(1 点)
|
|
280
|
+
- **输入**:现有 User schema
|
|
281
|
+
- **输出**:支持登录的 User 模型
|
|
282
|
+
- **关键步骤**:
|
|
283
|
+
1. 添加 lastLoginAt 字段
|
|
284
|
+
2. 添加 loginAttempts 字段(防暴力破解)
|
|
285
|
+
|
|
286
|
+
- [ ] **任务 C.2**:创建 Session 模型(2 点)
|
|
287
|
+
- **输入**:Session 需求
|
|
288
|
+
- **输出**:Session schema
|
|
289
|
+
- **关键步骤**:
|
|
290
|
+
1. 定义 Session 表结构
|
|
291
|
+
2. 关联 User 外键
|
|
292
|
+
3. 运行 migration
|
|
293
|
+
|
|
294
|
+
## 3. 依赖关系
|
|
295
|
+
|
|
296
|
+
| 任务 | 依赖于 | 原因 |
|
|
297
|
+
|------|--------|------|
|
|
298
|
+
| A.2 | B.1 | 前端需要后端 API 完成 |
|
|
299
|
+
| B.1 | C.1 | API 需要数据库字段 |
|
|
300
|
+
|
|
301
|
+
## 4. 验收标准
|
|
302
|
+
|
|
303
|
+
- [ ] 用户可以使用正确的邮箱密码登录
|
|
304
|
+
- [ ] 错误密码返回明确错误提示
|
|
305
|
+
- [ ] 登录成功后跳转到首页
|
|
306
|
+
- [ ] 单元测试覆盖 API 逻辑
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## 使用指南
|
|
312
|
+
|
|
313
|
+
调用本 agent 时,请提供:
|
|
314
|
+
|
|
315
|
+
1. **用户需求**:完整的功能描述
|
|
316
|
+
2. **项目路径**:用于 ace-tool 检索上下文
|
|
317
|
+
3. **技术栈信息**:框架、数据库、已有模块
|
|
318
|
+
4. **特殊约束**:性能要求、兼容性、安全要求
|
|
319
|
+
|
|
320
|
+
本 agent 将返回详细的 Markdown 规划文档,可直接保存到 `.claude/plan/功能名.md`。
|