claude-coder 1.9.0 → 1.9.2

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.
Files changed (74) hide show
  1. package/README.md +214 -214
  2. package/bin/cli.js +155 -155
  3. package/package.json +55 -55
  4. package/recipes/_shared/roles/developer.md +11 -11
  5. package/recipes/_shared/roles/product.md +12 -12
  6. package/recipes/_shared/roles/tester.md +12 -12
  7. package/recipes/_shared/test/report-format.md +86 -86
  8. package/recipes/backend/base.md +27 -27
  9. package/recipes/backend/components/auth.md +18 -18
  10. package/recipes/backend/components/crud-api.md +18 -18
  11. package/recipes/backend/components/file-service.md +15 -15
  12. package/recipes/backend/manifest.json +20 -20
  13. package/recipes/backend/test/api-test.md +25 -25
  14. package/recipes/console/base.md +37 -37
  15. package/recipes/console/components/modal-form.md +20 -20
  16. package/recipes/console/components/pagination.md +17 -17
  17. package/recipes/console/components/search.md +17 -17
  18. package/recipes/console/components/table-list.md +18 -18
  19. package/recipes/console/components/tabs.md +14 -14
  20. package/recipes/console/components/tree.md +15 -15
  21. package/recipes/console/components/upload.md +15 -15
  22. package/recipes/console/manifest.json +24 -24
  23. package/recipes/console/test/crud-e2e.md +47 -47
  24. package/recipes/h5/base.md +26 -26
  25. package/recipes/h5/components/animation.md +11 -11
  26. package/recipes/h5/components/countdown.md +11 -11
  27. package/recipes/h5/components/share.md +11 -11
  28. package/recipes/h5/components/swiper.md +11 -11
  29. package/recipes/h5/manifest.json +21 -21
  30. package/recipes/h5/test/h5-e2e.md +20 -20
  31. package/src/commands/auth.js +420 -362
  32. package/src/commands/setup-modules/helpers.js +100 -100
  33. package/src/commands/setup-modules/index.js +25 -25
  34. package/src/commands/setup-modules/mcp.js +115 -115
  35. package/src/commands/setup-modules/provider.js +260 -260
  36. package/src/commands/setup-modules/safety.js +47 -47
  37. package/src/commands/setup-modules/simplify.js +52 -52
  38. package/src/commands/setup.js +172 -172
  39. package/src/common/assets.js +245 -245
  40. package/src/common/config.js +125 -125
  41. package/src/common/constants.js +55 -55
  42. package/src/common/indicator.js +260 -260
  43. package/src/common/interaction.js +170 -170
  44. package/src/common/logging.js +77 -77
  45. package/src/common/sdk.js +50 -50
  46. package/src/common/tasks.js +88 -88
  47. package/src/common/utils.js +213 -213
  48. package/src/core/coding.js +33 -33
  49. package/src/core/go.js +264 -264
  50. package/src/core/hooks.js +500 -500
  51. package/src/core/init.js +166 -165
  52. package/src/core/plan.js +188 -187
  53. package/src/core/prompts.js +247 -247
  54. package/src/core/repair.js +36 -36
  55. package/src/core/runner.js +471 -458
  56. package/src/core/scan.js +93 -93
  57. package/src/core/session.js +280 -271
  58. package/src/core/simplify.js +74 -74
  59. package/src/core/state.js +105 -105
  60. package/src/index.js +76 -76
  61. package/templates/bash-process.md +12 -12
  62. package/templates/codingSystem.md +65 -65
  63. package/templates/codingUser.md +17 -17
  64. package/templates/coreProtocol.md +29 -29
  65. package/templates/goSystem.md +130 -130
  66. package/templates/guidance.json +72 -72
  67. package/templates/planSystem.md +78 -78
  68. package/templates/planUser.md +8 -8
  69. package/templates/requirements.example.md +57 -57
  70. package/templates/scanSystem.md +120 -120
  71. package/templates/scanUser.md +10 -10
  72. package/templates/test_rule.md +194 -194
  73. package/templates/web-testing.md +17 -17
  74. package/types/index.d.ts +217 -217
@@ -1,74 +1,74 @@
1
- 'use strict';
2
-
3
- const { log } = require('../common/config');
4
- const { assets } = require('../common/assets');
5
- const { Session } = require('./session');
6
- const { execSync } = require('child_process');
7
-
8
- const AUTO_COMMIT_MSG = 'style: auto simplify';
9
-
10
- function getSmartDiffRange(projectRoot, fallbackN) {
11
- try {
12
- const hash = execSync(
13
- `git log --grep='${AUTO_COMMIT_MSG}' -1 --format='%H'`,
14
- { cwd: projectRoot, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] },
15
- ).trim();
16
- if (hash) return { range: `${hash}..HEAD`, label: `自上次 auto simplify 以来` };
17
- } catch { /* ignore */ }
18
- return { range: `HEAD~${fallbackN}..HEAD`, label: `最近 ${fallbackN} 个 commit` };
19
- }
20
-
21
- function commitIfDirty(projectRoot) {
22
- try {
23
- execSync('git diff --quiet HEAD', { cwd: projectRoot, stdio: 'pipe' });
24
- } catch {
25
- execSync(`git add -A && git commit -m "${AUTO_COMMIT_MSG}"`, { cwd: projectRoot, stdio: 'pipe' });
26
- log('ok', `代码优化已提交: ${AUTO_COMMIT_MSG}`);
27
- }
28
- }
29
-
30
- async function executeSimplify(config, focus = null, opts = {}) {
31
- const n = opts.n || 3;
32
- const projectRoot = assets.projectRoot;
33
-
34
- const { range, label } = getSmartDiffRange(projectRoot, n);
35
-
36
- let diff = '';
37
- try {
38
- diff = execSync(`git diff ${range}`, { cwd: projectRoot, encoding: 'utf8', maxBuffer: 50 * 1024 * 1024 });
39
- } catch (err) {
40
- log('warn', `无法获取 diff (${label}): ${err.message}`);
41
- }
42
-
43
- if (!diff.trim()) {
44
- log('info', `无变更需要审查 (${label})`);
45
- return { success: true };
46
- }
47
-
48
- const focusLine = focus ? `\n审查聚焦方向:${focus}` : '';
49
- const prompt = `/simplify\n\n审查范围:${label}${focusLine}\n\n${diff.slice(0, 50000)}`;
50
- const dateStr = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 12);
51
-
52
- const result = await Session.run('simplify', config, {
53
- logFileName: `simplify_${dateStr}.log`,
54
- label: 'simplify',
55
-
56
- async execute(session) {
57
- log('info', `正在审查代码变更 (${label})...`);
58
-
59
- const queryOpts = session.buildQueryOptions(opts);
60
- queryOpts.disallowedTools = ['askUserQuestion'];
61
-
62
- await session.runQuery(prompt, queryOpts);
63
- log('ok', '代码审查完成');
64
-
65
- return {};
66
- },
67
- });
68
-
69
- commitIfDirty(projectRoot);
70
-
71
- return result;
72
- }
73
-
74
- module.exports = { executeSimplify };
1
+ 'use strict';
2
+
3
+ const { log } = require('../common/config');
4
+ const { assets } = require('../common/assets');
5
+ const { Session } = require('./session');
6
+ const { execSync } = require('child_process');
7
+
8
+ const AUTO_COMMIT_MSG = 'style: auto simplify';
9
+
10
+ function getSmartDiffRange(projectRoot, fallbackN) {
11
+ try {
12
+ const hash = execSync(
13
+ `git log --grep='${AUTO_COMMIT_MSG}' -1 --format='%H'`,
14
+ { cwd: projectRoot, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] },
15
+ ).trim();
16
+ if (hash) return { range: `${hash}..HEAD`, label: `自上次 auto simplify 以来` };
17
+ } catch { /* ignore */ }
18
+ return { range: `HEAD~${fallbackN}..HEAD`, label: `最近 ${fallbackN} 个 commit` };
19
+ }
20
+
21
+ function commitIfDirty(projectRoot) {
22
+ try {
23
+ execSync('git diff --quiet HEAD', { cwd: projectRoot, stdio: 'pipe' });
24
+ } catch {
25
+ execSync(`git add -A && git commit -m "${AUTO_COMMIT_MSG}"`, { cwd: projectRoot, stdio: 'pipe' });
26
+ log('ok', `代码优化已提交: ${AUTO_COMMIT_MSG}`);
27
+ }
28
+ }
29
+
30
+ async function executeSimplify(config, focus = null, opts = {}) {
31
+ const n = opts.n || 3;
32
+ const projectRoot = assets.projectRoot;
33
+
34
+ const { range, label } = getSmartDiffRange(projectRoot, n);
35
+
36
+ let diff = '';
37
+ try {
38
+ diff = execSync(`git diff ${range}`, { cwd: projectRoot, encoding: 'utf8', maxBuffer: 50 * 1024 * 1024 });
39
+ } catch (err) {
40
+ log('warn', `无法获取 diff (${label}): ${err.message}`);
41
+ }
42
+
43
+ if (!diff.trim()) {
44
+ log('info', `无变更需要审查 (${label})`);
45
+ return { success: true };
46
+ }
47
+
48
+ const focusLine = focus ? `\n审查聚焦方向:${focus}` : '';
49
+ const prompt = `/simplify\n\n审查范围:${label}${focusLine}\n\n${diff.slice(0, 50000)}`;
50
+ const dateStr = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 12);
51
+
52
+ const result = await Session.run('simplify', config, {
53
+ logFileName: `simplify_${dateStr}.log`,
54
+ label: 'simplify',
55
+
56
+ async execute(session) {
57
+ log('info', `正在审查代码变更 (${label})...`);
58
+
59
+ const queryOpts = session.buildQueryOptions(opts);
60
+ queryOpts.disallowedTools = ['askUserQuestion'];
61
+
62
+ await session.runQuery(prompt, queryOpts);
63
+ log('ok', '代码审查完成');
64
+
65
+ return {};
66
+ },
67
+ });
68
+
69
+ commitIfDirty(projectRoot);
70
+
71
+ return result;
72
+ }
73
+
74
+ module.exports = { executeSimplify };
package/src/core/state.js CHANGED
@@ -1,105 +1,105 @@
1
- 'use strict';
2
-
3
- const { assets } = require('../common/assets');
4
- const { getFeatures } = require('../common/tasks');
5
- const { TASK_STATUSES } = require('../common/constants');
6
-
7
- // ─── Harness State (harness_state.json) ───────────────────
8
-
9
- const DEFAULT_STATE = Object.freeze({
10
- version: 1,
11
- next_task_id: 1,
12
- next_priority: 1,
13
- session_count: 0,
14
- last_simplify_session: 0,
15
- current_task_id: null,
16
- });
17
-
18
- function loadState() {
19
- return assets.readJson('harnessState', { ...DEFAULT_STATE });
20
- }
21
-
22
- function saveState(data) {
23
- assets.writeJson('harnessState', data);
24
- }
25
-
26
- function extractIdNum(id) {
27
- const m = String(id).match(/(\d+)$/);
28
- return m ? parseInt(m[1], 10) : 0;
29
- }
30
-
31
- function syncAfterPlan() {
32
- const state = loadState();
33
- const tasks = assets.readJson('tasks', null);
34
- if (!tasks || !tasks.features) return state;
35
-
36
- const features = tasks.features;
37
- state.next_task_id = features.reduce((max, f) => Math.max(max, extractIdNum(f.id)), 0) + 1;
38
- state.next_priority = features.reduce((max, f) => Math.max(max, f.priority || 0), 0) + 1;
39
- saveState(state);
40
- return state;
41
- }
42
-
43
- // ─── Task Scheduling ──────────────────────────────────────
44
-
45
- function selectNextTask(taskData) {
46
- const features = getFeatures(taskData);
47
-
48
- const failed = features.filter(f => f.status === 'failed')
49
- .sort((a, b) => (a.priority || 999) - (b.priority || 999));
50
- if (failed.length > 0) return failed[0];
51
-
52
- const pending = features.filter(f => f.status === 'pending')
53
- .filter(f => {
54
- const deps = f.depends_on || [];
55
- return deps.every(depId => {
56
- const dep = features.find(x => x.id === depId);
57
- return dep && dep.status === 'done';
58
- });
59
- })
60
- .sort((a, b) => (a.priority || 999) - (b.priority || 999));
61
- if (pending.length > 0) return pending[0];
62
-
63
- const inProgress = features.filter(f => f.status === 'in_progress')
64
- .sort((a, b) => (a.priority || 999) - (b.priority || 999));
65
- return inProgress[0] || null;
66
- }
67
-
68
- function isAllDone(taskData) {
69
- const features = getFeatures(taskData);
70
- return features.length > 0 && features.every(f => f.status === 'done');
71
- }
72
-
73
- // ─── Progress & Counters ──────────────────────────────────
74
-
75
- function appendProgress(entry) {
76
- let progress = assets.readJson('progress', { sessions: [] });
77
- if (!Array.isArray(progress.sessions)) progress.sessions = [];
78
- progress.sessions.push(entry);
79
- assets.writeJson('progress', progress);
80
- }
81
-
82
- function incrementSession() {
83
- const state = loadState();
84
- state.session_count++;
85
- saveState(state);
86
- }
87
-
88
- function markSimplifyDone() {
89
- const state = loadState();
90
- state.last_simplify_session = state.session_count;
91
- saveState(state);
92
- }
93
-
94
- module.exports = {
95
- DEFAULT_STATE,
96
- loadState,
97
- saveState,
98
- syncAfterPlan,
99
- selectNextTask,
100
- isAllDone,
101
- appendProgress,
102
- incrementSession,
103
- markSimplifyDone,
104
- TASK_STATUSES,
105
- };
1
+ 'use strict';
2
+
3
+ const { assets } = require('../common/assets');
4
+ const { getFeatures } = require('../common/tasks');
5
+ const { TASK_STATUSES } = require('../common/constants');
6
+
7
+ // ─── Harness State (harness_state.json) ───────────────────
8
+
9
+ const DEFAULT_STATE = Object.freeze({
10
+ version: 1,
11
+ next_task_id: 1,
12
+ next_priority: 1,
13
+ session_count: 0,
14
+ last_simplify_session: 0,
15
+ current_task_id: null,
16
+ });
17
+
18
+ function loadState() {
19
+ return assets.readJson('harnessState', { ...DEFAULT_STATE });
20
+ }
21
+
22
+ function saveState(data) {
23
+ assets.writeJson('harnessState', data);
24
+ }
25
+
26
+ function extractIdNum(id) {
27
+ const m = String(id).match(/(\d+)$/);
28
+ return m ? parseInt(m[1], 10) : 0;
29
+ }
30
+
31
+ function syncAfterPlan() {
32
+ const state = loadState();
33
+ const tasks = assets.readJson('tasks', null);
34
+ if (!tasks || !tasks.features) return state;
35
+
36
+ const features = tasks.features;
37
+ state.next_task_id = features.reduce((max, f) => Math.max(max, extractIdNum(f.id)), 0) + 1;
38
+ state.next_priority = features.reduce((max, f) => Math.max(max, f.priority || 0), 0) + 1;
39
+ saveState(state);
40
+ return state;
41
+ }
42
+
43
+ // ─── Task Scheduling ──────────────────────────────────────
44
+
45
+ function selectNextTask(taskData) {
46
+ const features = getFeatures(taskData);
47
+
48
+ const failed = features.filter(f => f.status === 'failed')
49
+ .sort((a, b) => (a.priority || 999) - (b.priority || 999));
50
+ if (failed.length > 0) return failed[0];
51
+
52
+ const pending = features.filter(f => f.status === 'pending')
53
+ .filter(f => {
54
+ const deps = f.depends_on || [];
55
+ return deps.every(depId => {
56
+ const dep = features.find(x => x.id === depId);
57
+ return dep && dep.status === 'done';
58
+ });
59
+ })
60
+ .sort((a, b) => (a.priority || 999) - (b.priority || 999));
61
+ if (pending.length > 0) return pending[0];
62
+
63
+ const inProgress = features.filter(f => f.status === 'in_progress')
64
+ .sort((a, b) => (a.priority || 999) - (b.priority || 999));
65
+ return inProgress[0] || null;
66
+ }
67
+
68
+ function isAllDone(taskData) {
69
+ const features = getFeatures(taskData);
70
+ return features.length > 0 && features.every(f => f.status === 'done');
71
+ }
72
+
73
+ // ─── Progress & Counters ──────────────────────────────────
74
+
75
+ function appendProgress(entry) {
76
+ let progress = assets.readJson('progress', { sessions: [] });
77
+ if (!Array.isArray(progress.sessions)) progress.sessions = [];
78
+ progress.sessions.push(entry);
79
+ assets.writeJson('progress', progress);
80
+ }
81
+
82
+ function incrementSession() {
83
+ const state = loadState();
84
+ state.session_count++;
85
+ saveState(state);
86
+ }
87
+
88
+ function markSimplifyDone() {
89
+ const state = loadState();
90
+ state.last_simplify_session = state.session_count;
91
+ saveState(state);
92
+ }
93
+
94
+ module.exports = {
95
+ DEFAULT_STATE,
96
+ loadState,
97
+ saveState,
98
+ syncAfterPlan,
99
+ selectNextTask,
100
+ isAllDone,
101
+ appendProgress,
102
+ incrementSession,
103
+ markSimplifyDone,
104
+ TASK_STATUSES,
105
+ };
package/src/index.js CHANGED
@@ -1,76 +1,76 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const { loadConfig, log } = require('./common/config');
6
- const { assets } = require('./common/assets');
7
- const { Session } = require('./core/session');
8
-
9
- /** @typedef {{ max?: number, pause?: number, dryRun?: boolean, readFile?: string, model?: string, n?: number, planOnly?: boolean, interactive?: boolean, reset?: boolean, deployTemplates?: boolean, projectRoot?: string, reqFile?: string }} MainOpts */
10
-
11
- function checkReady(command) {
12
- if (['init', 'scan'].includes(command)) return;
13
-
14
- if (!assets.exists('profile')) {
15
- throw new Error('文件缺失: project_profile.json,请运行 claude-coder init 初始化项目');
16
- }
17
- }
18
-
19
- /**
20
- * 应用入口:初始化资产、加载配置、分发命令
21
- * @param {string} command - 命令名称(init | scan | plan | run | go | simplify)
22
- * @param {string} input - 位置参数(需求文本等)
23
- * @param {MainOpts} [opts={}] - CLI 选项
24
- * @returns {Promise<Object|void>}
25
- */
26
- async function main(command, input, opts = {}) {
27
- assets.init(opts.projectRoot || process.cwd());
28
- assets.ensureDirs();
29
- const config = loadConfig();
30
-
31
- if (!opts.model) opts.model = config.defaultOpus || config.model;
32
-
33
- if (opts.readFile) {
34
- const reqPath = path.resolve(assets.projectRoot, opts.readFile);
35
- if (!fs.existsSync(reqPath)) {
36
- throw new Error(`文件不存在: ${reqPath}`);
37
- }
38
- opts.reqFile = reqPath;
39
- }
40
-
41
- checkReady(command);
42
-
43
- const displayModel = opts.model || '(default)';
44
- log('ok', `模型: ${config.provider || 'claude'} (${displayModel}), 命令: ${command}`);
45
-
46
- switch (command) {
47
- case 'init': {
48
- const { executeInit } = require('./core/init');
49
- return executeInit(config, opts);
50
- }
51
- case 'scan': {
52
- const { executeScan } = require('./core/scan');
53
- return executeScan(config, opts);
54
- }
55
- case 'simplify': {
56
- const { executeSimplify } = require('./core/simplify');
57
- return executeSimplify(config, input, opts);
58
- }
59
- case 'plan': {
60
- const { executePlan } = require('./core/plan');
61
- return executePlan(config, input, opts);
62
- }
63
- case 'run': {
64
- const { executeRun } = require('./core/runner');
65
- return executeRun(config, opts);
66
- }
67
- case 'go': {
68
- const { executeGo } = require('./core/go');
69
- return executeGo(config, input, opts);
70
- }
71
- default:
72
- throw new Error(`未知命令: ${command}`);
73
- }
74
- }
75
-
76
- module.exports = { main, Session };
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { loadConfig, log } = require('./common/config');
6
+ const { assets } = require('./common/assets');
7
+ const { Session } = require('./core/session');
8
+
9
+ /** @typedef {{ max?: number, pause?: number, dryRun?: boolean, readFile?: string, model?: string, n?: number, planOnly?: boolean, interactive?: boolean, reset?: boolean, deployTemplates?: boolean, projectRoot?: string, reqFile?: string }} MainOpts */
10
+
11
+ function checkReady(command) {
12
+ if (['init', 'scan'].includes(command)) return;
13
+
14
+ if (!assets.exists('profile')) {
15
+ throw new Error('文件缺失: project_profile.json,请运行 claude-coder init 初始化项目');
16
+ }
17
+ }
18
+
19
+ /**
20
+ * 应用入口:初始化资产、加载配置、分发命令
21
+ * @param {string} command - 命令名称(init | scan | plan | run | go | simplify)
22
+ * @param {string} input - 位置参数(需求文本等)
23
+ * @param {MainOpts} [opts={}] - CLI 选项
24
+ * @returns {Promise<Object|void>}
25
+ */
26
+ async function main(command, input, opts = {}) {
27
+ assets.init(opts.projectRoot || process.cwd());
28
+ assets.ensureDirs();
29
+ const config = loadConfig();
30
+
31
+ if (!opts.model) opts.model = config.defaultOpus || config.model;
32
+
33
+ if (opts.readFile) {
34
+ const reqPath = path.resolve(assets.projectRoot, opts.readFile);
35
+ if (!fs.existsSync(reqPath)) {
36
+ throw new Error(`文件不存在: ${reqPath}`);
37
+ }
38
+ opts.reqFile = reqPath;
39
+ }
40
+
41
+ checkReady(command);
42
+
43
+ const displayModel = opts.model || '(default)';
44
+ log('ok', `模型: ${config.provider || 'claude'} (${displayModel}), 命令: ${command}`);
45
+
46
+ switch (command) {
47
+ case 'init': {
48
+ const { executeInit } = require('./core/init');
49
+ return executeInit(config, opts);
50
+ }
51
+ case 'scan': {
52
+ const { executeScan } = require('./core/scan');
53
+ return executeScan(config, opts);
54
+ }
55
+ case 'simplify': {
56
+ const { executeSimplify } = require('./core/simplify');
57
+ return executeSimplify(config, input, opts);
58
+ }
59
+ case 'plan': {
60
+ const { executePlan } = require('./core/plan');
61
+ return executePlan(config, input, opts);
62
+ }
63
+ case 'run': {
64
+ const { executeRun } = require('./core/runner');
65
+ return executeRun(config, opts);
66
+ }
67
+ case 'go': {
68
+ const { executeGo } = require('./core/go');
69
+ return executeGo(config, input, opts);
70
+ }
71
+ default:
72
+ throw new Error(`未知命令: ${command}`);
73
+ }
74
+ }
75
+
76
+ module.exports = { main, Session };
@@ -1,12 +1,12 @@
1
- 【进程管理规则】
2
- - 停止服务前检查 project_profile.json 的 services 配置
3
- - 使用配置中的端口进行精确 kill
4
- - 单次模式:收尾时停止所有后台服务
5
- - 连续模式:保持服务运行供下个 session 使用
6
-
7
- 【跨平台命令】
8
- - Windows: `netstat -ano | findstr :PORT` → `taskkill /F /T /PID <PID>`(/T 杀进程树,必须带)
9
- - Linux/Mac: `lsof -ti :PORT | xargs kill -9`
10
- - 跨平台备选: `npx kill-port PORT`
11
- - PowerShell: `Get-NetTCPConnection -LocalPort PORT -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }`
12
- - Python venv: uvicorn --reload 产生父子进程树,必须用 /T 或杀父进程
1
+ 【进程管理规则】
2
+ - 停止服务前检查 project_profile.json 的 services 配置
3
+ - 使用配置中的端口进行精确 kill
4
+ - 单次模式:收尾时停止所有后台服务
5
+ - 连续模式:保持服务运行供下个 session 使用
6
+
7
+ 【跨平台命令】
8
+ - Windows: `netstat -ano | findstr :PORT` → `taskkill /F /T /PID <PID>`(/T 杀进程树,必须带)
9
+ - Linux/Mac: `lsof -ti :PORT | xargs kill -9`
10
+ - 跨平台备选: `npx kill-port PORT`
11
+ - PowerShell: `Get-NetTCPConnection -LocalPort PORT -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }`
12
+ - Python venv: uvicorn --reload 产生父子进程树,必须用 /T 或杀父进程
@@ -1,65 +1,65 @@
1
- <!--
2
- Coding Session System Prompt.
3
- Prepended after coreProtocol.md by buildSystemPrompt('coding').
4
- .claude/CLAUDE.md is auto-loaded by the SDK (settingSources: ['project']).
5
- -->
6
-
7
- # 编码会话协议
8
-
9
- 你是增量编码 Agent。任务上下文已由 harness 注入 prompt,无需手动查找。
10
-
11
- ## 铁律
12
-
13
- 1. tasks.json 只改 `status` 字段,不得删改任务描述
14
- 2. 状态必须按状态机迁移,不得跳步
15
- 3. 未通过端到端测试不得标记 `done`
16
- 4. 发现 Bug 先修后建
17
- 5. 文档按需更新:对外行为变化才改 README;新模块/API 才更新架构文档
18
- 6. `.claude/CLAUDE.md` 只读
19
- 7. 遇到疑问或不确定时,自行判断最佳方案并执行,不要尝试提问
20
-
21
- ## 状态机
22
-
23
- - `pending` → `in_progress`(开始编码)
24
- - `in_progress` → `testing`(编码完成)
25
- - `testing` → `done`(测试通过)| `failed`(测试失败)
26
- - `failed` → `in_progress`(重试修复)
27
-
28
- ## 文件权限
29
-
30
- - `tasks.json` — 功能任务列表,带状态跟踪,只能修改 status 字段
31
- - `test.env` — 测试凭证(API Key、测试账号等)可追加写入
32
- - `project_profile.json` — 项目元数据(技术栈、服务等)只读(需要详情时可读取)
33
-
34
- ## 工作流程
35
-
36
- **Step 1 — 实现**
37
- 1. 确认 prompt 中注入的任务,status → `in_progress`
38
- 2. 先读相关文档,再读相关源文件,列改动清单,一次性完成编码
39
- 3. 信息不完整时,读 `.claude-coder/tasks.json` 或 `project_profile.json` 补充
40
-
41
- **Step 2 — 验证**
42
- 1. status → `testing`
43
- 2. 按 category 选最轻量方式:backend 用 curl,frontend 用 Playwright MCP,infra 用语法检查
44
- 3. 按任务 steps 最后一步验证。通过 → `done`;失败 → `failed`(notes 记原因)
45
-
46
- **Step 3 — 收尾(必须执行)**
47
- 1. 根据 prompt 提示管理后台服务
48
- 2. 写 session_result.json:notes 只写未解决问题
49
- 3. `git add -A && git commit -m "feat(task-id): 描述"`
50
-
51
- ## 工具规范
52
-
53
- - 搜索/读取:Glob/Grep/Read/LS 替代 bash find/grep/cat/ls
54
- - 编辑:同文件多处改用 MultiEdit,多文件合并一次批量调用
55
- - 探索:复杂搜索用 Task 启动子 Agent
56
- - 进程:停服务前 netstat/lsof 定位 PID 再 kill,重启前确认端口释放,失败最多重试 2 次后换方法
57
-
58
- ## 禁止清单
59
-
60
- - 跳步(`pending` → `done`)、回退到 `pending`、未测试直接 `done`
61
- - 后端任务启动浏览器测试
62
- - 创建独立测试文件
63
- - 为测试重启开发服务器
64
- - 编码-测试反复跳转(先完成全部编码再统一测试)
65
- - bash find/grep/cat/ls(用对应工具替代)
1
+ <!--
2
+ Coding Session System Prompt.
3
+ Prepended after coreProtocol.md by buildSystemPrompt('coding').
4
+ .claude/CLAUDE.md is auto-loaded by the SDK (settingSources: ['project']).
5
+ -->
6
+
7
+ # 编码会话协议
8
+
9
+ 你是增量编码 Agent。任务上下文已由 harness 注入 prompt,无需手动查找。
10
+
11
+ ## 铁律
12
+
13
+ 1. tasks.json 只改 `status` 字段,不得删改任务描述
14
+ 2. 状态必须按状态机迁移,不得跳步
15
+ 3. 未通过端到端测试不得标记 `done`
16
+ 4. 发现 Bug 先修后建
17
+ 5. 文档按需更新:对外行为变化才改 README;新模块/API 才更新架构文档
18
+ 6. `.claude/CLAUDE.md` 只读
19
+ 7. 遇到疑问或不确定时,自行判断最佳方案并执行,不要尝试提问
20
+
21
+ ## 状态机
22
+
23
+ - `pending` → `in_progress`(开始编码)
24
+ - `in_progress` → `testing`(编码完成)
25
+ - `testing` → `done`(测试通过)| `failed`(测试失败)
26
+ - `failed` → `in_progress`(重试修复)
27
+
28
+ ## 文件权限
29
+
30
+ - `tasks.json` — 功能任务列表,带状态跟踪,只能修改 status 字段
31
+ - `test.env` — 测试凭证(API Key、测试账号等)可追加写入
32
+ - `project_profile.json` — 项目元数据(技术栈、服务等)只读(需要详情时可读取)
33
+
34
+ ## 工作流程
35
+
36
+ **Step 1 — 实现**
37
+ 1. 确认 prompt 中注入的任务,status → `in_progress`
38
+ 2. 先读相关文档,再读相关源文件,列改动清单,一次性完成编码
39
+ 3. 信息不完整时,读 `.claude-coder/tasks.json` 或 `project_profile.json` 补充
40
+
41
+ **Step 2 — 验证**
42
+ 1. status → `testing`
43
+ 2. 按 category 选最轻量方式:backend 用 curl,frontend 用 Playwright MCP,infra 用语法检查
44
+ 3. 按任务 steps 最后一步验证。通过 → `done`;失败 → `failed`(notes 记原因)
45
+
46
+ **Step 3 — 收尾(必须执行)**
47
+ 1. 根据 prompt 提示管理后台服务
48
+ 2. 写 session_result.json:notes 只写未解决问题
49
+ 3. `git add -A && git commit -m "feat(task-id): 描述"`
50
+
51
+ ## 工具规范
52
+
53
+ - 搜索/读取:Glob/Grep/Read/LS 替代 bash find/grep/cat/ls
54
+ - 编辑:同文件多处改用 MultiEdit,多文件合并一次批量调用
55
+ - 探索:复杂搜索用 Task 启动子 Agent
56
+ - 进程:停服务前 netstat/lsof 定位 PID 再 kill,重启前确认端口释放,失败最多重试 2 次后换方法
57
+
58
+ ## 禁止清单
59
+
60
+ - 跳步(`pending` → `done`)、回退到 `pending`、未测试直接 `done`
61
+ - 后端任务启动浏览器测试
62
+ - 创建独立测试文件
63
+ - 为测试重启开发服务器
64
+ - 编码-测试反复跳转(先完成全部编码再统一测试)
65
+ - bash find/grep/cat/ls(用对应工具替代)