agents-gitflow-guard 0.0.16 → 0.0.17
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 +20 -7
- package/README.zh.md +20 -7
- package/lib/cli.mjs +1 -1
- package/lib/index.d.mts +44 -1
- package/lib/index.mjs +2 -2
- package/lib/{src-p6q9dCIr.mjs → src-BQYC4N6b.mjs} +48 -1
- package/package.json +6 -2
- package/pi/gitflow-guard.ts +11 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **Are you tired of agents skipping your GitFlow?**
|
|
4
4
|
|
|
5
|
-
A configurable branch-role guard for AI coding agents — [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH), Claude Code, Codex, OpenCode, and
|
|
5
|
+
A configurable branch-role guard for AI coding agents — [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH), Claude Code, Codex, OpenCode, Antigravity, and Pi.
|
|
6
6
|
You define your own branches —
|
|
7
7
|
**integration** (features merge in via PR/MR), **preview** (env endpoints), **production**, **archive** — each with its own update rules. Agents can't skip the flow, and sensitive merges stay in your hands.
|
|
8
8
|
|
|
@@ -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.17
|
|
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).
|
|
@@ -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.17 # pin recommended, see note above
|
|
316
316
|
```
|
|
317
317
|
|
|
318
318
|
Then restart DSH. Upgrades are the same command, followed by another restart.
|
|
@@ -326,7 +326,7 @@ dsh plugin --profile web add file:/path/to/agents-gitflow-guard
|
|
|
326
326
|
|
|
327
327
|
The package declares `dsh.bundle.patch`, so `dsh plugin add` automatically makes it a profile layer — no manual profile editing.
|
|
328
328
|
|
|
329
|
-
**Standalone agent hooks** — the same guard inside those agents, no DSH required. This repo ships project configs at `.claude/settings.json` (Claude Code), `.codex/hooks.json` (Codex), `.opencode/hook/hooks.yaml` (OpenCode)
|
|
329
|
+
**Standalone agent hooks** — the same guard inside those agents, no DSH required. This repo ships project configs at `.claude/settings.json` (Claude Code), `.codex/hooks.json` (Codex), `.opencode/hook/hooks.yaml` (OpenCode), `.agents/hooks.json` (Antigravity / Google) and `.pi/settings.json` + `.pi/extensions/gitflow-guard.ts` (Pi); any other repo adds its own:
|
|
330
330
|
|
|
331
331
|
```jsonc
|
|
332
332
|
// Claude Code — .claude/settings.json
|
|
@@ -371,13 +371,26 @@ hooks:
|
|
|
371
371
|
}
|
|
372
372
|
```
|
|
373
373
|
|
|
374
|
+
```jsonc
|
|
375
|
+
// Pi — .pi/settings.json (extensions resolve relative to .pi)
|
|
376
|
+
{ "extensions": ["extensions/gitflow-guard.ts"] }
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Pi loads extensions in-process (no stdin payload, no subprocess hook). Install the shipped entry point into the project and keep the package in devDependencies:
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
npm i -D agents-gitflow-guard
|
|
383
|
+
mkdir -p .pi/extensions
|
|
384
|
+
cp node_modules/agents-gitflow-guard/pi/gitflow-guard.ts .pi/extensions/gitflow-guard.ts
|
|
385
|
+
```
|
|
386
|
+
|
|
374
387
|
**GitHub Copilot — deliberately no hook here.** Copilot ships its own guardrails for exactly this job: per-tool **allow/deny/ask** permissions and project **rules** (`rules.json` + `AGENTS.md`). Point Copilot users at the official docs instead of a plugin hook:
|
|
375
388
|
|
|
376
389
|
- [Allowing and denying tool use (GitHub Docs)](https://docs.github.com/en/copilot/how-tos/copilot-cli/use-copilot-cli/allowing-tools)
|
|
377
390
|
- [Adding custom rules for the Copilot coding agent (GitHub Docs)](https://docs.github.com/en/copilot/customizing-copilot/adding-custom-rules-for-the-copilot-coding-agent)
|
|
378
391
|
- Optional: Copilot also has a [hooks system](https://docs.github.com/en/copilot/reference/hooks-reference) (`preToolUse` → `permissionDecision:"deny"`) if you want command-level interception.
|
|
379
392
|
|
|
380
|
-
- The hook reads the payload on stdin and answers with that platform's protocol: Claude Code / OpenCode → `exit 2` (stderr is the reason + "next step" hint); Codex → JSON `{"hookSpecificOutput":{"permissionDecision":"deny",...}}` on stdout; Antigravity → JSON `{"decision":"deny","reason":...}` on stdout with `exit 0` (Antigravity requires exit 0 and rejects `hookSpecificOutput` / non-allow values).
|
|
393
|
+
- The hook reads the payload on stdin and answers with that platform's protocol: Claude Code / OpenCode → `exit 2` (stderr is the reason + "next step" hint); Codex → JSON `{"hookSpecificOutput":{"permissionDecision":"deny",...}}` on stdout; Antigravity → JSON `{"decision":"deny","reason":...}` on stdout with `exit 0` (Antigravity requires exit 0 and rejects `hookSpecificOutput` / non-allow values). Pi has no stdin protocol: the in-process extension listens to the official `tool_call` event and denies via its return value `{ block: true, reason }` (the CLI subprocess only speaks the internal exit-2 contract).
|
|
381
394
|
- Only the pre-tool event is needed: the guard blocks *before* the command runs. There is no permit to consume afterwards, so no post-tool hooks are required.
|
|
382
395
|
- Use an **absolute path** to the binary — hook subprocesses may not inherit your shell `PATH`. `${CLAUDE_PROJECT_DIR}/bin/gitflow-guard.mjs` (Claude Code), `node bin/gitflow-guard.mjs` (Codex, runs from the project working directory), or `$OPENCODE_PROJECT_DIR/bin/gitflow-guard.mjs` (OpenCode) or `node bin/gitflow-guard.mjs` (Antigravity, relative to the workspace `.agents/` dir) also work from a checkout.
|
|
383
396
|
- Fully opt-in: the hook does nothing unless the repo has `gitflow-guard.config.json` with `enabled: true`.
|
|
@@ -494,12 +507,12 @@ npm install
|
|
|
494
507
|
npm test # unit tests: classify / gate / config / cli / repo / platform / i18n / index / accuracy-audit
|
|
495
508
|
npm run typecheck # tsc --noEmit, 0 errors
|
|
496
509
|
npm run build # tsdown → lib/ (CLI and plugin share the build)
|
|
497
|
-
npm run verify:matrix # continuous cross-agent regression: DSH logic + zh-locale regression + Claude Code / Codex / OpenCode / Antigravity hook wiring
|
|
510
|
+
npm run verify:matrix # continuous cross-agent regression: DSH logic + zh-locale regression + Claude Code / Codex / OpenCode / Antigravity hook wiring + Pi extension
|
|
498
511
|
```
|
|
499
512
|
|
|
500
513
|
**Rule**: any logic change must pass a 0-error build + all green tests + a green `verify:matrix` before done.
|
|
501
514
|
|
|
502
|
-
**Adding a new agent client** (e.g. Cursor / Windsurf): all of these must change in one commit — `src/platform.ts` (+tests, `HookPlatform` union), a repo hook config beside `.claude/settings.json` / `.codex/hooks.json`, `.agents/hooks/references/<tool>.md`, `scripts/verify-matrix.mjs`, the README hook section and the top tagline, `package.json` description/keywords, and `CHANGELOG`. Done only when `npm run verify:matrix` is green. (Same checklist in [AGENTS.md](AGENTS.md) §8.)
|
|
515
|
+
**Adding a new agent client** (e.g. Cursor / Windsurf): all of these must change in one commit — `src/platform.ts` (+tests, `HookPlatform` union), a repo hook config beside `.claude/settings.json` / `.codex/hooks.json`, `.agents/hooks/references/<tool>.md`, `scripts/verify-matrix.mjs`, the README hook section and the top tagline, `package.json` description/keywords, and `CHANGELOG`. Done only when `npm run verify:matrix` is green. (Same checklist in [AGENTS.md](AGENTS.md) §8; DSH and Pi are in-process clients covered by the exceptions noted there.)
|
|
503
516
|
|
|
504
517
|
---
|
|
505
518
|
|
package/README.zh.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **有没有受够了 agent 跳过你的合入流程?**
|
|
4
4
|
|
|
5
|
-
一个可自由配置分支角色的流程守卫,为 AI 编码 agent 而生——[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)、Claude Code、Codex、OpenCode、Antigravity。
|
|
5
|
+
一个可自由配置分支角色的流程守卫,为 AI 编码 agent 而生——[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)、Claude Code、Codex、OpenCode、Antigravity、Pi。
|
|
6
6
|
你自己定义分支——**集成分支**(feature 经 PR/MR 合入)、**预览分支**(环境终点)、**生产分支**、**归档分支**——每个角色各自配规则。agent 无法跳过流程,敏感合并始终留在你手上。
|
|
7
7
|
|
|
8
8
|
[English](README.md) · [许可证](LICENSE)
|
|
@@ -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.17
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
> **版本坑**: 裸 `add` 装的是安装时刻的 `latest`——在 npm/pnpm 注册表缓存或镜像陈旧的机器上可能拿到旧版本。看到版本不对就锁版本。pnpm 打印的 peer 依赖 *警告* 属预期: DSH 启动时经共享模块回退提供 `@deepseek-ai/cordis` / `@deepseek-ai/dsh-tools`(插件正常工作)。
|
|
@@ -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.17 # 建议锁版本, 见上文提示
|
|
312
312
|
```
|
|
313
313
|
|
|
314
314
|
然后重启 DSH。升级用同一命令,再重启一次。
|
|
@@ -322,7 +322,7 @@ dsh plugin --profile web add file:/path/to/agents-gitflow-guard
|
|
|
322
322
|
|
|
323
323
|
包自带 `dsh.bundle.patch` 声明,`dsh plugin add` 自动把它挂为 profile 层,无需手工编辑 profile。
|
|
324
324
|
|
|
325
|
-
**各 agent 独立 hook**——同一守卫也能在这些 agent 里跑,不依赖 DSH。本仓库已自带 `.claude/settings.json`(Claude Code)、`.codex/hooks.json`(Codex)、`.opencode/hook/hooks.yaml`(OpenCode)
|
|
325
|
+
**各 agent 独立 hook**——同一守卫也能在这些 agent 里跑,不依赖 DSH。本仓库已自带 `.claude/settings.json`(Claude Code)、`.codex/hooks.json`(Codex)、`.opencode/hook/hooks.yaml`(OpenCode)、`.agents/hooks.json`(Antigravity / Google)和 `.pi/settings.json` + `.pi/extensions/gitflow-guard.ts`(Pi);其他仓库加自己的 hooks:
|
|
326
326
|
|
|
327
327
|
```jsonc
|
|
328
328
|
// Claude Code — .claude/settings.json
|
|
@@ -367,13 +367,26 @@ hooks:
|
|
|
367
367
|
}
|
|
368
368
|
```
|
|
369
369
|
|
|
370
|
+
```jsonc
|
|
371
|
+
// Pi — .pi/settings.json(extensions 路径相对 .pi 解析)
|
|
372
|
+
{ "extensions": ["extensions/gitflow-guard.ts"] }
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Pi 以进程内扩展装载(没有 stdin payload,也没有子进程 hook)。把随包发布的入口装进项目、包留在 devDependencies:
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
npm i -D agents-gitflow-guard
|
|
379
|
+
mkdir -p .pi/extensions
|
|
380
|
+
cp node_modules/agents-gitflow-guard/pi/gitflow-guard.ts .pi/extensions/gitflow-guard.ts
|
|
381
|
+
```
|
|
382
|
+
|
|
370
383
|
**GitHub Copilot —— 故意不提供 hook**。Copilot 自带这套守卫的原生能力: 工具级 **allow/deny/ask** 权限 + 项目 **rules**(`rules.json` + `AGENTS.md`)。对 Copilot 用户,直接引官方文档即可,不需要我们的插件:
|
|
371
384
|
|
|
372
385
|
- [允许和拒绝工具使用(GitHub Docs)](https://docs.github.com/en/copilot/how-tos/copilot-cli/use-copilot-cli/allowing-tools)
|
|
373
386
|
- [为 Copilot coding agent 添加自定义规则(GitHub Docs)](https://docs.github.com/en/copilot/customizing-copilot/adding-custom-rules-for-the-copilot-coding-agent)
|
|
374
387
|
- 可选: Copilot 也有官方 [hooks 系统](https://docs.github.com/en/copilot/reference/hooks-reference)(`preToolUse` → `permissionDecision:"deny"`),想要命令级拦截可以自己接。
|
|
375
388
|
|
|
376
|
-
- hook 读 stdin payload,按**各平台协议**作答:Claude Code / OpenCode → `exit 2`(stderr 展示原因 + "下一步"提示);Codex → stdout 输出 JSON `{"hookSpecificOutput":{"permissionDecision":"deny",...}}`;Antigravity → stdout 输出 `{"decision":"deny","reason":...}` 且 **exit 0**(Antigravity 要求 exit 0,拒绝 hookSpecificOutput/非 allow 值)。
|
|
389
|
+
- hook 读 stdin payload,按**各平台协议**作答:Claude Code / OpenCode → `exit 2`(stderr 展示原因 + "下一步"提示);Codex → stdout 输出 JSON `{"hookSpecificOutput":{"permissionDecision":"deny",...}}`;Antigravity → stdout 输出 `{"decision":"deny","reason":...}` 且 **exit 0**(Antigravity 要求 exit 0,拒绝 hookSpecificOutput/非 allow 值)。Pi 没有 stdin 协议:进程内扩展监听官方 `tool_call` 事件,经返回值 `{ block: true, reason }` 拒绝(守卫 CLI 子进程只承载内部 exit-2 契约)。
|
|
377
390
|
- 只需要**执行前事件**:守卫在命令执行*之前*拦截;没有特许可事后消费,因此无需执行后钩子。
|
|
378
391
|
- 用**绝对路径**指向二进制——hook 子进程不一定继承你的 shell PATH。Claude Code 用 `${CLAUDE_PROJECT_DIR}/bin/gitflow-guard.mjs`,Codex 用 `node bin/gitflow-guard.mjs`,OpenCode 用 `$OPENCODE_PROJECT_DIR/bin/gitflow-guard.mjs`、Antigravity 用 `node bin/gitflow-guard.mjs`(相对 workspace `.agents/` 目录)也可以。
|
|
379
392
|
- 完全 opt-in:仓库没有 `gitflow-guard.config.json`(或 `enabled` 非 true)时 hook 什么都不做。
|
|
@@ -490,12 +503,12 @@ npm install
|
|
|
490
503
|
npm test # 单测: classify / gate / config / cli / repo / platform / i18n / index / accuracy-audit
|
|
491
504
|
npm run typecheck # tsc --noEmit, 0 Error
|
|
492
505
|
npm run build # tsdown → lib/(CLI 与插件共用)
|
|
493
|
-
npm run verify:matrix # 连续复测矩阵: DSH 逻辑 + zh 文案回归 + Claude Code / Codex / OpenCode / Antigravity hook 编码
|
|
506
|
+
npm run verify:matrix # 连续复测矩阵: DSH 逻辑 + zh 文案回归 + Claude Code / Codex / OpenCode / Antigravity hook 编码 + Pi 扩展
|
|
494
507
|
```
|
|
495
508
|
|
|
496
509
|
**铁律**:任何逻辑改动必须 0 Error 构建 + 单测全绿 + 连续复测矩阵(`verify:matrix`)全绿后才算完成。
|
|
497
510
|
|
|
498
|
-
**接入新的 agent 客户端**(如 Cursor / Windsurf):以下各项必须在同一个 commit 内完成——`src/platform.ts`(含测试与 `HookPlatform` 联合类型)、`.claude/settings.json` / `.codex/hooks.json` 旁新增一份仓库级 hook 配置、`.agents/hooks/references/<tool>.md`、`scripts/verify-matrix.mjs`、README 双语 hook 段与开头宣传语、`package.json` 的 description/keywords,以及 `CHANGELOG`。`npm run verify:matrix` 全绿才算完成。(同一清单见 [AGENTS.md](AGENTS.md) §8;DSH
|
|
511
|
+
**接入新的 agent 客户端**(如 Cursor / Windsurf):以下各项必须在同一个 commit 内完成——`src/platform.ts`(含测试与 `HookPlatform` 联合类型)、`.claude/settings.json` / `.codex/hooks.json` 旁新增一份仓库级 hook 配置、`.agents/hooks/references/<tool>.md`、`scripts/verify-matrix.mjs`、README 双语 hook 段与开头宣传语、`package.json` 的 description/keywords,以及 `CHANGELOG`。`npm run verify:matrix` 全绿才算完成。(同一清单见 [AGENTS.md](AGENTS.md) §8;DSH 与 Pi 为进程内接入,见该节例外说明。)
|
|
499
512
|
|
|
500
513
|
---
|
|
501
514
|
|
package/lib/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as
|
|
1
|
+
import { _ as resolveLocale, d as gitRunner, f as loadConfig, h as makeT, i as formatDeny, l as currentBranch, o as stateDir, p as roleMatches, r as evaluateCommand, u as findRepoRoot, v as classify } from "./src-BQYC4N6b.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
|
@@ -18,6 +18,49 @@ declare const MESSAGE_KEYS: readonly string[];
|
|
|
18
18
|
*/
|
|
19
19
|
declare function registerLocale(name: string, dict: Dict): void;
|
|
20
20
|
//#endregion
|
|
21
|
+
//#region src/pi.d.ts
|
|
22
|
+
/** Pi 官方 tool_call 事件(只读提取, 与官方 ExtensionAPI 的 ToolCallEvent 对齐) */
|
|
23
|
+
interface PiToolCallEvent {
|
|
24
|
+
toolName: string;
|
|
25
|
+
input?: {
|
|
26
|
+
command?: unknown;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Pi 扩展上下文最小面(官方 ExtensionContext 的 cwd/hasUI 子集) */
|
|
30
|
+
interface PiExtensionContext {
|
|
31
|
+
cwd: string;
|
|
32
|
+
hasUI?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** tool_call 拦截返回值: { block: true, reason } 即拒绝(官方 tool_call 协议) */
|
|
35
|
+
interface PiBlock {
|
|
36
|
+
block: true;
|
|
37
|
+
reason: string;
|
|
38
|
+
}
|
|
39
|
+
type PiToolCallResult = PiBlock | undefined;
|
|
40
|
+
type PiToolCallHandler = (event: PiToolCallEvent, ctx: PiExtensionContext) => Promise<PiToolCallResult> | PiToolCallResult;
|
|
41
|
+
interface PiExtensionAPI {
|
|
42
|
+
on(event: 'tool_call', handler: PiToolCallHandler): void;
|
|
43
|
+
}
|
|
44
|
+
/** 命令执行结果(适配器与守卫 CLI 的进程间契约: 借用 claude 编码 exit 2 + stderr) */
|
|
45
|
+
interface PiRunResult {
|
|
46
|
+
code: number;
|
|
47
|
+
stdout: string;
|
|
48
|
+
stderr: string;
|
|
49
|
+
}
|
|
50
|
+
interface PiExtensionOptions {
|
|
51
|
+
/** 拦截哪些工具的命令文本(默认 bash / powershell, 与 DSH 插件 toolNames 同口径) */
|
|
52
|
+
toolNames?: string[];
|
|
53
|
+
/** 守卫 CLI 可执行(默认 GITFLOW_GUARD_BIN 环境变量 → gitflow-guard); 可为 [node, path] 形式 */
|
|
54
|
+
bin?: string | string[];
|
|
55
|
+
/** 命令执行器(测试注入; 默认真实 execFile) */
|
|
56
|
+
run?: (argv: string[], cwd: string) => Promise<PiRunResult>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 创建 Pi 扩展入口: 返回函数形态与官方扩展默认导出一致(default export (pi) => void)。
|
|
60
|
+
* 监听 tool_call → 提取 bash/powershell 的 command → 守卫 CLI 门禁 → deny 映射为 { block, reason }。
|
|
61
|
+
*/
|
|
62
|
+
declare function createPiExtension(opts?: PiExtensionOptions): (pi: PiExtensionAPI) => void;
|
|
63
|
+
//#endregion
|
|
21
64
|
//#region src/index.d.ts
|
|
22
65
|
declare const name = "gitflow-guard";
|
|
23
66
|
interface PluginConfig {
|
|
@@ -73,4 +116,4 @@ declare function evaluateCommand(command: string, opts: EvaluateOptions): Promis
|
|
|
73
116
|
declare function formatDeny(locale: Locale, why: string, next: string): string;
|
|
74
117
|
declare function apply(ctx: Context, pluginConfig?: PluginConfig): void;
|
|
75
118
|
//#endregion
|
|
76
|
-
export { AuditEntry, type Dict, EvaluateOptions, EvaluateResult, MESSAGE_KEYS, PluginConfig, appendAudit, apply, evaluateCommand, formatDeny, name, registerLocale, stateDir, userStateRoot };
|
|
119
|
+
export { AuditEntry, type Dict, EvaluateOptions, EvaluateResult, MESSAGE_KEYS, type PiExtensionAPI, type PiExtensionContext, type PiExtensionOptions, type PiToolCallEvent, type PiToolCallResult, PluginConfig, appendAudit, apply, createPiExtension, 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, userStateRoot };
|
|
1
|
+
import { a as name, c as createPiExtension, g as registerLocale, i as formatDeny, m as MESSAGE_KEYS, n as apply, o as stateDir, r as evaluateCommand, s as userStateRoot, t as appendAudit } from "./src-BQYC4N6b.mjs";
|
|
2
|
+
export { MESSAGE_KEYS, appendAudit, apply, createPiExtension, evaluateCommand, formatDeny, name, registerLocale, stateDir, userStateRoot };
|
|
@@ -1122,6 +1122,53 @@ function resolvePrTarget(info, config) {
|
|
|
1122
1122
|
};
|
|
1123
1123
|
}
|
|
1124
1124
|
//#endregion
|
|
1125
|
+
//#region src/pi.ts
|
|
1126
|
+
const GITISH = /\b(?:git|gh|glab)\b|gitflow-guard/;
|
|
1127
|
+
function execFileResult(cmd, args, cwd) {
|
|
1128
|
+
return new Promise((resolve) => {
|
|
1129
|
+
execFile(cmd, args, { cwd }, (err, stdout, stderr) => {
|
|
1130
|
+
const e = err;
|
|
1131
|
+
resolve({
|
|
1132
|
+
code: e && typeof e.code === "number" ? e.code : e ? -1 : 0,
|
|
1133
|
+
stdout: String(stdout ?? ""),
|
|
1134
|
+
stderr: String(stderr ?? "")
|
|
1135
|
+
});
|
|
1136
|
+
});
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* 创建 Pi 扩展入口: 返回函数形态与官方扩展默认导出一致(default export (pi) => void)。
|
|
1141
|
+
* 监听 tool_call → 提取 bash/powershell 的 command → 守卫 CLI 门禁 → deny 映射为 { block, reason }。
|
|
1142
|
+
*/
|
|
1143
|
+
function createPiExtension(opts = {}) {
|
|
1144
|
+
const toolNames = new Set(opts.toolNames ?? ["bash", "powershell"]);
|
|
1145
|
+
const bin = opts.bin ?? process.env.GITFLOW_GUARD_BIN ?? "gitflow-guard";
|
|
1146
|
+
const run = opts.run ?? ((argv, cwd) => execFileResult(Array.isArray(bin) ? bin[0] : bin, [...Array.isArray(bin) ? bin.slice(1) : [], ...argv], cwd));
|
|
1147
|
+
return (pi) => {
|
|
1148
|
+
pi.on("tool_call", async (event, ctx) => {
|
|
1149
|
+
try {
|
|
1150
|
+
if (!toolNames.has(event.toolName)) return void 0;
|
|
1151
|
+
const command = typeof event.input?.command === "string" ? event.input.command : "";
|
|
1152
|
+
if (!command || !GITISH.test(command)) return void 0;
|
|
1153
|
+
const res = await run([
|
|
1154
|
+
"check",
|
|
1155
|
+
"--platform",
|
|
1156
|
+
"claude",
|
|
1157
|
+
"--command",
|
|
1158
|
+
command
|
|
1159
|
+
], ctx.cwd);
|
|
1160
|
+
if (res.code === 2) return {
|
|
1161
|
+
block: true,
|
|
1162
|
+
reason: res.stderr.trim() || "blocked by gitflow-guard"
|
|
1163
|
+
};
|
|
1164
|
+
return;
|
|
1165
|
+
} catch {
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
});
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
//#endregion
|
|
1125
1172
|
//#region src/index.ts
|
|
1126
1173
|
const name = "gitflow-guard";
|
|
1127
1174
|
/**
|
|
@@ -1291,4 +1338,4 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
1291
1338
|
});
|
|
1292
1339
|
}
|
|
1293
1340
|
//#endregion
|
|
1294
|
-
export {
|
|
1341
|
+
export { resolveLocale as _, name as a, createPiExtension as c, gitRunner as d, loadConfig as f, registerLocale as g, makeT as h, formatDeny as i, currentBranch as l, MESSAGE_KEYS as m, apply as n, stateDir as o, roleMatches as p, evaluateCommand as r, userStateRoot as s, appendAudit as t, findRepoRoot as u, classify as v };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agents-gitflow-guard",
|
|
3
|
-
"version": "0.0.
|
|
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",
|
|
3
|
+
"version": "0.0.17",
|
|
4
|
+
"description": "A configurable branch-role guard for AI coding agents (DSH / Claude Code / Codex / OpenCode / Antigravity / Pi) — integration/preview/production/archive, each with its own update rules",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"lib",
|
|
19
19
|
"bin",
|
|
20
20
|
"patch.yml",
|
|
21
|
+
"pi",
|
|
21
22
|
"README.md",
|
|
22
23
|
"README.zh.md"
|
|
23
24
|
],
|
|
@@ -32,6 +33,9 @@
|
|
|
32
33
|
"codex",
|
|
33
34
|
"opencode",
|
|
34
35
|
"antigravity",
|
|
36
|
+
"pi",
|
|
37
|
+
"pi-agent",
|
|
38
|
+
"pi-extension",
|
|
35
39
|
"plugin",
|
|
36
40
|
"hook",
|
|
37
41
|
"gitflow",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Pi 扩展入口(随包发布, 可复制): 拦截 bash/powershell 的 git 系命令, 经守卫 CLI 门禁后
|
|
2
|
+
// 以官方 tool_call 协议 { block: true, reason } 拒绝。协议见仓库 .agents/hooks/references/pi.md。
|
|
3
|
+
//
|
|
4
|
+
// 用法(推荐): 复制本文件到 <project>/.pi/extensions/gitflow-guard.ts, 项目 devDependencies
|
|
5
|
+
// 安装 agents-gitflow-guard(jiti 从扩展所在项目解析裸导入); 仓库再配 .pi/settings.json:
|
|
6
|
+
// { "extensions": ["extensions/gitflow-guard.ts"] }
|
|
7
|
+
//
|
|
8
|
+
// 也可以不复制: 手写一行 wrapper 后放任意位置并绝对路径登记进 extensions。
|
|
9
|
+
import { createPiExtension } from 'agents-gitflow-guard'
|
|
10
|
+
|
|
11
|
+
export default createPiExtension()
|