agents-gitflow-guard 0.0.8 → 0.0.10
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 +8 -4
- package/README.zh.md +8 -4
- package/lib/cli.mjs +1 -1
- package/lib/index.mjs +1 -1
- package/lib/{src-2TtpUFC9.mjs → src-CeEqUVQP.mjs} +10 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,12 +36,16 @@ You define your own branches —
|
|
|
36
36
|
|
|
37
37
|
## Quick Start — 30 seconds to a guarded repo
|
|
38
38
|
|
|
39
|
-
**Step 1 — install**,
|
|
39
|
+
**Step 1 — install**, then restart DSH (plugins load at process startup):
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
+
# installs the latest release
|
|
42
43
|
dsh plugin --profile web add agents-gitflow-guard
|
|
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.9
|
|
43
46
|
```
|
|
44
47
|
|
|
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).
|
|
45
49
|
**Step 2 — configure**, create `gitflow-guard.config.json` in your **project root**:
|
|
46
50
|
|
|
47
51
|
```jsonc
|
|
@@ -204,7 +208,7 @@ archive (optional; you archive after release)
|
|
|
204
208
|
| **integration** | `branches.integration` | always | no direct push (default `pr`); features merge in via PR/MR |
|
|
205
209
|
| **preview** | `branches.preview` (array) | optional | no direct push; updates via PR/MR only (env endpoints) |
|
|
206
210
|
| **production** | `branches.production` (array) | optional | PR/MR only; merge by user only (`mergeBy: "user"`) |
|
|
207
|
-
| **archive** | `branches.archive` (array) | optional |
|
|
211
|
+
| **archive** | `branches.archive` (array) | optional | archive PR/MR may be created by agents; the merge stays user-hand only |
|
|
208
212
|
|
|
209
213
|
### Customizing branch names & rules — any naming works
|
|
210
214
|
|
|
@@ -274,7 +278,7 @@ archive (optional; you archive after release)
|
|
|
274
278
|
| direct push / force-push / delete integration / preview / production / archive | 🚫 block (integration/preview `flexible` direct push allowed) |
|
|
275
279
|
| PR/MR: feature → integration / preview | ✅ allow |
|
|
276
280
|
| PR/MR: feature → production | ✅ allow to create; **merge blocked** (you merge in UI) |
|
|
277
|
-
| PR/MR
|
|
281
|
+
| PR/MR into archive | ✅ create allowed; 🚫 merge blocked (you merge in UI) |
|
|
278
282
|
| local `git merge feature/x` while on integration / preview | 🚫 block (PR/MR required); `update: flexible` allows |
|
|
279
283
|
| chained commands (`checkout develop && merge feature/x`) | 🚫 blocked — branch switches are simulated per segment, no bypass |
|
|
280
284
|
|
|
@@ -295,7 +299,7 @@ The PR/MR target is resolved via `gh pr view` (GitHub) or `glab mr view` (GitLab
|
|
|
295
299
|
**From the npm registry** — the standard path, already covered in [Quick Start](#quick-start--30-seconds-to-a-guarded-repo):
|
|
296
300
|
|
|
297
301
|
```bash
|
|
298
|
-
dsh plugin --profile web add agents-gitflow-guard
|
|
302
|
+
dsh plugin --profile web add agents-gitflow-guard@0.0.9 # pin recommended, see note above
|
|
299
303
|
```
|
|
300
304
|
|
|
301
305
|
Then restart DSH. Upgrades are the same command, followed by another restart.
|
package/README.zh.md
CHANGED
|
@@ -35,12 +35,16 @@
|
|
|
35
35
|
|
|
36
36
|
## 快速开始——30 秒用上
|
|
37
37
|
|
|
38
|
-
**第 1
|
|
38
|
+
**第 1 步——安装**,然后重启 DSH(插件在进程启动时加载):
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
+
# 安装最新版
|
|
41
42
|
dsh plugin --profile web add agents-gitflow-guard
|
|
43
|
+
# ...或锁定已知良好版本(推荐; 同时绕开 registry 陈旧缓存)
|
|
44
|
+
dsh plugin --profile web add agents-gitflow-guard@0.0.9
|
|
42
45
|
```
|
|
43
46
|
|
|
47
|
+
> **版本坑**: 裸 `add` 装的是安装时刻的 `latest`——在 npm/pnpm 注册表缓存或镜像陈旧的机器上可能拿到旧版本。看到版本不对就锁版本。pnpm 打印的 peer 依赖 *警告* 属预期: DSH 启动时经共享模块回退提供 `@deepseek-ai/cordis` / `@deepseek-ai/dsh-tools`(插件正常工作)。
|
|
44
48
|
**第 2 步——配置**,在**项目根目录**创建 `gitflow-guard.config.json`:
|
|
45
49
|
|
|
46
50
|
```jsonc
|
|
@@ -201,7 +205,7 @@ archive(可选, 发布后你亲手归档)
|
|
|
201
205
|
| **integration** | `branches.integration` | 必填 | 禁直推(默认 `pr`);feature 只经 PR/MR 合入 |
|
|
202
206
|
| **preview** | `branches.preview`(数组) | 可选 | 禁直推;只走 PR/MR(环境终点) |
|
|
203
207
|
| **production** | `branches.production`(数组) | 可选 | 只走 PR/MR;合并仅限你(`mergeBy: "user"`) |
|
|
204
|
-
| **archive** | `branches.archive`(数组) | 可选 |
|
|
208
|
+
| **archive** | `branches.archive`(数组) | 可选 | 允许 agent 创建指向它的 PR/MR; 合并仍限用户亲手 |
|
|
205
209
|
|
|
206
210
|
### 自定义分支名与规则——任何命名都可以
|
|
207
211
|
|
|
@@ -292,7 +296,7 @@ PR/MR 目标通过 `gh pr view`(GitHub)或 `glab mr view`(GitLab)解析;没有
|
|
|
292
296
|
**从 npm registry**——标准路径,已在[快速开始](#快速开始30-秒用上)覆盖:
|
|
293
297
|
|
|
294
298
|
```bash
|
|
295
|
-
dsh plugin --profile web add agents-gitflow-guard
|
|
299
|
+
dsh plugin --profile web add agents-gitflow-guard@0.0.9 # 建议锁版本, 见上文提示
|
|
296
300
|
```
|
|
297
301
|
|
|
298
302
|
然后重启 DSH。升级用同一命令,再重启一次。
|
|
@@ -438,7 +442,7 @@ MIT,免费,无条件。随便用、随便改、随便发,唯一义务是保留
|
|
|
438
442
|
| **integration** | 集成分支,唯一必填角色(`branches.integration`);feature 经 PR/MR 合入;受保护 |
|
|
439
443
|
| **preview** | 可选环境终点分支(`branches.preview`,数组);只走 PR/MR 更新 |
|
|
440
444
|
| **production** | 可选生产分支(`branches.production`,数组);PR/MR + 合并仅限用户 |
|
|
441
|
-
| **archive** |
|
|
445
|
+
| **archive** | `branches.archive`(数组) | 可选 | 允许 agent 创建指向它的 PR/MR; 合并仍限用户亲手 |
|
|
442
446
|
| **feature 分支** | 你的工作分支,由 `featurePattern` 识别;自由区 |
|
|
443
447
|
| **门禁矩阵** | 把每条被分类的命令映射为放行/拦截的判定表 |
|
|
444
448
|
| **pre-execute** | 工具管线中拦截发生的钩子——在命令运行之前 |
|
package/lib/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as findRepoRoot, d as resolveLocale, f as loadConfig, i as formatDeny, l as gitRunner, m as classify, o as stateDir, p as roleMatches, r as evaluateCommand, s as currentBranch, u as makeT } from "./src-
|
|
1
|
+
import { c as findRepoRoot, d as resolveLocale, f as loadConfig, i as formatDeny, l as gitRunner, m as classify, o as stateDir, p as roleMatches, r as evaluateCommand, s as currentBranch, u as makeT } from "./src-CeEqUVQP.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.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as name, i as formatDeny, n as apply, o as stateDir, r as evaluateCommand, t as appendAudit } from "./src-
|
|
1
|
+
import { a as name, i as formatDeny, n as apply, o as stateDir, r as evaluateCommand, t as appendAudit } from "./src-CeEqUVQP.mjs";
|
|
2
2
|
export { appendAudit, apply, evaluateCommand, formatDeny, name, stateDir };
|
|
@@ -97,6 +97,7 @@ function parsePush(args, ctx) {
|
|
|
97
97
|
for (const a of args) if (a === "-f" || a === "--force" || a === "--force-with-lease" || a.startsWith("--force-with-lease=")) force = true;
|
|
98
98
|
else if (a === "--delete" || a === "-d") isDelete = true;
|
|
99
99
|
else if (a === "--all" || a === "--mirror") all = true;
|
|
100
|
+
else if (a === "--tags") return [{ kind: "other" }];
|
|
100
101
|
else if (a.startsWith("-")) {} else nonFlag.push(a);
|
|
101
102
|
if (all) return [{
|
|
102
103
|
kind: "push",
|
|
@@ -113,10 +114,15 @@ function parsePush(args, ctx) {
|
|
|
113
114
|
delete: false
|
|
114
115
|
}];
|
|
115
116
|
return refspecs.map((ref) => {
|
|
117
|
+
let refForce = force;
|
|
118
|
+
if (ref.startsWith("+")) {
|
|
119
|
+
refForce = true;
|
|
120
|
+
ref = ref.slice(1);
|
|
121
|
+
}
|
|
116
122
|
if (ref.startsWith(":")) return {
|
|
117
123
|
kind: "push",
|
|
118
124
|
dst: stripRefPrefix(ref.slice(1)) || null,
|
|
119
|
-
force,
|
|
125
|
+
force: refForce,
|
|
120
126
|
delete: true
|
|
121
127
|
};
|
|
122
128
|
const colon = ref.indexOf(":");
|
|
@@ -126,20 +132,20 @@ function parsePush(args, ctx) {
|
|
|
126
132
|
return {
|
|
127
133
|
kind: "push",
|
|
128
134
|
dst: dst ? stripRefPrefix(dst) : null,
|
|
129
|
-
force,
|
|
135
|
+
force: refForce,
|
|
130
136
|
delete: deleteTarget || isDelete
|
|
131
137
|
};
|
|
132
138
|
}
|
|
133
139
|
if (ref === "HEAD") return {
|
|
134
140
|
kind: "push",
|
|
135
141
|
dst: ctx.currentBranch ?? null,
|
|
136
|
-
force,
|
|
142
|
+
force: refForce,
|
|
137
143
|
delete: isDelete
|
|
138
144
|
};
|
|
139
145
|
return {
|
|
140
146
|
kind: "push",
|
|
141
147
|
dst: stripRefPrefix(ref),
|
|
142
|
-
force,
|
|
148
|
+
force: refForce,
|
|
143
149
|
delete: isDelete
|
|
144
150
|
};
|
|
145
151
|
});
|
|
@@ -379,8 +385,6 @@ const en = {
|
|
|
379
385
|
"mergeFeature.next": (v) => `Push the feature branch first, then open a PR/MR into ${v.branch}.`,
|
|
380
386
|
"prCreateNoTarget.why": () => "Cannot determine the PR/MR target branch",
|
|
381
387
|
"prCreateNoTarget.next": (v) => `Specify --base/--target-branch explicitly (e.g. \`gh pr create --base ${v.base}\`).`,
|
|
382
|
-
"prCreateArchive.why": () => "Archive branches are user-managed; PRs/MRs into them are not allowed",
|
|
383
|
-
"prCreateArchive.next": () => "Do the release/archive yourself in your terminal or UI.",
|
|
384
388
|
"prCreateHead.why": (v) => `Current branch (${v.head}) is not a feature branch, so it cannot be the source of a PR/MR into ${v.role}`,
|
|
385
389
|
"prCreateHead.next": () => "Open the PR/MR into integration/preview/production from a feature/topic branch.",
|
|
386
390
|
"prMergeProduction.why": () => "Merging into production is allowed only by you (click merge)",
|
|
@@ -449,8 +453,6 @@ const zh = {
|
|
|
449
453
|
"mergeFeature.next": (v) => `先推 feature 分支, 再创建指向 ${v.branch} 的 PR/MR`,
|
|
450
454
|
"prCreateNoTarget.why": () => "无法确定 PR/MR 目标分支",
|
|
451
455
|
"prCreateNoTarget.next": (v) => `请显式指定 --base/--target-branch(如 gh pr create --base ${v.base})`,
|
|
452
|
-
"prCreateArchive.why": () => "归档分支(archive)仅用户亲手操作, 不允许创建指向它的 PR/MR",
|
|
453
|
-
"prCreateArchive.next": () => "发布/归档由你自己在终端或 UI 完成",
|
|
454
456
|
"prCreateHead.why": (v) => `当前分支(${v.head})不是 feature 分支, 不能作为指向${v.role}的 PR/MR 源`,
|
|
455
457
|
"prCreateHead.next": () => "请从 feature/topic 分支上创建指向集成/预览/生产分支的 PR/MR",
|
|
456
458
|
"prMergeProduction.why": () => "合入生产(production)分支仅允许用户亲手点合并",
|
|
@@ -598,7 +600,6 @@ function decidePrCreate(c, facts, config, t) {
|
|
|
598
600
|
const targetRole = roleOfBranch(c.target, config);
|
|
599
601
|
const head = facts.currentBranch;
|
|
600
602
|
const headRole = roleOfBranch(head, config);
|
|
601
|
-
if (targetRole === "archive") return deny(t("prCreateArchive.why"), t("prCreateArchive.next"));
|
|
602
603
|
if (targetRole === "integration" || targetRole === "preview" || targetRole === "production") {
|
|
603
604
|
if (headRole !== "feature") return deny(t("prCreateHead.why", {
|
|
604
605
|
head: head ?? t("head.unknown"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agents-gitflow-guard",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
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",
|