@hifullmoon/aicommit 1.4.0 → 1.5.1
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 +59 -74
- package/README.md +29 -9
- package/README.zh-CN.md +42 -22
- package/SECURITY.md +1 -1
- package/docs/distribution.md +23 -51
- package/docs/troubleshooting.md +1 -1
- package/package.json +5 -4
- package/src/cli.js +19 -10
- package/src/split.js +9 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,131 +1,116 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This file lists notable user-facing changes. Internal refactors, test-only changes, release mechanics, and documentation-only edits are omitted.
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.5.1] - 2026-08-27
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Normalized Windows 8.3 path aliases before validating split plan destinations, so repository-local output is rejected before any provider request.
|
|
12
|
+
|
|
13
|
+
## [1.5.0] - 2026-08-27
|
|
14
|
+
|
|
7
15
|
### Added
|
|
8
16
|
|
|
9
|
-
-
|
|
17
|
+
- Added a built-in Kimi Code provider preset and an environment-variable configuration example.
|
|
10
18
|
|
|
11
19
|
### Changed
|
|
12
20
|
|
|
13
|
-
-
|
|
14
|
-
- Repository
|
|
15
|
-
- Provider preset compatibility now
|
|
16
|
-
-
|
|
21
|
+
- `aicommit split` now starts the interactive split flow directly; `aicommit split run` remains available as an alias.
|
|
22
|
+
- Repository policies can enforce their configured language without CLI overrides.
|
|
23
|
+
- Provider preset compatibility now follows SemVer rules for prerelease and build versions.
|
|
24
|
+
- Split commands detect unfinished checkpoints early and provide safe resume or abort actions.
|
|
17
25
|
|
|
18
26
|
### Security
|
|
19
27
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
28
|
+
- Sensitive URL components are redacted from configuration, diagnostics, debug output, extension input, and credential-helper errors.
|
|
29
|
+
- Provider extensions reject credential-like configuration fields and excessively deep nested input.
|
|
22
30
|
|
|
23
|
-
##
|
|
31
|
+
## 1.4.0 - 2026-08-24
|
|
24
32
|
|
|
25
33
|
### Added
|
|
26
34
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
- Automated npm/Homebrew installation smoke paths plus bilingual distribution, troubleshooting, privacy, and provider-compatibility guides.
|
|
35
|
+
- Added credential-free `config show`, `config validate`, and `config path` commands.
|
|
36
|
+
- Added generated shell completion for Bash, Zsh, and Fish.
|
|
37
|
+
- Added repository-owned team policies with deterministic local and CI checks.
|
|
38
|
+
- Added independently updateable provider presets with install, repair, and rollback support.
|
|
39
|
+
- Added an isolated extension API for context providers, message validators, and provider adapters.
|
|
33
40
|
|
|
34
41
|
### Changed
|
|
35
42
|
|
|
36
|
-
- Interactive setup now
|
|
37
|
-
- Provider request orchestration accepts asynchronous built-in or extension adapters without changing the Git and interaction flows.
|
|
43
|
+
- Interactive setup now reads providers from the active preset manifest.
|
|
38
44
|
|
|
39
45
|
### Security
|
|
40
46
|
|
|
41
|
-
-
|
|
42
|
-
-
|
|
47
|
+
- Extension processes run with explicit permissions, a sanitized environment, and no provider credentials.
|
|
48
|
+
- Project configuration cannot enable extensions or weaken credential boundaries.
|
|
43
49
|
|
|
44
|
-
##
|
|
50
|
+
## 1.3.0 - 2026-08-24
|
|
45
51
|
|
|
46
52
|
### Added
|
|
47
53
|
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
- Opt-in `--split-hunks` support for tracked multi-hunk text modifications, with hunk IDs/ranges/hashes in plans and machine output.
|
|
52
|
-
- A shared end-to-end split fault matrix for SIGINT, process crashes, concurrent edits, hook failures, renames, deletions, binary files, and submodules.
|
|
54
|
+
- Added explicit staged/all split scopes and reusable `split plan` / `split apply` artifacts.
|
|
55
|
+
- Added resumable split checkpoints for interrupted or failed multi-commit operations.
|
|
56
|
+
- Added optional same-file hunk splitting for tracked text files.
|
|
53
57
|
|
|
54
58
|
### Changed
|
|
55
59
|
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
- Split apply and resume run without loading provider configuration or credentials.
|
|
60
|
+
- Split commits are built from captured snapshots so later worktree edits cannot enter pending commits.
|
|
61
|
+
- Split apply and resume no longer require provider configuration or credentials.
|
|
59
62
|
|
|
60
63
|
### Security
|
|
61
64
|
|
|
62
|
-
- Split
|
|
63
|
-
- Experimental hunk execution validates selected patches entirely in temporary indexes and requires the final tree to reproduce every captured target blob exactly; otherwise planning falls back to file-level groups before the first commit.
|
|
65
|
+
- Split plans, checkpoints, paths, and hunk operations are validated before Git state is changed.
|
|
64
66
|
|
|
65
|
-
##
|
|
67
|
+
## 1.2.0 - 2026-08-24
|
|
66
68
|
|
|
67
69
|
### Added
|
|
68
70
|
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
- Anonymous local eval coverage for single/mixed changes, renames, generated files, long diffs, Chinese/English output, and malformed weak-model candidates, enforced in CI at 99% or better.
|
|
71
|
+
- Added versioned commit policies for type, scope, subject, body, breaking changes, and language.
|
|
72
|
+
- Added bounded repository context from recent commits, package boundaries, trusted convention files, and recognized commitlint rules.
|
|
73
|
+
- Added local-only quality statistics with enable, disable, and clear controls.
|
|
73
74
|
|
|
74
75
|
### Changed
|
|
75
76
|
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
- Candidate responses are validated locally for policy compliance and diff/path alignment; hard policy failures receive at most one low-cost correction without re-sending the diff.
|
|
79
|
-
- Automatic policy corrections now contribute to the anonymous local rewrite metric.
|
|
77
|
+
- Commit generation now uses an authoritative structured policy and locally validates candidate messages.
|
|
78
|
+
- Repository context categories and budgets can be configured without allowing project settings to expand user-owned limits.
|
|
80
79
|
|
|
81
80
|
### Security
|
|
82
81
|
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
- Trusted convention reads reject paths outside the repository, symbolic links, and non-regular files; commitlint configuration is parsed as data and never executed.
|
|
82
|
+
- Repository and diff inputs are isolated as untrusted structured data.
|
|
83
|
+
- Trusted convention files cannot escape the repository or execute commitlint configuration code.
|
|
86
84
|
|
|
87
|
-
##
|
|
85
|
+
## 1.1.0 - 2026-08-24
|
|
88
86
|
|
|
89
87
|
### Added
|
|
90
88
|
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
- Bounded retries for rate limits, recoverable server failures, and interrupted network responses, including `Retry-After` support.
|
|
97
|
-
- Stable error categories and process exit codes for config, Git state, network, provider, response-format, sensitive-data, and concurrent-modification failures.
|
|
98
|
-
- `--output=text|json` with a published JSON schema and decoration-free stdout for automation.
|
|
99
|
-
- `aicommit doctor` diagnostics for runtime, configuration, endpoint security, provider capabilities, credentials, and connectivity.
|
|
100
|
-
- Optional Git credential-helper integration for OS-backed credential storage.
|
|
101
|
-
- Minimal local-only metrics with status, clear, enable, and disable commands.
|
|
89
|
+
- Added unified support for OpenAI, OpenRouter, DeepSeek, MiniMax, Ollama, and custom compatible endpoints.
|
|
90
|
+
- Added bounded retries for rate limits, recoverable server failures, and interrupted responses.
|
|
91
|
+
- Added stable error categories, process exit codes, and JSON output for automation.
|
|
92
|
+
- Added `aicommit doctor` diagnostics.
|
|
93
|
+
- Added optional Git credential-helper integration.
|
|
102
94
|
|
|
103
95
|
### Changed
|
|
104
96
|
|
|
105
|
-
- Constrained interactive prompt dependencies to releases that support Node.js 18.
|
|
106
|
-
- Normalized provider usage as input, output, and total tokens and exposed finish reasons through one internal response contract.
|
|
107
97
|
- Environment credentials now take priority over credential helpers and legacy plaintext configuration.
|
|
108
|
-
-
|
|
98
|
+
- Provider usage is normalized as input, output, and total tokens.
|
|
109
99
|
|
|
110
|
-
###
|
|
100
|
+
### Security
|
|
111
101
|
|
|
112
|
-
-
|
|
113
|
-
- Split
|
|
114
|
-
- Non-interactive split mode fails closed before auto-staging detected sensitive files.
|
|
115
|
-
- Split-plan messages are sanitized before terminal display and commit execution.
|
|
102
|
+
- Sensitive untracked files are detected before non-interactive staging.
|
|
103
|
+
- Split previews avoid symbolic links and sanitize generated messages before display or commit.
|
|
116
104
|
|
|
117
|
-
##
|
|
105
|
+
## 1.0.0 - 2026-08-24
|
|
118
106
|
|
|
119
107
|
### Added
|
|
120
108
|
|
|
121
|
-
- Conventional
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
|
|
126
|
-
[Unreleased]: https://github.com/hi-fullmoon/AICommit/compare/v1.
|
|
127
|
-
[1.
|
|
128
|
-
[1.
|
|
129
|
-
[1.2.0]: https://github.com/hi-fullmoon/AICommit/compare/v1.1.0...v1.2.0
|
|
130
|
-
[1.1.0]: https://github.com/hi-fullmoon/AICommit/compare/v1.0.0...v1.1.0
|
|
131
|
-
[1.0.0]: https://github.com/hi-fullmoon/AICommit/releases/tag/v1.0.0
|
|
109
|
+
- Added Conventional Commit generation in Chinese or English through OpenAI-compatible providers.
|
|
110
|
+
- Added interactive staging, editing, regeneration, dry-run, reasoning display, and connection checks.
|
|
111
|
+
- Added file-level split planning and execution with Git-state concurrency checks.
|
|
112
|
+
- Added provider presets and user/project configuration boundaries.
|
|
113
|
+
|
|
114
|
+
[Unreleased]: https://github.com/hi-fullmoon/AICommit/compare/v1.5.1...HEAD
|
|
115
|
+
[1.5.1]: https://github.com/hi-fullmoon/AICommit/releases/tag/v1.5.1
|
|
116
|
+
[1.5.0]: https://github.com/hi-fullmoon/AICommit/releases/tag/v1.5.0
|
package/README.md
CHANGED
|
@@ -4,6 +4,26 @@
|
|
|
4
4
|
|
|
5
5
|
AI-powered git commit message generator: reads your diff, asks an AI model for a conventional commit message, and commits after your confirmation.
|
|
6
6
|
|
|
7
|
+
## Usage preview
|
|
8
|
+
|
|
9
|
+
These screenshots were captured from real interactive terminal sessions in this repository. Provider, model, paths, and timings reflect the environment at capture time.
|
|
10
|
+
|
|
11
|
+
### Configure a provider interactively
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
### Diagnose configuration and connectivity
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
### Generate a commit message
|
|
20
|
+
|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
### Review the generated commit message
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
7
27
|
## Install
|
|
8
28
|
|
|
9
29
|
```bash
|
|
@@ -259,15 +279,15 @@ aicommit stats # show local quality, latency, and token trends
|
|
|
259
279
|
aicommit stats clear # permanently clear local metric history
|
|
260
280
|
aicommit # generate & commit in current directory
|
|
261
281
|
aicommit /path/to/repo # or a target directory
|
|
262
|
-
aicommit split
|
|
263
|
-
aicommit split
|
|
264
|
-
aicommit split
|
|
265
|
-
aicommit split
|
|
282
|
+
aicommit split # choose staged/all scope, then split logical commits
|
|
283
|
+
aicommit split --scope=staged # split only the reviewed index snapshot
|
|
284
|
+
aicommit split --scope=all # split the complete working-tree snapshot
|
|
285
|
+
aicommit split --scope=staged --split-hunks # experimental same-file hunk splitting
|
|
266
286
|
aicommit --dry-run # generate and review without creating a commit
|
|
267
|
-
aicommit split
|
|
287
|
+
aicommit split --dry-run # review a split plan without creating commits
|
|
268
288
|
aicommit --yes # non-interactively commit already staged changes
|
|
269
289
|
aicommit --yes --dry-run # non-interactively preview all changes; restores staging
|
|
270
|
-
aicommit split
|
|
290
|
+
aicommit split --scope=all --yes # non-interactively plan and commit all working-tree changes
|
|
271
291
|
aicommit split plan --scope=staged --file=/tmp/split-plan.json --yes
|
|
272
292
|
aicommit split apply --file=/tmp/split-plan.json --yes
|
|
273
293
|
aicommit split resume --yes # resume an interrupted split transaction
|
|
@@ -285,7 +305,7 @@ aicommit -h # help
|
|
|
285
305
|
| `-l`, `--lang` | Commit message language (`zh` or `en`) |
|
|
286
306
|
| `-p`, `--provider` | Use the named provider from `providers` |
|
|
287
307
|
| `--split-hunks` | Opt in to experimental same-file text-hunk planning; disabled by default |
|
|
288
|
-
| `--scope` | `staged` or `all` scope for `aicommit split
|
|
308
|
+
| `--scope` | `staged` or `all` scope for `aicommit split` and `aicommit split plan` |
|
|
289
309
|
| `--file` | JSON plan path for `aicommit split plan` and `aicommit split apply` |
|
|
290
310
|
| `--dry-run` | Generate and review a message or split plan without creating commits |
|
|
291
311
|
| `-y`, `--yes` | Accept without prompts; normal mode requires explicitly staged changes |
|
|
@@ -389,7 +409,7 @@ When reasoning mode is `on` (including via `--reasoning=<level>`), aicommit requ
|
|
|
389
409
|
|
|
390
410
|
### Split mode
|
|
391
411
|
|
|
392
|
-
`aicommit split run` asks whether to group the staged index snapshot or all staged, unstaged, and untracked changes into logical commits. Use `--scope=staged` or `--scope=all` when the boundary must be explicit, including every non-interactive run. You can review the plan, regenerate messages for selected groups, or edit the plan as JSON before committing. Extension validation errors are shown with the plan and must be corrected by editing or regenerating before commit. Sensitive-content detection fails closed before a non-interactive provider request or automatic staging.
|
|
412
|
+
`aicommit split` (also available as the explicit `aicommit split run`) asks whether to group the staged index snapshot or all staged, unstaged, and untracked changes into logical commits. Use `--scope=staged` or `--scope=all` when the boundary must be explicit, including every non-interactive run. You can review the plan, regenerate messages for selected groups, or edit the plan as JSON before committing. Extension validation errors are shown with the plan and must be corrected by editing or regenerating before commit. Sensitive-content detection fails closed before a non-interactive provider request or automatic staging.
|
|
393
413
|
|
|
394
414
|
For an auditable two-step flow, `aicommit split plan --scope=staged|all --file=<path>` exports a versioned JSON artifact, and `aicommit split apply --file=<path>` rechecks its base commit, change set, and content fingerprint before touching the index. Keep plan files outside the worktree or under `.git` so they cannot become part of their own plan.
|
|
395
415
|
|
|
@@ -399,7 +419,7 @@ Split remains file-level by default. `--split-hunks` opts in to experimental sam
|
|
|
399
419
|
|
|
400
420
|
## Development and releases
|
|
401
421
|
|
|
402
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for local development and pull-request checks, [SECURITY.md](SECURITY.md) for private vulnerability reporting, [RELEASING.md](RELEASING.md) for the
|
|
422
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for local development and pull-request checks, [SECURITY.md](SECURITY.md) for private vulnerability reporting, [RELEASING.md](RELEASING.md) for the maintainer process, and the bilingual [distribution guide](docs/distribution.md) for npm/Homebrew installation and rollback. Releases use npm Trusted Publishing with provenance, verify the exact package tarball, and run a post-publish Homebrew smoke test. `npm run eval` runs the anonymous local quality corpus covering single and mixed changes, renames, generated files, long diffs, Chinese/English output, and malformed weak-model candidates; it is also part of `npm run ci`.
|
|
403
423
|
|
|
404
424
|
## License
|
|
405
425
|
|
package/README.zh-CN.md
CHANGED
|
@@ -4,6 +4,26 @@
|
|
|
4
4
|
|
|
5
5
|
AI 驱动的 Git 提交信息生成器:读取 diff,请 AI 模型生成符合 Conventional Commits 规范的提交信息,并在你确认后执行提交。
|
|
6
6
|
|
|
7
|
+
## 使用预览
|
|
8
|
+
|
|
9
|
+
以下截图来自本仓库中的真实交互式终端会话。Provider、模型、路径和耗时均为截图时的实际环境。
|
|
10
|
+
|
|
11
|
+
### 交互式配置 Provider
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
### 检查配置与连接
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
### 生成提交信息
|
|
20
|
+
|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
### 检查生成的提交信息
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
7
27
|
## 安装
|
|
8
28
|
|
|
9
29
|
使用 npm:
|
|
@@ -261,15 +281,15 @@ aicommit stats # 显示本地质量、延迟和 token 趋势
|
|
|
261
281
|
aicommit stats clear # 永久清除本地指标历史
|
|
262
282
|
aicommit # 在当前目录生成提交信息并提交
|
|
263
283
|
aicommit /path/to/repo # 或指定目标目录
|
|
264
|
-
aicommit split
|
|
265
|
-
aicommit split
|
|
266
|
-
aicommit split
|
|
267
|
-
aicommit split
|
|
284
|
+
aicommit split # 选择 staged / all 范围并拆分逻辑提交
|
|
285
|
+
aicommit split --scope=staged # 只拆分已审阅的 index 快照
|
|
286
|
+
aicommit split --scope=all # 拆分完整工作区快照
|
|
287
|
+
aicommit split --scope=staged --split-hunks # 实验性同文件 hunk 拆分
|
|
268
288
|
aicommit --dry-run # 生成并审阅,但不创建提交
|
|
269
|
-
aicommit split
|
|
289
|
+
aicommit split --dry-run # 审阅拆分计划,但不创建提交
|
|
270
290
|
aicommit --yes # 非交互提交已明确暂存的变更
|
|
271
291
|
aicommit --yes --dry-run # 非交互预览所有变更;退出时恢复暂存状态
|
|
272
|
-
aicommit split
|
|
292
|
+
aicommit split --scope=all --yes # 非交互规划并提交所有工作区变更
|
|
273
293
|
aicommit split plan --scope=staged --file=/tmp/split-plan.json --yes
|
|
274
294
|
aicommit split apply --file=/tmp/split-plan.json --yes
|
|
275
295
|
aicommit split resume --yes # 恢复中断的拆分事务
|
|
@@ -282,20 +302,20 @@ aicommit --yes --output=json # 向 stdout 输出一个通过 schema 校验的 JS
|
|
|
282
302
|
aicommit -h # 帮助
|
|
283
303
|
```
|
|
284
304
|
|
|
285
|
-
| 选项 | 说明
|
|
286
|
-
| ------------------ |
|
|
287
|
-
| `-l`, `--lang` | 提交信息语言:`zh` 或 `en`
|
|
288
|
-
| `-p`, `--provider` | 使用 `providers` 中的命名 Provider
|
|
289
|
-
| `--split-hunks` | 启用实验性同文件文本 hunk 规划;默认关闭
|
|
290
|
-
| `--scope` | `aicommit split
|
|
291
|
-
| `--file` | `aicommit split plan` 和 `aicommit split apply` 的 JSON 计划路径
|
|
292
|
-
| `--dry-run` | 生成并审阅消息或拆分计划,但不创建提交
|
|
293
|
-
| `-y`, `--yes` | 不提示直接接受;普通模式要求变更已明确暂存
|
|
294
|
-
| `--reasoning` | 启用推理,可选强度:`low`、`medium`、`high`、`xhigh` 或 `max`
|
|
295
|
-
| `--no-reasoning` | 所选 Provider / 模型支持时显式关闭推理
|
|
296
|
-
| `--output` | `text`(默认)或单个 JSON 对象;提交 / 拆分的 JSON 流程要求 `--yes`
|
|
297
|
-
| `-v`, `--version` | 显示版本
|
|
298
|
-
| `-h`, `--help` | 显示帮助
|
|
305
|
+
| 选项 | 说明 |
|
|
306
|
+
| ------------------ | ------------------------------------------------------------------- |
|
|
307
|
+
| `-l`, `--lang` | 提交信息语言:`zh` 或 `en` |
|
|
308
|
+
| `-p`, `--provider` | 使用 `providers` 中的命名 Provider |
|
|
309
|
+
| `--split-hunks` | 启用实验性同文件文本 hunk 规划;默认关闭 |
|
|
310
|
+
| `--scope` | `aicommit split` 和 `aicommit split plan` 的范围:`staged` 或 `all` |
|
|
311
|
+
| `--file` | `aicommit split plan` 和 `aicommit split apply` 的 JSON 计划路径 |
|
|
312
|
+
| `--dry-run` | 生成并审阅消息或拆分计划,但不创建提交 |
|
|
313
|
+
| `-y`, `--yes` | 不提示直接接受;普通模式要求变更已明确暂存 |
|
|
314
|
+
| `--reasoning` | 启用推理,可选强度:`low`、`medium`、`high`、`xhigh` 或 `max` |
|
|
315
|
+
| `--no-reasoning` | 所选 Provider / 模型支持时显式关闭推理 |
|
|
316
|
+
| `--output` | `text`(默认)或单个 JSON 对象;提交 / 拆分的 JSON 流程要求 `--yes` |
|
|
317
|
+
| `-v`, `--version` | 显示版本 |
|
|
318
|
+
| `-h`, `--help` | 显示帮助 |
|
|
299
319
|
|
|
300
320
|
### 配置检查
|
|
301
321
|
|
|
@@ -391,7 +411,7 @@ aicommit completion fish > ~/.config/fish/completions/aicommit.fish
|
|
|
391
411
|
|
|
392
412
|
### 拆分提交模式
|
|
393
413
|
|
|
394
|
-
`aicommit split
|
|
414
|
+
`aicommit split`(也可以显式写成 `aicommit split run`)会询问是对暂存 index 快照分组,还是对全部已暂存、未暂存和未跟踪变更分组。边界必须明确时请使用 `--scope=staged` 或 `--scope=all`,所有非交互运行都应显式指定范围。提交前可以审阅计划、为选中的组重新生成消息,或直接编辑 JSON 计划。扩展校验错误会随计划显示,必须通过编辑或重新生成修复后才能提交。敏感内容检测会在非交互 Provider 请求或自动暂存前 fail closed。
|
|
395
415
|
|
|
396
416
|
如需可审计的两步流程,使用 `aicommit split plan --scope=staged|all --file=<path>` 导出版本化 JSON 工件,再用 `aicommit split apply --file=<path>` 在接触 index 前重新校验 base commit、变更集和内容指纹。计划文件应保存在工作区之外或 `.git` 下,避免被纳入自身计划。
|
|
397
417
|
|
|
@@ -401,7 +421,7 @@ split 默认仍按文件拆分。`--split-hunks` 可选择性启用实验性的
|
|
|
401
421
|
|
|
402
422
|
## 开发与发布
|
|
403
423
|
|
|
404
|
-
本地开发和 Pull Request 检查请参阅 [CONTRIBUTING.md](CONTRIBUTING.md),私密漏洞报告请参阅 [SECURITY.md](SECURITY.md)
|
|
424
|
+
本地开发和 Pull Request 检查请参阅 [CONTRIBUTING.md](CONTRIBUTING.md),私密漏洞报告请参阅 [SECURITY.md](SECURITY.md),维护者发布流程请参阅 [RELEASING.md](RELEASING.md),npm / Homebrew 安装和用户回滚请参阅双语[分发指南](docs/distribution.md)。发布通过 npm Trusted Publishing 生成 provenance,校验精确的 package tarball,并在发布后执行 Homebrew 冒烟测试。`npm run eval` 会运行匿名本地质量语料,覆盖单一与混合变更、rename、生成文件、长 diff、中英文输出和格式错误的弱模型候选;该命令也是 `npm run ci` 的一部分。
|
|
405
425
|
|
|
406
426
|
## 许可证
|
|
407
427
|
|
package/SECURITY.md
CHANGED
|
@@ -24,7 +24,7 @@ AICommit is a local CLI that sends selected repository context directly to the c
|
|
|
24
24
|
- common sensitive content should be detected and protected before the default model request;
|
|
25
25
|
- remote endpoints must use HTTPS, while plaintext HTTP is limited to loopback development services.
|
|
26
26
|
- third-party extension API v1 must deny resolved credential access, run out of process with a sanitized environment, and fail instead of falling back to unsandboxed execution;
|
|
27
|
-
-
|
|
27
|
+
- npm releases must use Trusted Publishing provenance, and the Homebrew formula must pin the published npm tarball by SHA-256.
|
|
28
28
|
|
|
29
29
|
Sensitive-content detection is intentionally a defense in depth and cannot replace a dedicated secret scanner. Interactive users can explicitly choose to send original content after a warning. Review the selected endpoint and diff before doing so.
|
|
30
30
|
|
package/docs/distribution.md
CHANGED
|
@@ -1,43 +1,41 @@
|
|
|
1
|
-
# Distribution
|
|
1
|
+
# Distribution / 分发
|
|
2
2
|
|
|
3
|
-
AICommit
|
|
3
|
+
AICommit 通过 npm 与 Homebrew 发布。Homebrew formula 安装同一个 npm tarball,并用 SHA-256 固定其内容。
|
|
4
4
|
|
|
5
|
-
AICommit
|
|
5
|
+
AICommit is distributed through npm and Homebrew. The Homebrew formula installs the same npm tarball and pins it by SHA-256.
|
|
6
6
|
|
|
7
7
|
## npm
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
+
# install / 安装
|
|
10
11
|
npm install --global @hifullmoon/aicommit
|
|
11
|
-
aicommit --version
|
|
12
12
|
|
|
13
13
|
# upgrade / 升级
|
|
14
14
|
npm install --global @hifullmoon/aicommit@latest
|
|
15
15
|
|
|
16
16
|
# pin or roll back / 固定或回滚
|
|
17
17
|
npm install --global @hifullmoon/aicommit@1.4.0
|
|
18
|
+
|
|
19
|
+
aicommit --version
|
|
18
20
|
```
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
发布工作流使用 npm Trusted Publishing,不保存长期 `NPM_TOKEN`。来自公开 GitHub 仓库的 OIDC 发布会自动携带 npm provenance。可使用当前 npm CLI 检查 registry signature 与 provenance:
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
The release workflow uses npm Trusted Publishing without a long-lived `NPM_TOKEN`. OIDC publishing from the public GitHub repository automatically includes npm provenance. Verify registry signatures and provenance with a current npm CLI:
|
|
23
25
|
|
|
24
26
|
```bash
|
|
25
27
|
workdir=$(mktemp -d)
|
|
26
28
|
cd "$workdir"
|
|
27
|
-
npm install --package-lock-only @hifullmoon/aicommit@1.
|
|
29
|
+
npm install --package-lock-only @hifullmoon/aicommit@1.5.1
|
|
28
30
|
npm audit signatures
|
|
29
31
|
```
|
|
30
32
|
|
|
31
33
|
## Homebrew
|
|
32
34
|
|
|
33
|
-
The main repository is a tap, so no separate tap repository or install script is trusted:
|
|
34
|
-
|
|
35
|
-
主仓库本身就是 tap,无需信任额外 tap 仓库或安装脚本:
|
|
36
|
-
|
|
37
35
|
```bash
|
|
36
|
+
# install / 安装
|
|
38
37
|
brew tap hi-fullmoon/aicommit https://github.com/hi-fullmoon/AICommit.git
|
|
39
38
|
brew install hi-fullmoon/aicommit/aicommit
|
|
40
|
-
aicommit --version
|
|
41
39
|
|
|
42
40
|
# upgrade / 升级
|
|
43
41
|
brew update
|
|
@@ -48,57 +46,31 @@ brew uninstall aicommit
|
|
|
48
46
|
brew untap hi-fullmoon/aicommit
|
|
49
47
|
```
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Formula 依赖 Homebrew 的 Node 包,使用 Homebrew 标准 npm 参数安装,并测试 `--version`、`--help`、无凭据配置校验和 Fish completion。Pull request 会针对本地打包 tarball 执行真实 `brew install`;发布工作流还会针对 registry 已发布 tarball 再跑一次 smoke。
|
|
49
|
+
Formula 依赖 Homebrew 的 Node package,使用 Homebrew 标准 npm 安装参数,并测试 `--version`、`--help` 与无凭据配置校验。每次 npm 发布完成后,release workflow 会从公开 registry 再执行一次真实安装测试。
|
|
54
50
|
|
|
55
|
-
|
|
51
|
+
The formula depends on Homebrew's Node package, uses Homebrew's standard npm installation arguments, and tests `--version`, `--help`, and credential-free configuration validation. After every npm publish, the release workflow performs a real install from the public registry.
|
|
56
52
|
|
|
57
|
-
|
|
53
|
+
## Integrity / 完整性
|
|
58
54
|
|
|
59
|
-
|
|
55
|
+
`Formula/aicommit.rb` 中的 `sha256` 必须与对应 npm tarball 一致。维护者发布前通过 `scripts/release-assets.mjs` 生成 formula,工作流发布前会再次比较生成结果与已提交文件。
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
- `aicommit.rb` — the versioned Homebrew formula / 固定版本的 Homebrew formula;
|
|
63
|
-
- `aicommit-X.Y.Z.spdx.json` — SPDX SBOM;
|
|
64
|
-
- `SHA256SUMS` — hashes for the tarball, formula, and SBOM;
|
|
65
|
-
- `*.sigstore.json` — GitHub OIDC/Sigstore provenance and SBOM bundles.
|
|
57
|
+
The `sha256` in `Formula/aicommit.rb` must match the corresponding npm tarball. Maintainers generate the formula with `scripts/release-assets.mjs`, and the release workflow compares it again before publishing.
|
|
66
58
|
|
|
67
|
-
|
|
59
|
+
## Rollback / 回滚
|
|
68
60
|
|
|
69
|
-
|
|
61
|
+
npm 用户可以立即固定上一可用版本:
|
|
70
62
|
|
|
71
63
|
```bash
|
|
72
|
-
version
|
|
73
|
-
asset_dir=$(mktemp -d)
|
|
74
|
-
gh release download "$version" -R hi-fullmoon/AICommit -D "$asset_dir"
|
|
75
|
-
cd "$asset_dir"
|
|
76
|
-
shasum -a 256 -c SHA256SUMS
|
|
77
|
-
gh attestation verify "aicommit-${version#v}.tgz" \
|
|
78
|
-
-R hi-fullmoon/AICommit \
|
|
79
|
-
--signer-workflow hi-fullmoon/AICommit/.github/workflows/release.yml
|
|
64
|
+
npm install --global @hifullmoon/aicommit@<last-good-version>
|
|
80
65
|
```
|
|
81
66
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Attestation 证明来源与完整性,不代表代码不存在漏洞。安装前仍应审查其关联 commit、workflow 与安全说明。
|
|
85
|
-
|
|
86
|
-
## Release and rollback / 发布与回滚
|
|
87
|
-
|
|
88
|
-
Maintainers execute the complete checklist in [`RELEASING.md`](../RELEASING.md). Public tags and attestations are immutable: never move a published tag or replace a published version.
|
|
89
|
-
|
|
90
|
-
维护者按 [`RELEASING.md`](../RELEASING.md) 执行完整清单。公开 tag 与 attestation 不可变:不得移动已发布 tag,也不得覆盖已发布版本。
|
|
91
|
-
|
|
92
|
-
For an affected npm version, deprecate it and publish a fixed patch. Users can immediately pin the preceding version. For Homebrew, revert the formula in a new commit or download the older release's attested `aicommit.rb`, uninstall the current formula, and install that local file:
|
|
93
|
-
|
|
94
|
-
若 npm 版本有问题,应 deprecate 并发布修复 patch;用户可立即固定上一版本。Homebrew 应通过新 commit 回退 formula,或下载旧 release 中已证明的 `aicommit.rb`,卸载当前版本后从本地文件安装:
|
|
67
|
+
Homebrew 用户可从旧 tag 取出 formula 并本地安装:
|
|
95
68
|
|
|
96
69
|
```bash
|
|
97
|
-
|
|
70
|
+
git clone https://github.com/hi-fullmoon/AICommit.git /tmp/aicommit-rollback
|
|
71
|
+
git -C /tmp/aicommit-rollback show v1.4.0:Formula/aicommit.rb > /tmp/aicommit.rb
|
|
98
72
|
brew uninstall aicommit
|
|
99
|
-
brew install --formula /tmp/aicommit
|
|
73
|
+
brew install --formula /tmp/aicommit.rb
|
|
100
74
|
```
|
|
101
75
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Provider preset 回滚不依赖核心包版本:执行 `aicommit preset rollback`,再运行 `aicommit preset show` 和 `aicommit doctor`。详见 [`provider-presets.md`](provider-presets.md)。
|
|
76
|
+
已发布的 npm version 不应覆盖或复用。维护者应 deprecate 有问题的版本、恢复正确的 dist-tag,并发布修复 patch。完整流程见 [`RELEASING.md`](../RELEASING.md)。
|
package/docs/troubleshooting.md
CHANGED
|
@@ -29,7 +29,7 @@ JSON 模式保证 stdout 只有一个机器对象,诊断进入 stderr。`error
|
|
|
29
29
|
| Preset install/rollback fails / preset 安装或回滚失败 | `config` / `2` | Schema/core range/adapter contract mismatch or no valid backup / schema、核心范围、adapter contract 不匹配或无备份 | `aicommit preset validate --file=...`; `aicommit preset show`; follow the compatibility guide |
|
|
30
30
|
| Extension requires Node 20+ / 扩展要求 Node 20+ | `config` / `2` | Node 18 intentionally has no executable-extension fallback / Node 18 有意不降级运行扩展 | Upgrade Node for extensions or remove user manifest entries; core CLI still supports Node 18 |
|
|
31
31
|
| Extension timeout or permission error / 扩展超时或权限错误 | warning or `response_format` | Extension exceeded its limit or tried denied filesystem/process access / 扩展超时或访问被拒资源 | Review the extension, keep it single-file, raise `extensions.timeoutMs` cautiously; validator failures are fail-closed |
|
|
32
|
-
| `brew install` checksum mismatch / Homebrew checksum 不一致 | Homebrew failure | Formula and registry tarball differ, stale tap, or tampered download / formula 与 tarball 不同、tap 过旧或下载被篡改 | `brew update`; compare
|
|
32
|
+
| `brew install` checksum mismatch / Homebrew checksum 不一致 | Homebrew failure | Formula and registry tarball differ, stale tap, or tampered download / formula 与 tarball 不同、tap 过旧或下载被篡改 | `brew update`; compare `Formula/aicommit.rb` with the npm tarball; do not use `--force` to bypass integrity |
|
|
33
33
|
| npm provenance is absent or invalid / npm provenance 缺失或失败 | npm audit failure | Old npm CLI, non-trusted release, or wrong version / npm 过旧、非可信发布或版本错误 | Upgrade npm; run `npm audit signatures`; install only a version linked to the official workflow |
|
|
34
34
|
|
|
35
35
|
If a failure remains, capture `aicommit doctor --output=json`, Node/Git versions, the error category, and redacted config sources. Never attach a diff, commit message, config file, API key, reasoning trace, extension source containing secrets, or credential-helper output to a public issue.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hifullmoon/aicommit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "Safe, local-first AI commit message generator for Git workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"README.md",
|
|
14
14
|
"SECURITY.md",
|
|
15
15
|
"bin/",
|
|
16
|
-
"docs
|
|
16
|
+
"docs/*.md",
|
|
17
|
+
"docs/examples/",
|
|
17
18
|
"presets/",
|
|
18
19
|
"schemas/",
|
|
19
20
|
"templates/",
|
|
@@ -29,9 +30,9 @@
|
|
|
29
30
|
"eval": "node eval/run.mjs",
|
|
30
31
|
"test:package": "node scripts/package-smoke.mjs",
|
|
31
32
|
"test:homebrew": "node scripts/homebrew-smoke.mjs",
|
|
33
|
+
"docs:terminal-demo": "node scripts/readme-terminal-demo.mjs",
|
|
32
34
|
"release:assets": "node scripts/release-assets.mjs",
|
|
33
|
-
"release:npm:check": "node scripts/
|
|
34
|
-
"release:npm:publish": "node scripts/publish-npm-org.mjs --publish",
|
|
35
|
+
"release:npm:check": "node scripts/verify-release.mjs && npm run ci && npm run test:package && npm pack --dry-run",
|
|
35
36
|
"ci": "npm run lint && npm run format:check && npm run eval && npm run coverage"
|
|
36
37
|
},
|
|
37
38
|
"c8": {
|
package/src/cli.js
CHANGED
|
@@ -18,7 +18,7 @@ function showHelp() {
|
|
|
18
18
|
${chalk.dim('$')} aicommit policy <template|check> [options]
|
|
19
19
|
${chalk.dim('$')} aicommit preset <show|validate|path|install|rollback> [options]
|
|
20
20
|
${chalk.dim('$')} aicommit completion <bash|zsh|fish>
|
|
21
|
-
${chalk.dim('$')} aicommit split
|
|
21
|
+
${chalk.dim('$')} aicommit split [run|plan|apply|resume|abort] [options]
|
|
22
22
|
|
|
23
23
|
${chalk.bold('Commands:')}
|
|
24
24
|
setup Interactive configuration wizard
|
|
@@ -30,7 +30,7 @@ function showHelp() {
|
|
|
30
30
|
policy check Validate a message file or Git range with the effective team policy
|
|
31
31
|
preset Inspect, validate, install, or roll back provider preset manifests
|
|
32
32
|
completion Generate Bash, Zsh, or Fish completion on stdout
|
|
33
|
-
split run
|
|
33
|
+
split, split run Plan and create logical commits
|
|
34
34
|
split plan Generate and export a fingerprinted JSON plan
|
|
35
35
|
split apply Validate and apply an exported JSON plan
|
|
36
36
|
split resume Resume the repository's unfinished transaction
|
|
@@ -46,7 +46,7 @@ function showHelp() {
|
|
|
46
46
|
-l, --lang=<zh|en> Commit message language (default: zh)
|
|
47
47
|
-p, --provider=<name> Use the named provider from config "providers"
|
|
48
48
|
--split-hunks Experimental same-file hunk planning (default: off)
|
|
49
|
-
--scope=<scope> Scope for "split
|
|
49
|
+
--scope=<scope> Scope for "split|split plan": staged, all
|
|
50
50
|
--file=<path> Split-plan artifact or commit-message file
|
|
51
51
|
--range=<revision> Git revision/range for "policy check" (default: HEAD)
|
|
52
52
|
--reasoning=<level> Set reasoning effort (enabled by default: medium)
|
|
@@ -73,10 +73,10 @@ function showHelp() {
|
|
|
73
73
|
aicommit Commit changes in current directory (Chinese)
|
|
74
74
|
aicommit --lang=en Generate English commit message
|
|
75
75
|
aicommit -p deepseek Switch to the "deepseek" provider from config
|
|
76
|
-
aicommit split
|
|
77
|
-
aicommit split
|
|
78
|
-
aicommit split
|
|
79
|
-
aicommit split
|
|
76
|
+
aicommit split Choose staged/all scope, then plan logical commits
|
|
77
|
+
aicommit split --scope=staged Split only the reviewed index snapshot
|
|
78
|
+
aicommit split --scope=all --yes Split the complete working tree non-interactively
|
|
79
|
+
aicommit split --scope=staged --split-hunks Split eligible text hunks
|
|
80
80
|
aicommit split plan --scope=staged --file=.aicommit-plan.json --yes
|
|
81
81
|
aicommit split apply --file=.aicommit-plan.json --yes
|
|
82
82
|
aicommit split resume --yes Resume pending groups from the checkpoint
|
|
@@ -203,14 +203,23 @@ export function parseArgs(args = process.argv.slice(2)) {
|
|
|
203
203
|
|
|
204
204
|
let splitCommand = null;
|
|
205
205
|
if (args[0] === 'split') {
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
const requestedAction = args[1];
|
|
207
|
+
const actions = ['run', 'plan', 'apply', 'resume', 'abort'];
|
|
208
|
+
if (!requestedAction || requestedAction.startsWith('-')) {
|
|
209
|
+
// Keep the common path short: `aicommit split` is the interactive
|
|
210
|
+
// split flow, while explicit actions remain available for automation
|
|
211
|
+
// and recovery.
|
|
212
|
+
splitCommand = 'run';
|
|
213
|
+
args = args.slice(1);
|
|
214
|
+
} else if (actions.includes(requestedAction)) {
|
|
215
|
+
splitCommand = requestedAction;
|
|
216
|
+
args = args.slice(2);
|
|
217
|
+
} else {
|
|
208
218
|
throw fail(
|
|
209
219
|
ERROR_CATEGORIES.CONFIG,
|
|
210
220
|
'split requires one action: run, plan, apply, resume, or abort.',
|
|
211
221
|
);
|
|
212
222
|
}
|
|
213
|
-
args = args.slice(2);
|
|
214
223
|
}
|
|
215
224
|
|
|
216
225
|
const doctor = args[0] === 'doctor';
|
package/src/split.js
CHANGED
|
@@ -101,12 +101,19 @@ function pathIsWithin(parent, candidate) {
|
|
|
101
101
|
return rel === '' || (rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
function canonicalExistingPath(path) {
|
|
105
|
+
// On Windows the native implementation expands 8.3 aliases such as
|
|
106
|
+
// RUNNER~1 consistently. The JS fallback can preserve whichever spelling
|
|
107
|
+
// it received, causing two paths to the same directory to compare unequal.
|
|
108
|
+
return realpathSync.native(path);
|
|
109
|
+
}
|
|
110
|
+
|
|
104
111
|
function canonicalDestination(path) {
|
|
105
112
|
let cursor = resolve(path);
|
|
106
113
|
const suffix = [];
|
|
107
114
|
while (true) {
|
|
108
115
|
try {
|
|
109
|
-
return join(
|
|
116
|
+
return join(canonicalExistingPath(cursor), ...suffix);
|
|
110
117
|
} catch {
|
|
111
118
|
const parent = dirname(cursor);
|
|
112
119
|
if (parent === cursor) return resolve(path);
|
|
@@ -120,7 +127,7 @@ function safeExportPlanPath(projectRoot, path) {
|
|
|
120
127
|
const absolute = resolve(path);
|
|
121
128
|
const rawGitDir = readGit(['rev-parse', '--git-dir'], projectRoot).trim();
|
|
122
129
|
const gitDir = isAbsolute(rawGitDir) ? rawGitDir : resolve(projectRoot, rawGitDir);
|
|
123
|
-
const canonicalRoot =
|
|
130
|
+
const canonicalRoot = canonicalExistingPath(projectRoot);
|
|
124
131
|
const canonicalGitDir = canonicalDestination(gitDir);
|
|
125
132
|
const canonicalPlan = canonicalDestination(absolute);
|
|
126
133
|
if (pathIsWithin(canonicalRoot, canonicalPlan) && !pathIsWithin(canonicalGitDir, canonicalPlan)) {
|