Repository navigation
Releases: Athosoo/dsh-git-graph-sidebar
Release list
v1.13.1
1.13.1 —— 插件不再自己合并规范
上一版把合并交给模型,但机械并集仍作为「草稿」留在插件里。这一版把它整条删掉:插件自己没有任何路径能合成一份规范。
删掉的东西
conventionsConsolidate、conventionsUnionSection、conventionsMergedBody/git/conventions/consolidate路由(现在返回 404)、git_conventions的draft动作与write参数GitApi.conventionsConsolidate、客户端合并计划面板、11 个 locale 键
留下的路径
read:把工作区、仓库、父仓库与散文文档(AGENTS.md 等)的完整正文交给模型(上限 20000 字符)check:逐字段、逐规则报告差异,并在没有机械冲突但存在多份文档时提醒查重write:落盘模型自己写的合并稿 —— 时间戳备份、被并入的仓库文档改成指针、指针下保留原文
面板的「Merge with AI」把一份写好的请求复制到剪贴板(客户端插件无法直接发起模型回合),插件自己一个字都不写。
测试
- 旧的合并路径改为断言不存在:
/git/conventions/consolidate404、报告不写盘、面板永不出现 - host 232/232、8 组 preview 断言全过、180 个 locale 键全部解析
安装后必须重启 DSH:宿主侧与客户端侧都改了。
资产文件名不带版本号(dsh-git-graph-sidebar.tgz),市场条目的 latest/download 自动跟随这个 Release。
v1.13.0
合并现在真的由智能体来做
1.10.0 的合并是确定性的并集:它只能合并正则看得见的东西,读不出两段话在说同一件事,也读不出「每节都写待定」的脚手架没有信息量。1.13.0 把合并搬到模型侧,代码只留真正机械的部分。
新增 read 与 write
action: read交出每份文档的完整正文(工作区总纲、仓库自己的、祖先仓库的,以及AGENTS.md/CLAUDE.md/.cursorrules/CONTRIBUTING.md),带来源、字节数、是否指针、是否截断;action: write落盘模型自己写好的合并稿:空正文拒绝、目标已存在且无force拒绝、旧目标先复制成.bak-<时间戳>、被并的仓库文档改成指针(下面保留合并前原文,clone 下来照样能读);- 旧的
consolidate退为draft(机械并集草稿),check不变。
提示词:谁来做判断
有冲突时不再让人去调机械合并,而是要求完整读文档、逐段比较、先给方案、用户同意后才写;并且写明「工具不可用就用你自己的文件工具」(agentTool 默认关闭)。文档之间没有机械冲突但存在多份时,也会提示一句「正文仍可能重复」——查重成了常驻指令,合并完成后自动消失。
面板:交接而不是执行
「AI 合并」和冲突条上的「查看并合并」会把一段现成的请求复制到剪贴板(客户端插件无法直接发起模型回合),粘贴到对话里发送即可。机械并集仍然一键可达——通知里的「先看机械并集草稿」,同样先预览再写。
接口与测试
- 工具参数:
action(required)+body/write/force/absorb - host
252/252,客户端 preview 8 组断言全过;locale 189 键
这次 host 与客户端都改了,装完必须重启 DSH。
v1.12.1
主区域视图落地后现场发现的两处问题,1.12.1 修掉。
提交卡片不再压在输入框上
主区域里 .viewArea 是跟着内容长高的,所以整列按画布高度撑开,卡片被推到滚动区底部,正好被粘在底部的输入框盖住。现在整列高度按宿主自己发布的两个变量算:
height: calc(var(--dsh-conversation-viewport-height, 100vh) - var(--dsh-composer-height, 96px))
页面不再滚动,卡片也不可能被盖住;草稿变高导致输入框变高时,变量会跟着更新。
顺带把卡片挪到图谱右侧(主区域是横的):选中提交时左右分栏(右侧 320px、自己做滚动),没选中时不占位。侧边栏仍是原先的底部卡片。
被并入的仓库文档保留原文
整合会把仓库级 GIT_CONVENTIONS.md 改成指针。如果这个文件被 git 跟踪,那等于提交了一个指向本机工作区的死链接。现在指针三行之后会保留合并前原文,并带一行注释说明它是合并前副本;内部所有读取路径仍然先过指针标记,所以规则不会被重复计入。
自检
build-libspliced 2843 / 3223 / 2153 / 449、patch-hostalready present 25validate-lib187 locale keystest-host243/243(新增「指针保留合并前原文」)preview-tab全过,新增一段主区域布局断言(高度含两个变量、左右分栏、卡片离开底部)
装完请重启 DSH:客户端的布局与视图注册都在启动时读取。
v1.12.0
1.12.0 — 图谱也能开进对话主区域
主区域视图(可选、可关闭)
- 注册
conversation.view:id: "git-graph"(自造 id,不占内置视图那一格)、order: 70、label用 thunk 随语言切换 - 规范条上的「在主区域打开」开关打开它,视图右上角
×关掉它,偏好记在localStorage["dsh-git-graph:main-view"] - 默认关闭:没打开之前不注册任何东西,别人的视图页签条不受影响;侧边栏 tab 仍是主入口
- 视图本体就是原来的 tab,没有
tab描述符,choose()已加守卫
文档
README.md/README.zh.md开头重写为 Why this one / 为什么选它:规范进的是模型提示、规范会被读回(含AGENTS.md这类散文)、两份规范打架不会被悄悄投票、三个入口一套本体、全程本地只读DEVELOPMENT.md记下偏好键、注册代码、tab守卫、字面量t()的坑与测试限制HANDOVER.md补 §7.13
接口与测试
- locale 键 185 → 187;tab 源码 3189 行
preview-tab.mjs的假 ctx 补slots/sessions/ 内存版localStorage,新增断言组:偏好关不注册、开则注册进conversation.view、×关掉后 dispose 且偏好变"0"、再开能重注册test-host242/242、validate-lib187 键、patch-hostalready present 25、build-libspliced3189 / 2149 / 449
安装
宿主与客户端都改了,装完必须重启 DSH(Ctrl+R 不够),否则新面板与新视图都不会出现。
v1.11.0
这一版做了什么
规范不只写在 GIT_CONVENTIONS.md 里。很多工作区的提交规则写在 AGENTS.md、CLAUDE.md、.cursorrules 或 CONTRIBUTING.md 里,之前的版本完全看不见它们。
1.11.0 把这类散文文档也读进来(只读,永不改写):
conventionsSources()在工作区根和仓库根各扫一遍AGENTS.md/CLAUDE.md/.cursorrules/CONTRIBUTING.md,作为foreign来源单独返回,不混进「治理这批提交的规范文档」计数。- 它们和规范文档用同一个规则解析器(
parseConventionRules():标题长度、type 词表、小写、句号、祈使句),所以散文里的「Keep the subject under 50 characters.」这种句子照样能被读出规则——不需要调用模型,判定是确定性的。 conventionsConflicts()把它们的规则纳入比对与并集:谁的更严就按谁算(长度取最小、type 取并集、布尔「任一方要求即生效」),并新增foreign一项列出「文档里没有、或与并集不同」的规则,计入冲突数。- 每一步注入给助手的提示会写明:
AGENTS.mdalso states … - it is not rewritten by a merge, so ask the user whether those rules should move into the document first。模型因此会先问,而不是默默按旧规范写。 - 一键整合允许「只有一份规范 + 旁边有
AGENTS.md」时执行;计划里新增leftInPlace——这些文件只读不写,因为工作区里别的工具在读它们。 - 规范面板的合并计划会列出「保留原地」的文件(
data-gitgraph-left)。
接口
| 路由 / 工具 | 变化 |
|---|---|
/git/conventions/conflicts |
返回值新增 foreign: [{origin, docPath, keys}] |
/git/conventions/consolidate |
计划新增 leftInPlace: string[] |
git_conventions 工具 |
同上一并返回 |
验证
test-host242/242(新增第 [20] 段 10 项:散文文档被报成 foreign、把并集收紧到 50 字符、提示里出现AGENTS.md、计划列leftInPlace、合并后只读文件原文未变、count 0)。preview-tab12 段全过(新增data-gitgraph-left断言)。validate-lib185 个 locale 键全部解析;build-libspliced 2843 / 3079 / 2149 / 449 行;patch-host25 处幂等。
这次 host 与客户端都改了:装完必须重启 DSH,Ctrl+R 不够。
v1.10.1
补丁版。1.10.0 把规范能力做齐了,但冲突条只在真有冲突时才出现,想主动把几份规范整理成一份时,面板上没有入口。
规范面板自己带一个「合并规范」按钮
规范面板的标题行(Git 规范 / 文档名 / 状态 / 打开 / 更换框架 那一行)现在还有一枚 合并规范 按钮:
- 文档存在才出现,操作进行中禁用;
- 点了走的是和冲突条完全相同的流程:先出并集计划(哪些文档会被并掉、新增哪几节、合并后的规则并集),再点「写入并备份」才落盘;
- 所以不管冲突条在不在,都能手动整理一遍。
只有一份规范时,不再当错误
只有一份规范在生效时,主机返回 convention-single-source。原来它会被当成错误红字显示,现在改成一句提示「只有一份规范,无需合并。」并清掉计划面板。
接口与测试
- 行为不变的部分一律没动:
/git/conventions/consolidate不带write仍只出计划,git_conventions工具仍是 opt-in; - locale 键 181 → 183(
sidebar.consolidateOpen、sidebar.consolidateSingle); preview-tab的 tier-4 补一段:面板按钮出计划但不写盘、取消后计划面板消失;- 全链路自检:
spliced 3068 / 2102 / 449、patch-host already present 25、183 locale keys、host232/232、预览 12 段全过。
这次只动了客户端(lib/client.js)与文案,没有 host 变更;但插件是按包整体加载的,装完还是重启一下 DSH 最稳妥。
v1.10.0
AI 署名政策、排他性检测与一键整合。
AI 署名是明确的政策
前置字段新增 ai: required | optional | forbidden,默认 optional,老文档不受影响。required 要求每条提交信息带一个 AI 署名 trailer(Assisted-by: / Generated-by: / Co-authored-by: 都认),forbidden 只拦 AI 专用 trailer——人类结对提交的 Co-authored-by: 不算违规。检查读的是提交正文:commitCompliance() 的 git log 格式从 %H%x00%s 改成 %H%x00%s%x00%b%x1e,以前只读标题,所以根本看不到 trailer。和其它规则一样:面板始终标出,只有 strict: true 时才真的拒绝提交。
冲突会被报出来,不会被悄悄投票
conventionsConflicts() 把「管同一批提交」的文档三方对比——工作区 <工作区>/.dsh/GIT_CONVENTIONS.md、当前仓库自己的、以及祖先仓库的:字段(status / framework / strict / language / ai)与规则(标题长度、type 词表、小写、句号、祈使句)都比,但只有双方都明确写了同一个字段且取值不同才算冲突,沉默不算。有冲突时,每一步注入给助手的提示里都会带上这份分歧清单,并明确要求「不要自己选边,先问用户」——所以中途才加入工作区的插件、模型也不会闷头照旧规范写。
一键整合到工作区文档
「查看并合并」先把并集方案预览出来(新增几节、改写几节、哪些文档会被并掉),按「写入并备份」才落盘,落到 <工作区>/.dsh/GIT_CONVENTIONS.md。并集语义:长度取最严、type 取词表并集、布尔规则「任一方要求即生效」,各文档正文小节都会搬过来(同名标注来源)。每一份被替换的文件都留一份 .bak-<年月日-时分秒>,仓库级文档改成指针文件(inherited from …)——想退回随时能退。
助手自己也能查
打开 agentTool 后会注册 git_conventions 工具(action: check 列冲突、action: consolidate 出合并计划),不带 write: true 时只出计划不动盘。
接口与测试
新增 /git/conventions/conflicts、/git/conventions/consolidate,ai 透传到写入、预览、设置、工作区四条既有路由;locale 键 166 → 181。test-host 232/232(新增 [17] AI 署名、[18] 冲突与合并、[19] 工具三段),preview-tab 增加 tier-4 一段(AI 三态开关、冲突条、先预览后写入)。
这次 host 与客户端都动了,装完必须重启 DSH。
1.9.2 - 标签终于真的能和分支分开
1.9.2 — 标签终于真的能和分支分开
1.9.1 说「标签退出筛选排」,但只改了面板;主机那一行没动,所以装在插件里看不出任何变化。
修的是什么
lib/index.js:616 的 parseDecoration() 一直在做 .replace(/^tag: /, ""),把标签和分支都变成光秃秃的名字。客户端再聪明也分不出来——你截图里那 9 枚 v1.5.0 … v1.9.0 被当成「分支」画成实心青蓝,就是这个原因。
现在只剥 HEAD -> (和裸 HEAD),tag: 前缀保留,面板据此区分:分支是实心药丸、标签是灰色描边、当前分支额外加底色。
为什么 1.9.1 的测试没抓出来
scripts/preview-tab.mjs 的 fixture 是手写的,里面本来就写着 "tag: v1.0.0"——客户端逻辑在假数据上完全正确,而真实主机在链路的前一步就把前缀剥掉了。测试测的是自己的想象力。
test-host 因此新增第 [16] 段:真建仓库、真打 annotated tag、再断言 /git/graph 返回的 refs 里既有 tag: v1.0.0 也有无前缀的 main。现在 189/189。
验证
build-libspliced 2843 / 1560 / 449 行patch-host23 处、validate-lib166 个 locale 键test-host189/189、preview-tab10 节全过- 安装后需 ==重启 DSH==(这次改的是主机半边,
Ctrl+R不够)
v1.9.1 - 标签不再占筛选项 / tags are not filters
1.9.1 — 标签不再占筛选项
一个标签只指向一个提交,静音它只能藏掉一行——它不该和分支一起排队。这一版把标签从筛选排里拿走,仍然留在提交行上作徽章。
变更
- 标签退出筛选排:
refGroups不再收tag: …,顺序变成「当前分支 → 其他本地分支 → 只有远程的分支」。hostlib/index.js:616不再剥掉tag:前缀,客户端据此区分标签与分支(1.9.0 里发布标签被当成分支画成实心 chip,就是这条前缀被剥掉导致的)。 - 标签仍是行内标记:新增
refLabelOf,把tag: v1.0.0映射成v1.0.0,行内徽章与导出的 SVG 都用它。 - 可筛分支少于四条时整排不显示(
SIDEBAR_TAB_FILTER_REFS_MIN = 4);已经静音过东西时仍然显示,因为「清除筛选」在那里。 - 可见性过滤:标签不参与静音,但只被标签指着的提交必须仍算起点,否则静音任意分支时老版本提交会消失。
- 清掉 1.6.1 遗留的死键
sidebar.expandGraph(「全屏查看」/「Full-window view」)。
验证
build-lib spliced 2843 / 1560 / 449 行、patch-host 23 处、166 个 locale 键、test-host 186/186、preview-tab 全过(含新的 refs 一节与「单分支时整排隐藏」用例)。
1.9.1 — tags are not filter candidates
A tag points at a single commit, so muting one hides exactly one row; it never deserved a slot next to the branches. Tags still show up on the commit rows as badges.
refGroupsskipstag: …; hostlib/index.js:616keeps the prefix now so the client can tell a tag from a branch.refLabelOfrenderstag: v1.0.0asv1.0.0in row badges and in the exported SVG.- Fewer than four filterable branches and the row is not drawn at all (unless something is muted, because Clear filters lives there).
- Dead
sidebar.expandGraphkeys from 1.6.1 removed.
v1.9.0 — ref chips: one per branch
1.9.0 — 引用标签:一个分支一枚
筛选那一排以前是「一个 ref 一枚标签」:main、origin/main、origin/HEAD、feat/x、origin/feat/x、tag: v1.8.2 各占一枚,同一个分支出现两次,符号引用也混在里面;超过十二枚的部分被直接切掉,看不见也点不到。
现在:
- 一个分支一枚标签 —
feat/x与origin/feat/x共用一枚,静音一次两边一起关掉;标签的title把两个名字都写出来。 - 符号引用不再出现 —
HEAD、HEAD -> main、origin/HEAD不成为标签。 - 排序有意义 — 当前分支在最前,然后是其他本地分支、只有远程的分支,最后是标签(灰色)。同级按名字。
- 不再被切掉 — 默认显示前十二枚,多出来的给
+N,点开变「收起」。 - 一键清空 — 有任何一枚静音时,旁边出现「清除筛选」。
- 行内徽章同步 —
HEAD -> main现在显示成main,计数从+4变成+2;导出的 SVG 用的是同一套标签。
Toolbar layout, zoom, export, search and everything else are unchanged.
Verification
scripts/test-host.mjs: 186/186 checks passedscripts/preview-tab.mjs: export, search, ref chips, conventions, tier-3 and overview sections all greenscripts/validate-lib.mjs: 166 locale keys resolve, all fork identifiers defined
English
The filter row used to carry one chip per ref — main, origin/main, origin/HEAD, feat/x, origin/feat/x, tag: v1.8.2 — so one branch showed up twice, symbolic refs got their own chips, and anything past twelve was sliced off and unreachable.
Now it is one chip per branch: a local branch and its remote twin share a chip and mute together (the chip's tooltip names both), HEAD / HEAD -> … / origin/HEAD never become chips, tags keep a grey one of their own, the order is current branch → other local → remote-only → tags, the row folds to +N past twelve, and a Clear filters chip appears whenever something is muted. Row badges and the exported SVG use the same labels, so HEAD -> main reads as main.