agents-gitflow-guard 0.0.13 → 0.0.14
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/README.md +6 -6
- package/README.zh.md +6 -6
- package/lib/cli.mjs +1 -1
- package/lib/index.d.mts +12 -1
- package/lib/index.mjs +2 -2
- package/lib/{src-BHyQJ6hX.mjs → src-C1CZM7Q4.mjs} +36 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ You define your own branches —
|
|
|
42
42
|
# installs the latest release
|
|
43
43
|
dsh plugin --profile web add agents-gitflow-guard
|
|
44
44
|
# ...or pin an exact known-good version (recommended; also bypasses stale registry caches)
|
|
45
|
-
dsh plugin --profile web add agents-gitflow-guard@0.0.
|
|
45
|
+
dsh plugin --profile web add agents-gitflow-guard@0.0.14
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
> **Version gotcha**: a bare `add` resolves whatever `latest` is at install time — on machines behind a stale npm/pnpm registry cache or mirror it may install an old version. If the installed version looks wrong, pin it explicitly. The peer-dependency *warning* pnpm may print is expected: DSH supplies `@deepseek-ai/cordis` / `@deepseek-ai/dsh-tools` through its shared profile module fallback at startup (the plugin works normally).
|
|
@@ -132,7 +132,7 @@ Nobody has to remember the rules — the rules are enforced.
|
|
|
132
132
|
- **Role-driven, fully configurable**: `integration` is the only required role; `preview` / `production` / `archive` are optional arrays of branch names or regexes, each with its own update rules (`pr` / `flexible`, `mergeBy`).
|
|
133
133
|
- **Merge-by-user where it matters**: production & archive merges stay in your hands — the plugin blocks the agent from clicking merge, so your action *is* the confirmation.
|
|
134
134
|
- **Works with any naming**: branch names are mapped by your config, never hard-coded (see [Configuration](#configuration-reference)).
|
|
135
|
-
- **Fully audited**: every deny is
|
|
135
|
+
- **Fully audited**: every deny is appended to an audit log under your user state directory (`~/.local/state/gitflow-guard/`, `%LOCALAPPDATA%\gitflow-guard` on Windows) — outside the repository, never committed, and outside the agent's writable sandbox.
|
|
136
136
|
- **Platform-agnostic core**: pure local git; optionally consults `gh` (GitHub) or `glab` (GitLab) for PR/MR target resolution, and works fine without them.
|
|
137
137
|
|
|
138
138
|
---
|
|
@@ -168,7 +168,7 @@ Why this matters: branch protection answers *"can this push happen at all?"*; th
|
|
|
168
168
|
|
|
169
169
|
1. An agent calls a shell tool (`pwsh` / `bash`) with a git command.
|
|
170
170
|
2. The plugin classifies the command, resolves the branch roles from `gitflow-guard.config.json`, and applies the gate matrix.
|
|
171
|
-
3. Violation → the tool call is **denied before it runs**, with a reason and the next step. Allowed → the command proceeds; every deny is audited to
|
|
171
|
+
3. Violation → the tool call is **denied before it runs**, with a reason and the next step. Allowed → the command proceeds; every deny is audited to the user-level log (`~/.local/state/gitflow-guard/repos/<repo>-<hash>/audit.jsonl`).
|
|
172
172
|
|
|
173
173
|
No chat-confirmation or permit store: sensitive merges (production / archive) are simply **user-only** — an agent may prepare the PR/MR, but the merge click stays yours.
|
|
174
174
|
|
|
@@ -302,7 +302,7 @@ The PR/MR target is resolved via `gh pr view` (GitHub) or `glab mr view` (GitLab
|
|
|
302
302
|
## Where the human stays in control
|
|
303
303
|
|
|
304
304
|
- **Production merge** and **archive** are user-only by default: an agent may help prepare the PR/MR, but **you click the merge button** — that click *is* the confirmation. There is no separate permit store to outsource that decision.
|
|
305
|
-
- Every deny is
|
|
305
|
+
- Every deny is appended to the user-level audit log for review (`gitflow-guard audit`).
|
|
306
306
|
|
|
307
307
|
---
|
|
308
308
|
## Installation in detail
|
|
@@ -312,7 +312,7 @@ The PR/MR target is resolved via `gh pr view` (GitHub) or `glab mr view` (GitLab
|
|
|
312
312
|
**From the npm registry** — the standard path, already covered in [Quick Start](#quick-start--30-seconds-to-a-guarded-repo):
|
|
313
313
|
|
|
314
314
|
```bash
|
|
315
|
-
dsh plugin --profile web add agents-gitflow-guard@0.0.
|
|
315
|
+
dsh plugin --profile web add agents-gitflow-guard@0.0.14 # pin recommended, see note above
|
|
316
316
|
```
|
|
317
317
|
|
|
318
318
|
Then restart DSH. Upgrades are the same command, followed by another restart.
|
|
@@ -471,7 +471,7 @@ If it saves your team from a shortcut gone wrong, the coffee button at the top o
|
|
|
471
471
|
## Roadmap
|
|
472
472
|
|
|
473
473
|
- **i18n — localized block messages** ✅ (0.0.3): English by default, `"locale": "zh"` for Chinese.
|
|
474
|
-
- **v2 — audit sync**: sync
|
|
474
|
+
- **v2 — audit sync**: sync the user-level audit log across machines (audit is local-only today).
|
|
475
475
|
- **v2 — more pre-built templates**: ready-made config templates for common flows (solo `develop`, multi-env enterprise) as community-contributed presets.
|
|
476
476
|
- **v2 — CI hard-gating research**: whether `pr checks` could become a real gate without hurting the platform-agnostic core.
|
|
477
477
|
|
package/README.zh.md
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
# 安装最新版
|
|
42
42
|
dsh plugin --profile web add agents-gitflow-guard
|
|
43
43
|
# ...或锁定已知良好版本(推荐; 同时绕开 registry 陈旧缓存)
|
|
44
|
-
dsh plugin --profile web add agents-gitflow-guard@0.0.
|
|
44
|
+
dsh plugin --profile web add agents-gitflow-guard@0.0.14
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
> **版本坑**: 裸 `add` 装的是安装时刻的 `latest`——在 npm/pnpm 注册表缓存或镜像陈旧的机器上可能拿到旧版本。看到版本不对就锁版本。pnpm 打印的 peer 依赖 *警告* 属预期: DSH 启动时经共享模块回退提供 `@deepseek-ai/cordis` / `@deepseek-ai/dsh-tools`(插件正常工作)。
|
|
@@ -129,7 +129,7 @@ AI 编码 agent 在你的仓库里工作。它通过系统提示词、项目智
|
|
|
129
129
|
- **角色驱动、完全可配**:`integration` 是唯一必填;`preview` / `production` / `archive` 是可选数组(精确名或正则),每个角色独立 `update`(`pr` / `flexible`)与 `mergeBy`。
|
|
130
130
|
- **在关键处保留人的操作权**:生产与归档合并始终在你手上——插件阻止 agent 点击合并,于是你的动作*就是*确认。
|
|
131
131
|
- **任何命名都行**:分支名全由配置映射,绝无硬编码(见[配置参考](#配置参考))。
|
|
132
|
-
-
|
|
132
|
+
- **全程审计**:每次拦截都追加到用户级状态目录(macOS/Linux `~/.local/state/gitflow-guard/`,Windows `%LOCALAPPDATA%\gitflow-guard`)下的审计日志——在仓库外、绝不进版本库,且位于 agent 可写沙箱之外。
|
|
133
133
|
- **平台无关核心**:纯本地 git;可选调用 `gh`(GitHub)或 `glab`(GitLab)做 PR/MR 目标解析,没有它们照样工作。
|
|
134
134
|
|
|
135
135
|
---
|
|
@@ -165,7 +165,7 @@ AI 编码 agent 在你的仓库里工作。它通过系统提示词、项目智
|
|
|
165
165
|
|
|
166
166
|
1. agent 调用 shell 工具(`pwsh`/`bash`)执行一条 git 命令。
|
|
167
167
|
2. 插件分类该命令,从 `gitflow-guard.config.json` 解析分支角色,套用门禁矩阵。
|
|
168
|
-
3. 违规 → 工具调用在**运行前被拒绝**,附原因和下一步;放行 →
|
|
168
|
+
3. 违规 → 工具调用在**运行前被拒绝**,附原因和下一步;放行 → 命令照常执行,每次拦截都写入用户级日志(`~/.local/state/gitflow-guard/repos/<repo>-<hash>/audit.jsonl`)。
|
|
169
169
|
|
|
170
170
|
没有聊天确认、也没有特许库:敏感合并(生产/归档)就是**仅用户**——agent 可以帮你准备 PR/MR,但点合并的始终是你。
|
|
171
171
|
|
|
@@ -298,7 +298,7 @@ PR/MR 目标通过 `gh pr view`(GitHub)或 `glab mr view`(GitLab)解析;没有
|
|
|
298
298
|
## 人保持控制权的地方
|
|
299
299
|
|
|
300
300
|
- **生产合并与归档**默认仅用户:agent 可以帮你准备 PR/MR,但**合并按钮由你点**——那个点击*就是*确认。没有独立特许库能把这决定外包出去。
|
|
301
|
-
-
|
|
301
|
+
- 每次拦截都追加到用户级审计日志供查阅(`gitflow-guard audit`)。
|
|
302
302
|
|
|
303
303
|
---
|
|
304
304
|
## 安装详解
|
|
@@ -308,7 +308,7 @@ PR/MR 目标通过 `gh pr view`(GitHub)或 `glab mr view`(GitLab)解析;没有
|
|
|
308
308
|
**从 npm registry**——标准路径,已在[快速开始](#快速开始30-秒用上)覆盖:
|
|
309
309
|
|
|
310
310
|
```bash
|
|
311
|
-
dsh plugin --profile web add agents-gitflow-guard@0.0.
|
|
311
|
+
dsh plugin --profile web add agents-gitflow-guard@0.0.14 # 建议锁版本, 见上文提示
|
|
312
312
|
```
|
|
313
313
|
|
|
314
314
|
然后重启 DSH。升级用同一命令,再重启一次。
|
|
@@ -467,7 +467,7 @@ MIT,免费,无条件。随便用、随便改、随便发,唯一义务是保留
|
|
|
467
467
|
## 路线图
|
|
468
468
|
|
|
469
469
|
- **i18n——拦截文案本地化** ✅(0.0.3):默认英文,`"locale": "zh"` 切中文。
|
|
470
|
-
- **v2
|
|
470
|
+
- **v2——审计同步**:跨机器同步用户级审计日志(现仅本地)。
|
|
471
471
|
- **v2——更多预制模板**:常用流程(solo `develop`、多环境企业)的现成配置模板,由社区贡献。
|
|
472
472
|
- **v2——CI 硬门槛研究**:`pr checks` 能否在不伤平台无关核心的前提下变成真实门槛。
|
|
473
473
|
|
package/lib/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as
|
|
1
|
+
import { _ as classify, c as currentBranch, d as loadConfig, f as roleMatches, g as resolveLocale, i as formatDeny, l as findRepoRoot, m as makeT, o as stateDir, r as evaluateCommand, u as gitRunner } from "./src-C1CZM7Q4.mjs";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
//#region src/platform.ts
|
package/lib/index.d.mts
CHANGED
|
@@ -53,6 +53,17 @@ interface AuditEntry {
|
|
|
53
53
|
role?: string;
|
|
54
54
|
reason?: string;
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* 用户级运行时状态根目录(仓库外): macOS/Linux 走 XDG state, Windows 走 %LOCALAPPDATA%。
|
|
58
|
+
* GITFLOW_GUARD_STATE_ROOT 显式覆盖所有平台默认值(测试/特殊部署用)。
|
|
59
|
+
*/
|
|
60
|
+
declare function userStateRoot(): string;
|
|
61
|
+
/**
|
|
62
|
+
* 仓库运行时状态目录(审计流水等), 键为「仓库名-真实路径哈希」。
|
|
63
|
+
* 刻意放在仓库外、且在 agent 文件沙箱(workspace-write)可写区之外:
|
|
64
|
+
* 凡 agent 可写之处的状态都可能被 agent 伪造而自我授权, 存仓库外才堵住这条路;
|
|
65
|
+
* 附带收益: 重克隆/移动 .git 不丢历史。
|
|
66
|
+
*/
|
|
56
67
|
declare function stateDir(repoRoot: string): string;
|
|
57
68
|
/** 审计留痕; 失败不阻断门禁 */
|
|
58
69
|
declare function appendAudit(repoRoot: string, entry: AuditEntry): Promise<void>;
|
|
@@ -61,4 +72,4 @@ declare function evaluateCommand(command: string, opts: EvaluateOptions): Promis
|
|
|
61
72
|
declare function formatDeny(locale: Locale, why: string, next: string): string;
|
|
62
73
|
declare function apply(ctx: Context, pluginConfig?: PluginConfig): void;
|
|
63
74
|
//#endregion
|
|
64
|
-
export { AuditEntry, type Dict, EvaluateOptions, EvaluateResult, MESSAGE_KEYS, PluginConfig, appendAudit, apply, evaluateCommand, formatDeny, name, registerLocale, stateDir };
|
|
75
|
+
export { AuditEntry, type Dict, EvaluateOptions, EvaluateResult, MESSAGE_KEYS, PluginConfig, appendAudit, apply, evaluateCommand, formatDeny, name, registerLocale, stateDir, userStateRoot };
|
package/lib/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as name,
|
|
2
|
-
export { MESSAGE_KEYS, appendAudit, apply, evaluateCommand, formatDeny, name, registerLocale, stateDir };
|
|
1
|
+
import { a as name, h as registerLocale, i as formatDeny, n as apply, o as stateDir, p as MESSAGE_KEYS, r as evaluateCommand, s as userStateRoot, t as appendAudit } from "./src-C1CZM7Q4.mjs";
|
|
2
|
+
export { MESSAGE_KEYS, appendAudit, apply, evaluateCommand, formatDeny, name, registerLocale, stateDir, userStateRoot };
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { appendFile, mkdir, readFile } from "node:fs/promises";
|
|
2
|
-
import {
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { basename, join } from "node:path";
|
|
3
6
|
import { execFile } from "node:child_process";
|
|
4
7
|
//#region src/classify.ts
|
|
5
8
|
/** 拆分命令为多段(&& / || / | / 分号 / 换行), 每段独立分类; 引号内的分隔符不算 */
|
|
@@ -1112,8 +1115,38 @@ function resolvePrTarget(info, config) {
|
|
|
1112
1115
|
//#endregion
|
|
1113
1116
|
//#region src/index.ts
|
|
1114
1117
|
const name = "gitflow-guard";
|
|
1118
|
+
/**
|
|
1119
|
+
* 用户级运行时状态根目录(仓库外): macOS/Linux 走 XDG state, Windows 走 %LOCALAPPDATA%。
|
|
1120
|
+
* GITFLOW_GUARD_STATE_ROOT 显式覆盖所有平台默认值(测试/特殊部署用)。
|
|
1121
|
+
*/
|
|
1122
|
+
function userStateRoot() {
|
|
1123
|
+
const override = process.env.GITFLOW_GUARD_STATE_ROOT?.trim();
|
|
1124
|
+
if (override) return override;
|
|
1125
|
+
if (process.platform === "win32") {
|
|
1126
|
+
const local = process.env.LOCALAPPDATA?.trim() || join(homedir(), "AppData", "Local");
|
|
1127
|
+
return join(local, "gitflow-guard");
|
|
1128
|
+
}
|
|
1129
|
+
const xdg = process.env.XDG_STATE_HOME?.trim();
|
|
1130
|
+
return join(xdg || join(homedir(), ".local", "state"), "gitflow-guard");
|
|
1131
|
+
}
|
|
1132
|
+
function canonicalRepoRoot(repoRoot) {
|
|
1133
|
+
try {
|
|
1134
|
+
return realpathSync(repoRoot);
|
|
1135
|
+
} catch {
|
|
1136
|
+
return repoRoot;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* 仓库运行时状态目录(审计流水等), 键为「仓库名-真实路径哈希」。
|
|
1141
|
+
* 刻意放在仓库外、且在 agent 文件沙箱(workspace-write)可写区之外:
|
|
1142
|
+
* 凡 agent 可写之处的状态都可能被 agent 伪造而自我授权, 存仓库外才堵住这条路;
|
|
1143
|
+
* 附带收益: 重克隆/移动 .git 不丢历史。
|
|
1144
|
+
*/
|
|
1115
1145
|
function stateDir(repoRoot) {
|
|
1116
|
-
|
|
1146
|
+
const real = canonicalRepoRoot(repoRoot);
|
|
1147
|
+
const hash = createHash("sha256").update(real).digest("hex").slice(0, 12);
|
|
1148
|
+
const name = basename(real).replace(/[^\w.-]+/g, "-") || "repo";
|
|
1149
|
+
return join(userStateRoot(), "repos", `${name}-${hash}`);
|
|
1117
1150
|
}
|
|
1118
1151
|
/** 审计留痕; 失败不阻断门禁 */
|
|
1119
1152
|
async function appendAudit(repoRoot, entry) {
|
|
@@ -1242,4 +1275,4 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
1242
1275
|
});
|
|
1243
1276
|
}
|
|
1244
1277
|
//#endregion
|
|
1245
|
-
export { name as a,
|
|
1278
|
+
export { classify as _, name as a, currentBranch as c, loadConfig as d, roleMatches as f, resolveLocale as g, registerLocale as h, formatDeny as i, findRepoRoot as l, makeT as m, apply as n, stateDir as o, MESSAGE_KEYS as p, evaluateCommand as r, userStateRoot as s, appendAudit as t, gitRunner as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agents-gitflow-guard",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "A configurable branch-role guard for AI coding agents (DSH / Claude Code / Codex / OpenCode / Antigravity) — integration/preview/production/archive, each with its own update rules",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|