clawt 3.8.5 → 3.8.7

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/index.js CHANGED
@@ -796,7 +796,7 @@ var PROJECT_DEFAULT_CONFIG = deriveDefaultConfig2(PROJECT_CONFIG_DEFINITIONS);
796
796
  var PROJECT_CONFIG_DESCRIPTIONS = deriveConfigDescriptions2(PROJECT_CONFIG_DEFINITIONS);
797
797
 
798
798
  // src/constants/git.ts
799
- var AUTO_SAVE_COMMIT_MESSAGE = "chore: auto-save before sync";
799
+ var AUTO_SAVE_COMMIT_MESSAGE_PREFIX = "clawt: auto-save before merging";
800
800
  var EXEC_MAX_BUFFER = 200 * 1024 * 1024;
801
801
 
802
802
  // src/constants/logger.ts
@@ -1290,6 +1290,9 @@ function gitAddFiles(files, cwd) {
1290
1290
  function gitMergeContinue(cwd) {
1291
1291
  execCommand("GIT_EDITOR=true git merge --continue", { cwd });
1292
1292
  }
1293
+ function buildAutoSaveCommitMessage(mainBranch, branch) {
1294
+ return `${AUTO_SAVE_COMMIT_MESSAGE_PREFIX} ${mainBranch} into ${branch}`;
1295
+ }
1293
1296
 
1294
1297
  // src/utils/git-branch.ts
1295
1298
  function checkBranchExists(branchName, cwd) {
@@ -3999,14 +4002,7 @@ var InteractivePanel = class {
3999
4002
  this.clearTimers();
4000
4003
  this.keyboardController.stop();
4001
4004
  this.restoreTerminal();
4002
- if (this.resizeHandler) {
4003
- process.stdout.removeListener("resize", this.resizeHandler);
4004
- this.resizeHandler = null;
4005
- }
4006
- if (this.exitHandler) {
4007
- process.removeListener("exit", this.exitHandler);
4008
- this.exitHandler = null;
4009
- }
4005
+ this.removeTerminalListeners();
4010
4006
  if (this.resolveStart) {
4011
4007
  this.resolveStart();
4012
4008
  this.resolveStart = null;
@@ -4016,6 +4012,7 @@ var InteractivePanel = class {
4016
4012
  * 初始化终端:进入备选屏幕、隐藏光标、禁用行换行
4017
4013
  */
4018
4014
  initTerminal() {
4015
+ this.removeTerminalListeners();
4019
4016
  process.stdout.write(ALT_SCREEN_ENTER);
4020
4017
  process.stdout.write(CURSOR_HIDE);
4021
4018
  process.stdout.write(LINE_WRAP_DISABLE);
@@ -4026,13 +4023,22 @@ var InteractivePanel = class {
4026
4023
  }
4027
4024
  };
4028
4025
  process.stdout.on("resize", this.resizeHandler);
4029
- this.exitHandler = () => {
4030
- process.stdout.write(LINE_WRAP_ENABLE);
4031
- process.stdout.write(CURSOR_SHOW);
4032
- process.stdout.write(ALT_SCREEN_LEAVE);
4033
- };
4026
+ this.exitHandler = () => this.restoreTerminal();
4034
4027
  process.on("exit", this.exitHandler);
4035
4028
  }
4029
+ /**
4030
+ * 移除终端事件监听器(resize 和 exit)
4031
+ */
4032
+ removeTerminalListeners() {
4033
+ if (this.resizeHandler) {
4034
+ process.stdout.removeListener("resize", this.resizeHandler);
4035
+ this.resizeHandler = null;
4036
+ }
4037
+ if (this.exitHandler) {
4038
+ process.removeListener("exit", this.exitHandler);
4039
+ this.exitHandler = null;
4040
+ }
4041
+ }
4036
4042
  /**
4037
4043
  * 恢复终端:启用行换行、显示光标、退出备选屏幕
4038
4044
  */
@@ -4175,6 +4181,7 @@ var InteractivePanel = class {
4175
4181
  this.isOperating = true;
4176
4182
  this.clearTimers();
4177
4183
  this.restoreTerminal();
4184
+ this.removeTerminalListeners();
4178
4185
  this.keyboardController.stop();
4179
4186
  action();
4180
4187
  console.log(PANEL_PRESS_ENTER_TO_RETURN);
@@ -4812,9 +4819,9 @@ var SYNC_RESOLVE_MESSAGES = {
4812
4819
  multipleMatches: MESSAGES.SYNC_MULTIPLE_MATCHES,
4813
4820
  noMatch: MESSAGES.SYNC_NO_MATCH
4814
4821
  };
4815
- function autoSaveChanges(worktreePath, branch) {
4822
+ function autoSaveChanges(worktreePath, branch, mainBranch) {
4816
4823
  gitAddAll(worktreePath);
4817
- gitCommit(AUTO_SAVE_COMMIT_MESSAGE, worktreePath);
4824
+ gitCommit(buildAutoSaveCommitMessage(mainBranch, branch), worktreePath);
4818
4825
  printInfo(MESSAGES.SYNC_AUTO_COMMITTED(branch));
4819
4826
  logger.info(`\u5DF2\u81EA\u52A8\u4FDD\u5B58 ${branch} \u5206\u652F\u7684\u672A\u63D0\u4EA4\u53D8\u66F4`);
4820
4827
  }
@@ -4833,7 +4840,7 @@ async function executeSyncForBranch(targetWorktreePath, branch) {
4833
4840
  const mainWorktreePath = getGitTopLevel();
4834
4841
  const mainBranch = getMainWorkBranch();
4835
4842
  if (!isWorkingDirClean(targetWorktreePath)) {
4836
- autoSaveChanges(targetWorktreePath, branch);
4843
+ autoSaveChanges(targetWorktreePath, branch, mainBranch);
4837
4844
  }
4838
4845
  printInfo(MESSAGES.SYNC_MERGING(branch, mainBranch));
4839
4846
  const hasConflict = mergeMainBranch(targetWorktreePath, mainBranch);
@@ -5083,7 +5090,7 @@ function commitSquash(message, worktreePath, branchName) {
5083
5090
  printSuccess(MESSAGES.MERGE_SQUASH_COMMITTED(branchName));
5084
5091
  }
5085
5092
  async function handleSquashIfNeeded(targetWorktreePath, mainWorktreePath, branchName, commitMessage) {
5086
- if (!hasCommitWithMessage(branchName, AUTO_SAVE_COMMIT_MESSAGE, mainWorktreePath)) {
5093
+ if (!hasCommitWithMessage(branchName, AUTO_SAVE_COMMIT_MESSAGE_PREFIX, mainWorktreePath)) {
5087
5094
  return false;
5088
5095
  }
5089
5096
  const shouldSquash = await confirmAction(MESSAGES.MERGE_SQUASH_PROMPT, false);
package/docs/merge.md CHANGED
@@ -42,7 +42,7 @@ clawt merge [-m <commitMessage>]
42
42
  - 提示 `主 worktree 有未提交的更改,请先处理`,退出
43
43
  - 无更改 → 继续
44
44
  6. **Squash 检测与执行(auto-save 临时提交压缩)**
45
- - 通过 `git log HEAD..<branchName> --format=%s` 检查目标分支是否存在以 `AUTO_SAVE_COMMIT_MESSAGE`(`chore: auto-save before sync`)为前缀的 commit
45
+ - 通过 `git log HEAD..<branchName> --format=%s` 检查目标分支是否存在以 `AUTO_SAVE_COMMIT_MESSAGE_PREFIX`(`clawt: auto-save before merging`)为前缀的 commit
46
46
  - **不存在** → 跳过,进入步骤 7
47
47
  - **存在** → 提示用户是否将所有提交压缩为一个:
48
48
  ```
package/docs/sync.md CHANGED
@@ -61,7 +61,7 @@ export interface SyncResult {
61
61
 
62
62
  1. **获取主 worktree 路径和主分支名**:通过 `getGitTopLevel()` 获取主 worktree 路径(后续传给 `rebuildValidateBranch`),通过项目级配置 `clawtMainWorkBranch` 获取主工作分支名(不再通过 `getCurrentBranch` 动态获取,因为在新架构下主 worktree 可能处于验证分支上)
63
63
  2. **自动保存未提交变更**:检查目标 worktree 是否有未提交修改
64
- - 有修改 → 自动执行 `git add . && git commit -m "<AUTO_SAVE_COMMIT_MESSAGE>"` 保存变更(commit message 由常量 `AUTO_SAVE_COMMIT_MESSAGE` 定义,值为 `chore: auto-save before sync`,同时用于 merge 命令的 squash 检测)
64
+ - 有修改 → 自动执行 `git add . && git commit -m "<message>"` 保存变更(commit message `buildAutoSaveCommitMessage(mainBranch, branch)` 函数动态生成,格式为 `clawt: auto-save before merging {mainBranch} into {branch}`,前缀部分由常量 `AUTO_SAVE_COMMIT_MESSAGE_PREFIX` 定义,值为 `clawt: auto-save before merging`,同时用于 merge 命令的 squash 检测)
65
65
  - 无修改 → 跳过
66
66
  3. **在目标 worktree 中合并主分支**:
67
67
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawt",
3
- "version": "3.8.5",
3
+ "version": "3.8.7",
4
4
  "description": "本地并行执行多个Claude Code Agent任务,融合 Git Worktree 与 Claude Code CLI 的命令行工具",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,7 +1,7 @@
1
1
  import type { Command } from 'commander';
2
2
  import { logger } from '../logger/index.js';
3
3
  import { ClawtError } from '../errors/index.js';
4
- import { MESSAGES, AUTO_SAVE_COMMIT_MESSAGE } from '../constants/index.js';
4
+ import { MESSAGES, AUTO_SAVE_COMMIT_MESSAGE_PREFIX } from '../constants/index.js';
5
5
  import type { MergeOptions } from '../types/index.js';
6
6
  import { PRE_CHECK_MERGE } from '../constants/index.js';
7
7
  import {
@@ -92,7 +92,7 @@ async function handleSquashIfNeeded(
92
92
  commitMessage?: string,
93
93
  ): Promise<boolean> {
94
94
  // 检查目标分支是否存在 auto-save commit
95
- if (!hasCommitWithMessage(branchName, AUTO_SAVE_COMMIT_MESSAGE, mainWorktreePath)) {
95
+ if (!hasCommitWithMessage(branchName, AUTO_SAVE_COMMIT_MESSAGE_PREFIX, mainWorktreePath)) {
96
96
  return false;
97
97
  }
98
98
 
@@ -1,7 +1,7 @@
1
1
  import type { Command } from 'commander';
2
2
  import { logger } from '../logger/index.js';
3
3
  import { ClawtError } from '../errors/index.js';
4
- import { MESSAGES, AUTO_SAVE_COMMIT_MESSAGE } from '../constants/index.js';
4
+ import { MESSAGES } from '../constants/index.js';
5
5
  import type { SyncOptions } from '../types/index.js';
6
6
  import { PRE_CHECK_SYNC } from '../constants/index.js';
7
7
  import {
@@ -20,6 +20,7 @@ import {
20
20
  getMainWorkBranch,
21
21
  rebuildValidateBranch,
22
22
  getValidateBranchName,
23
+ buildAutoSaveCommitMessage,
23
24
  } from '../utils/index.js';
24
25
  import type { WorktreeResolveMessages } from '../utils/index.js';
25
26
 
@@ -49,10 +50,11 @@ const SYNC_RESOLVE_MESSAGES: WorktreeResolveMessages = {
49
50
  * 自动保存目标 worktree 中的未提交变更
50
51
  * @param {string} worktreePath - 目标 worktree 路径
51
52
  * @param {string} branch - 分支名
53
+ * @param {string} mainBranch - 主分支名
52
54
  */
53
- function autoSaveChanges(worktreePath: string, branch: string): void {
55
+ function autoSaveChanges(worktreePath: string, branch: string, mainBranch: string): void {
54
56
  gitAddAll(worktreePath);
55
- gitCommit(AUTO_SAVE_COMMIT_MESSAGE, worktreePath);
57
+ gitCommit(buildAutoSaveCommitMessage(mainBranch, branch), worktreePath);
56
58
  printInfo(MESSAGES.SYNC_AUTO_COMMITTED(branch));
57
59
  logger.info(`已自动保存 ${branch} 分支的未提交变更`);
58
60
  }
@@ -99,7 +101,7 @@ export async function executeSyncForBranch(targetWorktreePath: string, branch: s
99
101
 
100
102
  // 检查目标 worktree 是否有未提交变更,有则自动保存
101
103
  if (!isWorkingDirClean(targetWorktreePath)) {
102
- autoSaveChanges(targetWorktreePath, branch);
104
+ autoSaveChanges(targetWorktreePath, branch, mainBranch);
103
105
  }
104
106
 
105
107
  // 在目标 worktree 中合并主分支
@@ -1,5 +1,5 @@
1
1
  /** sync 自动保存的 commit message 前缀,用于检测 auto-save 提交 */
2
- export const AUTO_SAVE_COMMIT_MESSAGE = 'chore: auto-save before sync';
2
+ export const AUTO_SAVE_COMMIT_MESSAGE_PREFIX = 'clawt: auto-save before merging';
3
3
 
4
4
  /** execSync 最大缓冲区大小(200MB),防止大分支 diff 时触发 ENOBUFS 错误 */
5
5
  export const EXEC_MAX_BUFFER = 200 * 1024 * 1024;
@@ -7,7 +7,7 @@ export { EXIT_CODES } from './exitCodes.js';
7
7
  export { ENABLE_BRACKETED_PASTE, DISABLE_BRACKETED_PASTE, PASTE_THRESHOLD_MS, VALID_TERMINAL_APPS, ITERM2_APP_PATH } from './terminal.js';
8
8
  export { DEFAULT_CONFIG, CONFIG_DESCRIPTIONS, CONFIG_DEFINITIONS, APPEND_SYSTEM_PROMPT } from './config.js';
9
9
  export { PROJECT_CONFIG_DEFINITIONS, PROJECT_DEFAULT_CONFIG, PROJECT_CONFIG_DESCRIPTIONS } from './project-config.js';
10
- export { AUTO_SAVE_COMMIT_MESSAGE } from './git.js';
10
+ export { AUTO_SAVE_COMMIT_MESSAGE_PREFIX } from './git.js';
11
11
  export { DEBUG_LOG_PREFIX, DEBUG_TIMESTAMP_FORMAT } from './logger.js';
12
12
  export { UPDATE_CHECK_INTERVAL_MS, NPM_REGISTRY_URL, NPM_REGISTRY_TIMEOUT_MS, PACKAGE_NAME } from './update.js';
13
13
  export {
@@ -2,7 +2,7 @@ import { basename } from 'node:path';
2
2
  import { execSync, execFileSync } from 'node:child_process';
3
3
  import { execCommand, execCommandWithInput } from './shell.js';
4
4
  import { logger } from '../logger/index.js';
5
- import { EXEC_MAX_BUFFER } from '../constants/git.js';
5
+ import { EXEC_MAX_BUFFER, AUTO_SAVE_COMMIT_MESSAGE_PREFIX } from '../constants/git.js';
6
6
 
7
7
  /**
8
8
  * 获取 git common dir(用于判断是否为主 worktree)
@@ -459,3 +459,13 @@ export function gitMergeContinue(cwd?: string): void {
459
459
  export function gitMergeAbort(cwd?: string): void {
460
460
  execCommand('git merge --abort', { cwd });
461
461
  }
462
+
463
+ /**
464
+ * 生成完整的 auto-save commit message
465
+ * @param {string} mainBranch - 主分支名(被合并的源分支)
466
+ * @param {string} branch - 目标分支名(合并到的分支)
467
+ * @returns {string} 完整的 commit message
468
+ */
469
+ export function buildAutoSaveCommitMessage(mainBranch: string, branch: string): string {
470
+ return `${AUTO_SAVE_COMMIT_MESSAGE_PREFIX} ${mainBranch} into ${branch}`;
471
+ }
@@ -56,6 +56,7 @@ export {
56
56
  gitAddFiles,
57
57
  gitMergeContinue,
58
58
  gitMergeAbort,
59
+ buildAutoSaveCommitMessage,
59
60
  } from './git.js';
60
61
  export { sanitizeBranchName, generateBranchNames, validateBranchesNotExist } from './branch.js';
61
62
  export { validateMainWorktree, validateGitInstalled, validateClaudeCodeInstalled, validateHeadExists, validateWorkingDirClean, runPreChecks } from './validation.js';
@@ -125,17 +125,7 @@ export class InteractivePanel {
125
125
  // 恢复终端
126
126
  this.restoreTerminal();
127
127
 
128
- // 移除 resize 监听
129
- if (this.resizeHandler) {
130
- process.stdout.removeListener('resize', this.resizeHandler);
131
- this.resizeHandler = null;
132
- }
133
-
134
- // 移除 exit 兜底
135
- if (this.exitHandler) {
136
- process.removeListener('exit', this.exitHandler);
137
- this.exitHandler = null;
138
- }
128
+ this.removeTerminalListeners();
139
129
 
140
130
  // 完成 Promise
141
131
  if (this.resolveStart) {
@@ -148,6 +138,9 @@ export class InteractivePanel {
148
138
  * 初始化终端:进入备选屏幕、隐藏光标、禁用行换行
149
139
  */
150
140
  private initTerminal(): void {
141
+ // 确保不会重复注册监听器
142
+ this.removeTerminalListeners();
143
+
151
144
  process.stdout.write(ALT_SCREEN_ENTER);
152
145
  process.stdout.write(CURSOR_HIDE);
153
146
  process.stdout.write(LINE_WRAP_DISABLE);
@@ -163,14 +156,24 @@ export class InteractivePanel {
163
156
  process.stdout.on('resize', this.resizeHandler);
164
157
 
165
158
  // 注册 exit 兜底,确保异常退出时终端状态被恢复
166
- this.exitHandler = () => {
167
- process.stdout.write(LINE_WRAP_ENABLE);
168
- process.stdout.write(CURSOR_SHOW);
169
- process.stdout.write(ALT_SCREEN_LEAVE);
170
- };
159
+ this.exitHandler = () => this.restoreTerminal();
171
160
  process.on('exit', this.exitHandler);
172
161
  }
173
162
 
163
+ /**
164
+ * 移除终端事件监听器(resize 和 exit)
165
+ */
166
+ private removeTerminalListeners(): void {
167
+ if (this.resizeHandler) {
168
+ process.stdout.removeListener('resize', this.resizeHandler);
169
+ this.resizeHandler = null;
170
+ }
171
+ if (this.exitHandler) {
172
+ process.removeListener('exit', this.exitHandler);
173
+ this.exitHandler = null;
174
+ }
175
+ }
176
+
174
177
  /**
175
178
  * 恢复终端:启用行换行、显示光标、退出备选屏幕
176
179
  */
@@ -365,6 +368,8 @@ export class InteractivePanel {
365
368
 
366
369
  // 恢复终端以便子命令输出
367
370
  this.restoreTerminal();
371
+ // 移除旧的终端事件监听器,避免 initTerminal() 重复注册导致泄漏
372
+ this.removeTerminalListeners();
368
373
 
369
374
  // 恢复 stdin 以便子命令交互
370
375
  this.keyboardController.stop();
@@ -41,7 +41,7 @@ vi.mock('../../../src/constants/index.js', async (importOriginal) => {
41
41
  MERGE_SUCCESS_NO_MESSAGE: (branch: string, autoPullPush: boolean) => `合并成功: ${branch}`,
42
42
  WORKTREE_CLEANED: (branch: string) => `已清理: ${branch}`,
43
43
  },
44
- AUTO_SAVE_COMMIT_MESSAGE: 'clawt:auto-save',
44
+ AUTO_SAVE_COMMIT_MESSAGE_PREFIX: 'clawt: auto-save before merging',
45
45
  };
46
46
  });
47
47
 
@@ -30,7 +30,7 @@ vi.mock('../../../src/constants/index.js', async (importOriginal) => {
30
30
  SYNC_SUCCESS: (branch: string, mainBranch: string) => `✓ 已将 ${mainBranch} 同步到 ${branch}`,
31
31
  SYNC_VALIDATE_BRANCH_REBUILT: (validateBranch: string) => `验证分支 ${validateBranch} 已重建`,
32
32
  },
33
- AUTO_SAVE_COMMIT_MESSAGE: 'clawt:auto-save',
33
+ AUTO_SAVE_COMMIT_MESSAGE_PREFIX: 'clawt: auto-save before merging',
34
34
  };
35
35
  });
36
36
 
@@ -54,6 +54,8 @@ vi.mock('../../../src/utils/index.js', () => ({
54
54
  getValidateBranchName: vi.fn((name: string) => `clawt-validate-${name}`),
55
55
  guardMainWorkBranch: vi.fn().mockResolvedValue(undefined),
56
56
  guardMainWorkBranchExists: vi.fn(),
57
+ buildAutoSaveCommitMessage: (mainBranch: string, branch: string) =>
58
+ `clawt: auto-save before merging ${mainBranch} into ${branch}`,
57
59
  }));
58
60
 
59
61
  import { registerSyncCommand } from '../../../src/commands/sync.js';
@@ -135,7 +137,10 @@ describe('handleSync', () => {
135
137
  await program.parseAsync(['sync', '-b', 'feature'], { from: 'user' });
136
138
 
137
139
  expect(mockedGitAddAll).toHaveBeenCalledWith('/path/feature');
138
- expect(mockedGitCommit).toHaveBeenCalledWith('clawt:auto-save', '/path/feature');
140
+ expect(mockedGitCommit).toHaveBeenCalledWith(
141
+ 'clawt: auto-save before merging main into feature',
142
+ '/path/feature',
143
+ );
139
144
  expect(mockedGitMerge).toHaveBeenCalled();
140
145
  });
141
146
 
@@ -1,17 +1,17 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { AUTO_SAVE_COMMIT_MESSAGE } from '../../../src/constants/git.js';
2
+ import { AUTO_SAVE_COMMIT_MESSAGE_PREFIX } from '../../../src/constants/git.js';
3
3
 
4
- describe('AUTO_SAVE_COMMIT_MESSAGE', () => {
5
- it('值为预期的 commit message', () => {
6
- expect(AUTO_SAVE_COMMIT_MESSAGE).toBe('chore: auto-save before sync');
4
+ describe('AUTO_SAVE_COMMIT_MESSAGE_PREFIX', () => {
5
+ it('值为预期的前缀', () => {
6
+ expect(AUTO_SAVE_COMMIT_MESSAGE_PREFIX).toBe('clawt: auto-save before merging');
7
7
  });
8
8
 
9
9
  it('是非空字符串', () => {
10
- expect(typeof AUTO_SAVE_COMMIT_MESSAGE).toBe('string');
11
- expect(AUTO_SAVE_COMMIT_MESSAGE.length).toBeGreaterThan(0);
10
+ expect(typeof AUTO_SAVE_COMMIT_MESSAGE_PREFIX).toBe('string');
11
+ expect(AUTO_SAVE_COMMIT_MESSAGE_PREFIX.length).toBeGreaterThan(0);
12
12
  });
13
13
 
14
14
  it('符合 conventional commit 格式', () => {
15
- expect(AUTO_SAVE_COMMIT_MESSAGE).toMatch(/^[a-z]+:\s.+$/);
15
+ expect(AUTO_SAVE_COMMIT_MESSAGE_PREFIX).toMatch(/^[a-z]+:\s.+$/);
16
16
  });
17
17
  });
@@ -64,6 +64,7 @@ import {
64
64
  gitDiffTree,
65
65
  gitApplyCachedCheck,
66
66
  getBranchCreatedAt,
67
+ buildAutoSaveCommitMessage,
67
68
  } from '../../../src/utils/git.js';
68
69
 
69
70
  const mockedExecCommand = vi.mocked(execCommand);
@@ -610,3 +611,20 @@ describe('getBranchCreatedAt', () => {
610
611
  );
611
612
  });
612
613
  });
614
+
615
+ describe('buildAutoSaveCommitMessage', () => {
616
+ it('生成包含分支信息的完整 commit message', () => {
617
+ const result = buildAutoSaveCommitMessage('main', 'feature/login');
618
+ expect(result).toBe('clawt: auto-save before merging main into feature/login');
619
+ });
620
+
621
+ it('生成的 message 以前缀常量开头', () => {
622
+ const result = buildAutoSaveCommitMessage('main', 'feat-xyz');
623
+ expect(result.startsWith('clawt: auto-save before merging')).toBe(true);
624
+ });
625
+
626
+ it('符合 conventional commit 格式', () => {
627
+ const result = buildAutoSaveCommitMessage('develop', 'hotfix');
628
+ expect(result).toMatch(/^[a-z]+:\s.+$/);
629
+ });
630
+ });