Skip to content

Releases: FeatureAgents/AgentsGitFlowController

v0.1.8

Choose a tag to compare

@github-actions github-actions released this 24 Oct 13:47
91441b1
  • fix(dsh): judge a git command in the directory it actually runs in — the DSH adapter resolved the repository and current branch from the session directory (exec.agent.session.header.cwd) only, so a bash / pwsh call that ran elsewhere was judged against the wrong checkout: from a session rooted on main, git merge develop with workdir set to a feature worktree, cd <worktree> && git merge develop and git -C <worktree> merge develop were refused as "Merging into archive branch(main)", and the reverse (session on a feature worktree, command aimed at the main checkout) was allowed; apply() now starts from the tool's workdir (or cwd) argument, applies leading cd / pushd steps and the gated git command's -C options (new pure resolveSegmentCwds in src/classify.ts, see the next entry for the per-segment rules), and falls back to the session directory's repository when the resolved directory is not inside one; covered by tests/classify.spec.ts and a real-git main checkout + linked worktree suite in tests/index.spec.ts —— DSH 适配层按命令实际运行的目录判定:此前仓库与当前分支只取会话目录(exec.agent.session.header.cwd),在别处运行的 bash / pwsh 调用会按错误的检出判定——会话停在 main 时,workdir 指向 feature worktree 的 git merge develop、cd <worktree> && git merge develop 与 git -C <worktree> merge develop 被误拒为「合并进归档分支 main」,反向(会话在 feature worktree、命令打到 main 检出)则被放行;现 apply() 以工具的 workdir(兼容 cwd)参数为起点,依次应用前导 cd / pushd 与受门禁 git 段的 -C(新增纯函数 src/classify.ts 的 resolveSegmentCwds,逐段规则见下一条),推演出的目录不在任何仓库内时回落到会话目录的仓库;由 tests/classify.spec.ts 与 tests/index.spec.ts 的真实 git 主检出 + linked worktree 用例覆盖。
  • fix(dsh): judge every gated segment in its own directory — the first fix resolved one directory (the first gated git segment's -C) and judged the whole command against it, so a later segment that runs elsewhere was never judged where it really runs: from a session on a feature worktree, git -C <archive checkout> merge develop && git push origin feature/x was allowed, and so were git push origin feature/wt && git -C <archive checkout> merge develop and, from a session on the archive checkout, git -C <worktree> merge develop && git merge develop; a step that cannot be resolved statically (cd $VAR, cd ~, cd -, popd, globs, git -C "$D", a subshell or command group) used to fall back to the starting directory, which let cd $VAR && git merge develop through from a feature worktree; resolveSegmentCwds (replaces resolveCommandCwd) now derives the directory of each gated segment separately (workdir / cwd → leading cd / pushd → that segment's own git -C), and apply() denies the command (audited, in the repository's configured locale, and only when a candidate repository has the guard enabled — otherwise it passes through as before) when the gated segments resolve to different directories or when any gated segment's directory cannot be determined statically, and otherwise judges all of them in the one shared directory; a step that cannot be resolved only matters when a gated segment follows it (git merge develop && cd $VAR is still judged as before). Out of scope, unchanged: cd scoping inside command groups and subshells, directories inside wrappers (env / sudo / sh -c / command / builtin) and nested contexts ($(...), backticks, shell keywords such as then / do), --git-dir / --work-tree / GIT_DIR redirection, allowing different subdirectories of one repository, and unifying the command-line hook channels (tracked separately) —— 受门禁段各自按其实际运行的目录判定:上一条修复只推演一个目录(首个受门禁 git 段的 -C)并拿它判定整条命令,后面在别处运行的段从未按真实目录判定——会话在功能工作树时,git -C <归档检出> merge develop && git push origin feature/x、git push origin feature/wt && git -C <归档检出> merge develop 被放行,会话在归档检出时 git -C <工作树> merge develop && git merge develop 同样被放行;无法静态确定的步骤(cd $VAR、cd ~、cd -、popd、通配符、git -C "$D"、子 shell 与命令组)此前回落到起点目录,使功能工作树会话里的 cd $VAR && git merge develop 被放行;现 resolveSegmentCwds(取代 resolveCommandCwd)为每个受门禁段分别推演目录(workdir / cwd → 前导 cd / pushd → 该段自身的 git -C),apply() 在各受门禁段目录不一致、或任一受门禁段的目录无法静态确定时拒绝整条命令(写审计、按仓库配置的语言出文案,且仅当候选仓库中有启用守卫的仓库时才拒绝,否则与此前一样放行),全部一致时按这一个共同目录判定;无法静态确定的步骤只有其后仍有受门禁段时才触发拒绝(git merge develop && cd $VAR 判定不变)。本次不做、行为不变:命令组与子 shell 内 cd 的作用域推演、包装器(env / sudo / sh -c / command / builtin)内部与嵌套语境($(...)、反引号、then / do 等 shell 关键字)里的目录、--git-dir / --work-tree / GIT_DIR 重定向、同一仓库内不同子目录的跨目录放行、命令行钩子通道的统一(另开议题);由 tests/classify.spec.ts 与 tests/index.spec.ts 的真实 git 主检出 + linked worktree 用例覆盖(双向不一致 / 同目录不误伤 / 无法确定即拒绝)。

v0.1.7

Choose a tag to compare

@github-actions github-actions released this 18 Oct 12:30
98a8dd0
  • fix(cli,docs): use the published package name in npx commands and expose agents-gitflow-guard in package.json#bin — the first-screen demo snippet across all 11 READMEs, cli.demo.wire in src/i18n.ts (en/zh), and docs/assets/demo.svg previously invoked npx gitflow-guard ..., which only worked on machines where the CLI was already on PATH and failed with 404 Not Found from the npm registry on any fresh machine (while leaving the unclaimed gitflow-guard package name open to squatting); package.json#bin now exposes both gitflow-guard and agents-gitflow-guard pointing to bin/gitflow-guard.mjs, every npx command in the 11 READMEs, src/i18n.ts and the regenerated docs/assets/demo.svg now uses npx agents-gitflow-guard ..., and tests/doc-consistency.spec.ts plus tests/cli.spec.ts guard against bare npx gitflow-guard regressions —— 修复 npx 首屏命令使用未注册包名的问题并在 package.json#bin 同步暴露 agents-gitflow-guard:此前 11 语言 README 首屏演示代码、src/i18n.ts(中英双语 cli.demo.wire)与 docs/assets/demo.svg 均写 npx gitflow-guard ...,仅在已全局安装使 gitflow-guard 位于 PATH 的机器上能运行,未安装的新用户执行即报 npm 404 Not Found(且未注册包名 gitflow-guard 存在被第三方抢注的风险);现 package.json#bin 同时暴露 gitflow-guard 与 agents-gitflow-guard 指向 bin/gitflow-guard.mjs,11 语言 README、src/i18n.ts 与重新生成的 docs/assets/demo.svg 统一改为 npx agents-gitflow-guard ...,并由 tests/doc-consistency.spec.ts 与 tests/cli.spec.ts 机械拦截回退。

v0.1.6

Choose a tag to compare

@github-actions github-actions released this 13 Oct 13:46
d08229f
  • test(docs): harden the 11-language README checker — scripts/check-readme-equality.mjs now resolves every TOC anchor against the real headings, requires the TOC order to match the document's H2 order, and requires every H2 to be listed; heading/TOC parsing is one shared, fence-aware, CRLF-tolerant source (collectHeadings / collectTocItems), and the slug model matches github-slugger (no trim, so a heading ending in " ?" keeps its trailing hyphen). The old checker only counted TOC items, so the two real drifts below passed silently —— 11 语 README 校验器加严:scripts/check-readme-equality.mjs 现会校验每个 TOC 锚点都能解析到真实标题、TOC 顺序必须与正文 H2 顺序一致、且每个 H2 必须列入 TOC;标题/TOC 解析合并为唯一事实源(围栏感知、容忍 CRLF),slug 规则对齐 github-slugger(不 trim,标题尾部“空格+标点”保留尾部连字符)。旧校验只数 TOC 条数,下面两处真实漂移因此长期漏检。
  • fix(docs): repair four misleading client links in all 11 READMEs — Pi pointed at a 404 (github.com/mariozechner/pi → pi.dev), ZCode's domain now redirects to an unrelated promo page (zcode.ai → zcode.z.ai, the official site), Antigravity pointed at a GitHub organization page (github.com/google-deepmind → antigravity.google), and OpenCode at its legacy repository (github.com/opencode-ai/opencode → opencode.ai) —— 修正 11 语 README 的四个误导外链:Pi 原本指向 404(github.com/mariozechner/pi → pi.dev);ZCode 原域名已跳转到无关推广页(zcode.ai → 官方站 zcode.z.ai);Antigravity 原本指向 GitHub 组织主页(github.com/google-deepmind → antigravity.google);OpenCode 原本指向旧仓库(github.com/opencode-ai/opencode → opencode.ai)。
  • fix(docs): repair the French TOC anchor and reorder every TOC to document order — #voyez-le-à-loeuvre--une-démo-live-de-30-secondes never resolved (a ligature was missing from the slug), and all 11 TOCs still listed the demo section third although 0.1.2 moved that section to the first screen. Three duplicated paragraphs are dropped at the same time: the wire recap in the hook-mechanism section, the FAQ config-error example that repeats the configuration reference, and the FAQ coffee line that repeats the Support section —— 修复法语 TOC 锚点并让 11 语目录顺序与正文一致:#voyez-le-à-loeuvre--… 因漏字符从未解析成功;11 语目录也都仍把演示段排在第三位,而 0.1.2 已把它移到首屏。同时删除三处重复段落:钩子机制段的 wire 复述、FAQ 里与配置参考重复的配置错误示例、以及 FAQ 里与 Support 段重复的咖啡句。

v0.1.5

Choose a tag to compare

@github-actions github-actions released this 12 Oct 15:22
2c8a1b2
  • fix(pi): start the guard as node <bundled runner> by default — createPiExtension() used to default to the bare gitflow-guard command, which Windows cannot start without a shell (extension-less npm shim or .cmd), so the spawn error was swallowed by the fail-open path and the extension silently stopped guarding (verified on Windows 2026-10-06); resolvePiBin() now returns [process.execPath, resolveRunnerPath()], GITFLOW_GUARD_BIN still overrides it, and the verification matrix asserts the default and runs a real CLI round-trip without injecting bin/run —— Pi 扩展默认执行器改为 node <随包 runner>:此前默认走 PATH 上的 gitflow-guard,而 Windows 不带 shell 无法启动无扩展名 shim 或 .cmd,spawn 失败被降级路径吞掉,守卫静默失效(2026-10-06 Windows 实测);现 resolvePiBin() 返回 [process.execPath, resolveRunnerPath()],GITFLOW_GUARD_BIN 仍可覆盖,复测矩阵改为不注入 bin/run 直接验证默认执行器并实弹跑一次真实 CLI。
  • docs(pi): document user-level wiring — the 11 READMEs, the Pi protocol reference, the wire --client pi guidance and the shipped extension header now describe the user-level install (~/.pi/agent/extensions/ + ~/.pi/agent/settings.json + the package installed inside ~/.pi/agent, PowerShell junction on Windows) and state that no PATH entry or global npm install is needed —— Pi 用户级接线补进文档:11 语言 README、Pi 协议参考、wire --client pi 引导与随包扩展头部说明均补上用户级安装三条(~/.pi/agent/extensions/ + ~/.pi/agent/settings.json + 在 ~/.pi/agent 内安装本包;Windows 用 PowerShell junction),并写明不依赖 PATH 与全局 npm 安装。
  • docs: drop the remaining section signs in source comments and test names (17 occurrences) — the same replacement as 0.1.4, applied to .ts / .mjs comments and the dogfood extension header; the only remaining "§" is the literal one quoted in the 0.1.4 changelog entry itself —— 补清源码注释与测试名里的章节符号(17 处):与 0.1.4 同一替换规则,覆盖 .ts / .mjs 注释与 dogfood 扩展头部;现在唯一剩下的 "§" 是 0.1.4 条目里描述本次清理时引用的那个字面符号。

v0.1.4

Choose a tag to compare

@github-actions github-actions released this 12 Oct 15:03
c343a41
  • docs(agents): add a project scope section (AGENTS.md, section 9) — one place that states what the project does (gate correctness, truthful documentation, real usability of the supported clients including Windows, tests green) and what it explicitly does not do (new client integrations, CI-side hard gating, cross-machine audit synchronization, remote policy fetching, filesystem interception, an MCP interception layer, a Copilot plugin, more README languages), plus a two-question rule for any new capability; docs/design.md section 2 remains the authoritative full text —— AGENTS.md 新增第 9 节「项目范围(做什么 / 不做什么)」:一处写明做什么(门禁正确性、文档如实、已支持客户端含 Windows 的真实可用、测试全绿)与明确不做的事(新客户端接入、CI 侧硬门禁、跨机器审计同步、远程策略拉取、文件系统拦截、MCP 拦截层、Copilot 插件、新增语言文档),并给出新增能力的两问决策规则;权威全文仍是 docs/design.md 第 2 节。
  • docs: replace every "§" section sign with plain references (72 occurrences across AGENTS.md, CHANGELOG.md, the 11 READMEs, docs/design.md, docs/e2e/README.md and five skill files) — English files now say "section N", Chinese files say "第 N 节"; no meaning changed —— 全库清理「§」章节符号(72 处,覆盖 AGENTS.md、CHANGELOG.md、11 个 README、docs/design.md、docs/e2e/README.md 与 5 个技能文件):英文改为 "section N",中文改为「第 N 节」,语义不变。

v0.1.3

Choose a tag to compare

@github-actions github-actions released this 12 Oct 14:57
c26ae5d
  • docs(readme): replace the stale roadmap with an honest scope statement — the Roadmap section no longer lists "new agent integrations", "cross-machine audit aggregation", "workflow presets" or "CI hard-gating" as future work; it now states the project's direction (correctness and real-world validation of the existing gate first) and what it deliberately does not plan (new agent integrations, CI-side hard gating, cross-machine audit synchronization, remote policy fetching), so the public page no longer advertises capabilities the project has decided against —— README 路线图改为诚实的范围声明:不再把"更多 Agent 平台接入 / 跨机器审计汇总 / 场景化流程预设 / CI 硬门禁"列为未来计划,改为写明项目方向(先把现有门禁的正确性与真实验证做好)与明确不计划的事项(新 Agent 平台接入、CI 侧硬门禁、跨机器审计同步、远程策略拉取),公开页面不再宣传已被否决的能力。
  • docs(readme): align the Development section's structure counts with the structure checker (45 headings / 7 tables / 18 TOC items) —— 开发段的结构数字与结构校验器对齐(45 标题 / 7 表格 / 18 TOC 项)。

v0.1.2

Choose a tag to compare

@github-actions github-actions released this 05 Oct 13:45
9264c20
  • docs(readme): move the "See it work — a 30-second live demo" section above the fold — the demo section (animated SVG + one-command reproduction) now sits right after the badges and before the Table of Contents in all 11 language READMEs, instead of after the Why section where it took two screens of scrolling to reach; structure moved verbatim, checker constants unchanged (still 45 headings / 7 tables / 21 code blocks / 18 TOC anchors) —— README demo 段上移到首屏:"看它干活——30 秒真机演示"段(动画 SVG + 一条命令复现)从 Why 段之后移到徽章之下、目录之上,11 语言同步;此前要滚两三屏才能看到,现在打开首页即见;结构原样平移,校验器常量不变(仍为 45 标题 / 7 表格 / 21 代码块 / 18 TOC 锚点)。

v0.1.1

Choose a tag to compare

@github-actions github-actions released this 05 Oct 12:12
826eecf
  • feat(cli): add gitflow-guard demo — a 30-second live demo that builds a throwaway real-git sandbox repo, runs three real scenes through the same evaluateCommand core the agent hooks call (1 allow, 2 denials with the actual why/next), then deletes the sandbox; audit state is redirected inside the sandbox via GITFLOW_GUARD_STATE_ROOT for the run, so nothing is left in the user's home or state directories; --cast <file> emits the run as a JSONL event stream; usage text updated in both locales —— 新增 gitflow-guard demo:30 秒真机演示——在一次性沙箱仓库里用与 agent hook 完全同一的 evaluateCommand 核心跑三个真实场景(1 放行、2 拦截,拦截附真实 why/next),退出即删;演示期间经 GITFLOW_GUARD_STATE_ROOT 把审计状态根指进沙箱,用户主目录与状态目录零残留;--cast <文件> 把本次运行落成 JSONL 事件流;双语文案与 usage 同步更新。
  • feat(demo-svg): add scripts/generate-demo-svg.mjs (dev-only, not shipped) that renders the demo --cast JSONL into a SMIL animated SVG (dark terminal, per-event frames, strict escaping, fails loudly on malformed input); docs/assets/demo.svg is generated from a real demo run and embedded in all 11 READMEs —— 新增 scripts/generate-demo-svg.mjs(仅仓库内工具,不随包发布):把 demo --cast 的 JSONL 渲染成 SMIL 动画 SVG(暗色终端、逐事件成帧、严格转义、坏输入响亮失败);docs/assets/demo.svg 由真实 demo 运行生成,内嵌进全部 11 语言 README。
  • docs(readme): keep claims honest — the intro line and the "Why" section no longer claim agents "can't skip the flow" or call the guard a "hard mechanism"; they now say routine flow violations are blocked before they run with why/next guidance, and that a determined agent can still evade a text-layer guard (linking the existing honest-limits section); a new "See it work — a 30-second live demo" section embeds the generated demo SVG and the one-command reproduction in all 11 languages, with TOC updated (45 headings / 7 tables / 21 code blocks / 18 TOC anchors, checker constants updated accordingly) —— 文档表述诚实化:引言行与 "Why" 段不再宣称 agent "无法跳过流程"、不再称守卫为"硬机制";改为"常规流程违规在执行前被拦截并给出 why/next 引导,存心的 agent 仍可绕过文本层守卫"(链向既有诚实边界段);新增"看它干活——30 秒真机演示"段,内嵌生成的演示 SVG 与一条命令复现,11 语言同步,TOC 更新(45 标题 / 7 表格 / 21 代码块 / 18 TOC 锚点,校验器常量随之更新)。

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 15 Sep 12:56
dfae409
  • chore(release): same as 0.0.50

v0.0.50

Choose a tag to compare

@github-actions github-actions released this 15 Sep 12:31
4e055b5
  • fix(gate): enforce mergeBy consistently across all four roles — PR merge checks previously read mergeBy only on production, denied archive merges unconditionally, and ignored mergeBy on integration/preview entirely; decidePrMerge now reads mergeBy for every role with dedicated i18n guidance, keeping each role's established default (integration/preview = anyone, production/archive = user). Behavior change to note: archive merges are no longer denied unconditionally — they are denied unless the archive role explicitly sets mergeBy: "anyone" —— 四角色统一按 mergeBy 判定:此前 PR 合并检查只对生产分支读取 mergeBy、对归档分支无条件拒绝、对集成分支与预览分支完全忽略该配置;现 decidePrMerge 对四个角色统一读取 mergeBy 并给出对应国际化提示,各角色沿用既有默认(integration/preview = anyone,production/archive = user)。需注意的行为变化:归档分支不再是"一律拒绝",而是"除显式配置 mergeBy: "anyone" 外均拒绝"。
  • fix(config,gate): strictly anchor featurePattern — featurePattern regex previously lacked start/end boundary anchors, allowing spoofed branch names like malicious/feature/foo to pass as valid feature branches; default pattern and pattern matching now enforce strict boundary anchors (^(?:...)$) —— 严格首尾锚定 featurePattern 正则:此前分支角色判断未对 featurePattern 实施首尾锚定,导致带有前缀的伪装分支名(如 malicious/feature/foo)被误判为合法 feature 分支;现默认正则与匹配层均严格约束 ^(?:...)$。
  • fix(platform): identify Cursor payloads when cursor_version is omitted — Cursor beforeShellExecution and top-level { command, cwd } payloads lacking cursor_version were previously misclassified as Claude Code, resulting in exit 2 client crashes instead of structured exit 0 with permission JSON; detectPlatform now inspects top-level command attributes and Cursor hook lifecycle events to reliably identify Cursor and return the standard { permission: "deny", ... } JSON payload —— 完善 Cursor 平台识别机制:部分 Cursor 事件未携带 cursor_version 特征导致被误判为 Claude Code 并返回 exit 2 报错;现通过顶层命令结构与生命周期事件精准识别 Cursor,拦截时严格遵循 exit 0 与结构化 JSON 拒绝协议。
  • fix(wire): preserve JSONC comments and existing hooks during wire and unwire — reading/writing JSON configuration previously discarded comments via standard JSON.parse/JSON.stringify, and unwiring blanket-deleted entire hook matcher blocks; wire now uses comment-json so comments survive a rewrite (the file is re-serialized with a uniform 2-space indent), and filtering is fine-grained: only the guard's own hook entries are removed, while sibling hooks, pre-existing empty entries, and non-object entries are left intact; unwiring antigravity keeps the top-level key whenever user-authored content remains in it, except when the guard command sits outside every event array, in which case the key is removed as a whole (legacy migration semantics) —— 保留 JSONC 注释并实现细粒度 Hook 卸载:接线层引入 comment-json 读写用户配置文件,注释在重写后保留(文件统一以 2 空格缩进重新序列化);卸载只摘除守卫自身的 hook 条目,同 matcher 下的用户自定义 Hook、用户原有的空条目与非对象条目均原样保留;antigravity 卸载时若顶层键内仍有用户自建内容则保留该键,仅当守卫命令落在所有事件数组之外时才整键移除(沿用历史迁移语义)。
  • fix(pi): block instead of failing open when the guard subprocess is timed out — the extension's own 10s subprocess timeout raced the guard's internal 10s git budget and killed it first, so a slow git turned into "allow"; the outer timeout is now 45s (above the guard's worst-case budget), a timeout kill is reported as timedOut and mapped to { block: true }, and killSignal: SIGKILL guarantees the kill cannot be ignored —— Pi 扩展超时改为阻断:此前扩展自身的 10s 子进程超时与守卫内部 10s 的 git 预算同量级且先到,慢 git 会被杀成"放行";现外层超时提高到 45s(高于守卫最坏预算),超时被杀标记为 timedOut 并映射为 { block: true },killSignal: SIGKILL 保证杀进程不可被忽略。
  • fix(repo): guarantee the 5s/10s runner timeouts actually fire — execFile used the default SIGTERM, so a child process ignoring that signal kept the guard hanging forever; the git/gh/glab runners now kill with SIGKILL —— 保证 5s/10s 熔断真正生效:execFile 原先使用默认 SIGTERM,忽略该信号的子进程会让守卫永久挂起;现 git/gh/glab 三个 runner 一律用 SIGKILL 终结。
  • fix(index,cli): keep non-git commands out of the timeout path and audit timeout denials — the DSH plugin probed the repository before knowing whether the command was git-related, so a hung git denied unrelated commands such as npm test, and timeout denials were not recorded at all; the plugin now has the same classify fast path as the CLI, and timeout denials are written to audit.jsonl whenever a repository root is known (a findRepoRoot timeout has no repository to attribute to and is reported on stderr instead) —— DSH 插件此前在判断命令是否 git 相关之前就探测仓库,git 卡死会连带拒绝 npm test 这类无关命令,且超时拒绝不留痕;现插件与 CLI 采用同一 classify 快路径,超时拒绝在能定位到仓库根时写入 audit.jsonl(findRepoRoot 自身超时时没有可归属的仓库,改为在 stderr 报告)。
  • test(matrix): count skipped cases as failures — the decision matrix silently skipped rows whose sandbox branch was missing, so a broken sandbox could shrink coverage without turning the run red; skips are now reported and counted into FAIL —— 矩阵把跳过计为失败:此前沙箱缺分支的行会被静默跳过,沙箱损坏会悄悄缩小覆盖而不变红;现跳过会被报告并计入 FAIL。
  • chore(package): ship third-party notices for bundled code — comment-json, esprima and array-timsort are inlined into lib/, so their licenses now travel with the package (THIRD-PARTY-NOTICES.md) —— 随包附第三方声明:comment-json、esprima、array-timsort 被内联进 lib/,其许可文本随包分发(THIRD-PARTY-NOTICES.md)。
  • fix(repo,pi): add timeout control for external CLI and git runner child processes — gh and glab CLI calls previously lacked timeout bounds and could hang indefinitely on network failure or auth prompts; runners now enforce a 5-second timeout for external CLIs and a 10-second timeout for git/pi child processes —— 外部子进程增加超时熔断:gh/glab 等外部 CLI 子进程增加 5 秒超时保护,本地 git 与 Pi 扩展增加 10 秒超时,防止网络卡顿或鉴权挂死导致守卫进程永久阻塞。
  • fix(repo,gate): fail closed when worktree status query fails — getWorktreeStatus previously caught git failures (e.g. index.lock locks) and returned a clean status, allowing dirty worktrees to bypass clean-worktree gates; it now returns null on failure, and worktree gates fail closed by rejecting sensitive operations when worktree status cannot be determined —— 修复工作区状态查询失败时的假干净漏洞:getWorktreeStatus 在 git 报错时不再虚假返回干净状态,改为返回 null;门禁在工作区状态不可知时遵循安全失败(fail-closed)原则坚决阻断。
  • ci(release): run test:git-matrix and test:realflow in release verification — the 169-case git decision matrix and realflow E2E tests are now executed within the release workflow verification suite before tagging and publishing —— 发布流水线补充 Git 决策矩阵与真机流回归:在发版校验阶段加入 test:git-matrix 与 test:realflow,防止缺陷版本流入发布环节。
  • test(pi): enforce strict branch assertions in test-pi-extension.sh — post-state branch immutability checks previously used || echo which masked failures and reported PASS even if a branch was illegally moved; the script now tracks assertion failures and exits with a non-zero exit code on failure —— 严密 Pi 扩展测试断言:移除屏蔽非零退出码的容错逻辑,分支被篡改时立即输出错误并中断退出。
  • fix(wire): keep user data intact during fine-grained filtering — the filtering introduced in this batch silently deleted non-object array entries and user-authored empty entries on every wire/unwire; filtering now recycles only the entries that became empty because the guard's own command was removed, antigravity unwiring walks every event array under its top-level key, and the key is kept whenever user-authored content remains in it —— 修复本批引入的非破坏性回归:细粒度过滤会在每次 wire/unwire 时静默删除数组中的非对象条目与用户原有的空条目;现仅回收"因摘除守卫自身命令而变空"的条目,antigravity 卸载遍历顶层键内所有事件数组,且键内仍有用户内容时保留该键。
  • fix(repo,gate,cli): fail closed when a git query times out — the 5s/10s timeouts added in this batch funneled "killed by timeout" into the same bucket as ordinary failures, so branch/upstream lookups that timed out degraded to “unprotected” and allowed the command; runners now surface timedOut, repo helpers raise RunnerTimeoutError, and the gate, DSH plugin and CLI check paths all deny with a dedicated message instead of failing open —— git 查询超时改为保守拒绝:本批新增的 5s/10s 超时把"超时被杀"与普通失败混在一起,分支/上游查询一旦超时会静默降级为"不受保护"而放行;现 runner 显式暴露 timedOut,仓库查询抛 RunnerTimeoutError,门禁、DSH 插件与 CLI check 三条路径均以专属文案拒绝,不再 fail-open。
  • test(matrix): stop counting guard crashes as legitimate allows — scripts/test-git-matrix.sh mapped every exit code other than 2 to allow, so an internal crash (exit 1) could masquerade as a real allow; only 0 (allow) and 2 (deny) are protocol results now, and anything else is counted as FAIL —— 矩阵不再把守卫崩溃记成放行:此前 check() 把所有非 2 退出码都记为 allow,守卫内部崩溃(exit 1)会被伪装成合法放行;现只有 0(放行)与 2(拦截)属协议内结果,其余一律计 FAIL 并单列计数。
  • test(matrix): cover platform auto-detection — the verification matrix always passed --platform, so the new Cursor heuristics had no end-to-end coverage; the Cursor block now also runs gitflow-guard check without --platform and asserts the {"permission":"deny"} payload for a payload without cursor_version —— 矩阵补自动判别覆盖:此前验证矩阵恒传 --platform,新的 Cursor 启发式没有端到端兜底;现 Cursor 区块额外以不带 --platform 的方式实弹断言无 cursor_version 的 payload 仍返回 Cursor 拒绝协议。
  • ci(release): provide the E2E git identity per step — the release workflow wrote a global git identity into the runner (git config --global), leaking into every later git invocation of the job; the two E2E suites now receive identity through step-level environment variables —— 发布工作流不再写全局 git 配置:此前用 git config --global 给 runner 写入全局身份,会波及该作业后续所有 git 调用;现改为步骤级环境变量,仅对两个 E2E 套件生效。
  • docs(readme): document whole-string anchoring of featurePattern — patterns are compiled as ^(?:…)$, so prefix/substring-style patterns no longer match and prefix spoofing (malicious/feature/x) is rejected; the regex-safety bullet says so in all 11 languages, and docs/design.md records the rule with its anti-spoofing rationale —— 11 语言 README 与 docs/design.md 补记 featurePattern 整串锚定语义:模式按 ^(?:…)$ 编译,前缀/子串式写法会失配,前缀伪装(malicious/feature/x)不再被认作 feature 分支。
  • test(wire,repo,gate,platform,cli): close the coverage gaps found in review — non-object and pre-existing empty hook entries survive wire+unwire, an entry mixing user and guard commands unwires to the user command only (codex/zcode), antigravity multi-event unwire keeps user content, a real 50 ms timeout boundary plus RunnerTimeoutError pr...
Read more