diff --git a/CHANGELOG.md b/CHANGELOG.md index 924ae8c..38a7733 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ - **Claude Code 配置(Agentic Git 预置)**:新增两项与 Claude Code 相关的配置为 M5 [AI 接缝](./docs/research/05-ai-agent-seams.md) 铺路——① 设置项 `hyperGit.claudeCode.executablePath`(Claude Code CLI 可执行路径,**留空=从 `PATH` 自动探测 `claude`**;描述内嵌 `command:` 链接就地提供「浏览 / 打开 Claude 设置」);② 命令 `hyperGit.setClaudeCodePath`(QuickPick:Browse 文件选择器写回 / **Use system Claude Code** 清空覆盖)与 `hyperGit.openClaudeSettings`(打开 `~/.claude/settings.json`,缺失时经确认创建 `{}`)。采用**原生设置 + 命令**承载(零新增 Webview 面板),路径解析下沉纯函数 [`engine/agent/claude-path.ts`](./src/engine/agent/claude-path.ts)(Vitest 可测),命令实现见 [`adapter/claude-commands.ts`](./src/adapter/claude-commands.ts)。**仅落地配置与快捷入口**,`agent/` 五接缝与 `hyperGit.ai.enabled` 行为不变、零破坏。同步校正 README 指标行(`6 视图 · 101 命令 · 7 配置项 · 372 单元测试`,此前 `97 命令 / 324 测试` 已滞后 HEAD)。完整叙述见 [Claude Code 配置](./docs/features/claude-code-config.md)。 - **Branches 视图按 `/` 前缀分组为文件夹树**:Local / Remote / Tags 三段支持在**平铺**与**按 `/` 前缀分组的可折叠文件夹树**间切换——共享前缀的分支收拢到以前缀命名的文件夹下、叶子仅显示末段后缀(如 `bak/2025`、`bak/master-2025-07` → 📁`bak` → `2025` / `master-2025-07`;远程整体收拢为 `origin` 文件夹并内嵌 `feature`)。新增纯逻辑引擎 [`buildRefTree`](./src/engine/ref/ref-tree.ts)(复用「变更文件目录树」`buildFileTree` 的 trie 构建 + compact 折叠范式;叶子携完整 `RawRef`、命令定位不受影响;分支感知排序:当前 HEAD → 收藏 → 同档文件夹优先、名称数字感知升序),并**隐藏 `origin/HEAD` 符号引用**(对齐主流 Git UI,消除 `origin` 叶子与 `origin` 文件夹同名冲突)。工具栏提供「平铺 ⇄ 树」切换(`hyperGit.branchesGroupByPrefix` / `hyperGit.branchesFlatten`,context key 驱动按钮互斥),偏好按仓库持久化于 `workspaceState`(默认树形),文件夹默认展开、展开态跨刷新稳定。文件夹节点用独立 `contextValue` 且不登记任何右键命令,checkout / delete / rename / merge / rebase / compare / favorite 与多选批量均零改动、零破坏。完整叙述见 [分支前缀分组树](./docs/features/branch-tree-group-by-prefix.md)。 +### Changed + +- **面板视图默认布局调整(显隐与顺序)**:`package.json` `contributes.views` 声明式微调六视图默认态——**Stash / Shelf** 由 `collapsed` 改为 `visibility:"hidden"`(VS Code schema 中 `hidden` 映射 `hideByDefault`:默认不出现在容器内,仍可经视图标题右键菜单勾选恢复);**Commit / Worktrees** 由 `visible` 改为 `collapsed`(显示但默认折叠、点击标题即展开);**Branches / Graph** 保持 `visible`;容器内声明顺序调整为 **Commit · Branches · Graph · Worktrees**(Stash · Shelf 隐藏排其后)。`initialSize` 权重不变,`src/` 零改动,命令 / 协议 / 菜单 / `viewsWelcome` / 交互零破坏。新增 [`tests/unit/views-layout.test.ts`](./tests/unit/views-layout.test.ts) 声明式护栏锁定顺序与各视图 `visibility`。**平台约束**:`visibility` 仅影响全新安装 / 干净 profile 的初始态——老用户升级后需命令面板「View: Reset View Locations」或右键容器页签「Reset Location」方采用新默认(同 [issue #12](./docs/.agents/issue.md) / [#13](./docs/.agents/issue.md) 平台行为)。决策详见 [issue #16](./docs/.agents/issue.md)。 + ## [0.0.14] - 2026-07-06 — 修复 GRAPH 视图提交记录时间倒序 修复 GRAPH 视图「All」范围下提交记录未按时间倒序排列的问题——取数参数由 `--topo-order` 改为 `--author-date-order`,令跨分支提交按作者日期正确交错、消除「日期回跳」。纯取数排序修复,不改数据协议、布局算法与任何视图交互。完整用户视角叙述见 [Release Note v0.0.14](./docs/releases/v0.0.14.md)。 diff --git a/README.md b/README.md index cfee9e6..5b2c227 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ English · 简体中文

-

6 views · 101 commands · 11 settings · 372 unit tests

+

6 views · 101 commands · 11 settings · 375 unit tests

## Features @@ -78,7 +78,7 @@ See the [Engineering Plan](./docs/architecture/engineering-plan.md), the [Implem pnpm install # install dependencies pnpm run compile # type-check + lint + build pnpm run watch # watch build (press F5 to launch the Extension Host debugger) -pnpm run test:unit # unit tests (pure engine logic, Vitest, 324 cases) +pnpm run test:unit # unit tests (pure engine logic, Vitest, 375 cases) pnpm run test:integration # integration tests (@vscode/test-electron) pnpm run package # production build pnpm dlx @vscode/vsce package # package the .vsix diff --git a/docs/.agents/issue.md b/docs/.agents/issue.md index 31de2b1..628942c 100644 --- a/docs/.agents/issue.md +++ b/docs/.agents/issue.md @@ -98,7 +98,7 @@ - **表因**:用户反馈 Worktrees 视图展开后无法继续缩小(截图中仍占大片空白),要求「所有视图可拖到任意高度、取消最小高度限制」。 - **根因**:侧边栏每个视图面板(`Pane`)的最小体高由 VS Code 核心**硬编码 = 120px**(竖直方向;构造函数 `this._minimumBodySize = ... orientation === HORIZONTAL ? 200 : 120`,见 `src/vs/base/browser/ui/splitview/paneview.ts`),加 22px 标题栏,展开态最小 ≈ **142px**,该值经 `minimumSize` 直接驱动 SplitView 拖拽分隔条下限。`WebviewViewPane extends ViewPane` **未覆写** `minimumBodySize`,故本扩展 2 个 webview(Commit/Graph)与 4 个 tree(Branches/Stash/Shelf/Worktrees)视图**共用同一 142px 下限**。允许扩展为活动栏容器内视图指定固定/最小/最大高度的官方特性请求 [microsoft/vscode#123715](https://github.com/microsoft/vscode/issues/123715) 已被**关闭为 not planned / out-of-scope**,从未新增任何 API 或 `package.json` 贡献点。扩展运行于独立进程,拿不到工作台面板对象,`minimumBodySize` setter 仅核心 `ViewPaneContainer` 调用;注入 CSS 亦无效(`.pane-body{min-height:0}` 改不动 JS 层用于夹取拖拽下限的 `minimumSize`)。 -- **处理方式**:该限制**无法经扩展解除**,采用受支持的折中缓解——在 `package.json` `contributes.views` 调初始布局默认值:次要视图 Stash/Shelf 设 `visibility:"collapsed"`(默认仅 22px 标题栏、点击即展开),Worktrees 保持 `visible`(仅以 `initialSize` 权重收窄),全部视图加 `initialSize`(Commit 3 / Graph 3 / Branches 2 / 其余 1,类 CSS flex 的高度权重)。两字段经 `src/vs/workbench/api/browser/viewsExtensionPoint.ts` 的 `viewDescriptor` schema 确认可用;`initialSize` **仅当「同一扩展同时拥有视图与视图容器」时生效**(本扩展拥有 `hyper-git` 容器与全部视图,条件满足)。 +- **处理方式**:该限制**无法经扩展解除**,采用受支持的折中缓解——在 `package.json` `contributes.views` 调初始布局默认值:次要视图 Stash/Shelf 设 `visibility:"collapsed"`(默认仅 22px 标题栏、点击即展开),Worktrees 保持 `visible`(仅以 `initialSize` 权重收窄),全部视图加 `initialSize`(Commit 3 / Graph 3 / Branches 2 / 其余 1,类 CSS flex 的高度权重)。两字段经 `src/vs/workbench/api/browser/viewsExtensionPoint.ts` 的 `viewDescriptor` schema 确认可用;`initialSize` **仅当「同一扩展同时拥有视图与视图容器」时生效**(本扩展拥有 `hyper-git` 容器与全部视图,条件满足)。**注**:此处枚举系 v0.0.12 时点缓解快照——自 #16 起默认布局改为 Stash/Shelf `hidden`、Commit/Worktrees `collapsed`、顺序重排为 Commit·Branches·Graph·Worktrees,**当前默认布局以 #16 为准**。 - **后续防范**:① VS Code 侧边栏视图存在约 **142px 硬性最小展开高度**,无法经扩展降低——遇「任意高度 / 无最小高度」类诉求应直接引 #123715(not planned)说明平台边界,**勿承诺实现**;判断「webview 内容 CSS `min-height`」与「外层面板最小高度」是两回事。② `visibility` / `initialSize` **只影响初始状态**(「用户手动折叠/移动/隐藏过后即不再生效」)——老用户需命令面板「View: Reset View Locations」或右键容器图标「Reset Location」才采用新默认;实机验证须用**干净 profile 或先重置**以规避持久化布局。③ 想让展开视图更紧凑,只能靠「减少常驻视图数(默认折叠)+ 权重」,而非解除下限。 - **同类问题影响**:所有向活动栏/侧边栏容器贡献 TreeView/WebviewView 且希望自定义或取消视图高度的扩展;凡把「webview 内容 `min-height` CSS」误认为能改变外层面板最小高度的实现。 @@ -131,4 +131,12 @@ - **后续防范**:① 为差异的「缺失端」构造 URI 时,**一律用 git 空树 ref**,不要对不存在对象取 `'HEAD'` / `${hash}^` 这类具名 ref——它们只在旧版 VS Code(容错 readFile)上侥幸可用,新版必抛 FileNotFound。② VS Code git 扩展内部行为(如 readFile 容错性)随版本变化,复用其 `toGitUri` 时须确认跨 `engines.vscode` 下限到当前主线的兼容矩阵;空树 ref 是少数有契约保障的「稳定回空」途径。③ webview 的 `data-*` 属性应承载**数据**(机器可用的稳定 key/路径),展示串(含 `"old → new"` 这类人为拼接)只放在可见标签文本里——二者混用会导致 `joinPath` 之类以数据为输入的下游崩溃。④ 逐文件级语义(status)须端到端透传到决策点(host 命令),勿用提交级布尔(`hasParent`)模糊替代——后者无法区分单文件是 A/D/M/R。⑤ 测试断言「差异已打开」时勿按标签计数(VS Code `{preview:true}` 会复用预览槽替换而非新增),应先 `closeAllEditors` 再按差异标题(含文件名)匹配标签。 - **同类问题影响**:所有消费 vscode.git `toGitUri` 自建差异打开逻辑的扩展,凡为缺失端取具名 ref 的均在新版 VS Code 复现;凡 webview `data-path` 复用展示串(含分隔符)的实现均会在路径拼接处崩溃;以及任何「逐文件操作」误用「提交级 / 全局级」标志判定单文件形态的设计。 +## #16 面板视图默认布局调整(Stash/Shelf 默认隐藏 · Commit/Worktrees 默认折叠 · 顺序重排) + +- **表因**:用户(附 VS Code「视图显隐」右键菜单截图)要求——Stash / Shelf **默认不显示**、仅在用户勾选后出现;其余视图显示顺序为 **Commit → Branches → Graph → Worktrees**;且 Commit 与 Worktrees **默认折叠**。 +- **根因**:非缺陷,系默认布局的 UX 决策落地。视图的显隐 / 顺序 / 初始尺寸**纯由 `package.json` `contributes.views` 声明式驱动**(`src/` 无任何代码断言或依赖,两处 `.focus` 在折叠/可见态均正常),可零代码达成。此前 #12 缓解取值(Stash/Shelf `collapsed`、Worktrees/Commit/Graph/Branches `visible`)与本诉求不符,需重排数组并改写 `visibility`。 +- **处理方式**:重排 `contributes.views["hyper-git"]` 数组为 `commit → branches → log → worktrees → stash → shelf → changesBadge`(容器内顺序取声明顺序);`visibility` 改写为 Commit/Worktrees=`collapsed`、Branches/Graph=`visible`、**Stash/Shelf=`hidden`**(VS Code `src/vs/workbench/api/browser/viewsExtensionPoint.ts` 的 `viewDescriptor` schema 确认 `visibility` 枚举为 `['visible','hidden','collapsed']`,`hidden` 映射 `hideByDefault:true`——不入容器但「可经视图菜单发现/勾选」,正对附图未勾选态);`initialSize` 权重与 `changesBadge`(`when:false`,恒末位)不变。命令 / 协议 / 菜单 / `viewsWelcome` 均按 id 匹配、与顺序无关,零破坏。新增 [`tests/unit/views-layout.test.ts`](../../tests/unit/views-layout.test.ts) 声明式护栏锁定顺序 + 各视图 `visibility` + `changesBadge` 的 `when:false`。 +- **后续防范**:① `visibility` / 顺序 / `initialSize` **仅影响全新安装 / 干净 profile 的初始态**(复用 #12 结论,不重述)——老用户须「View: Reset View Locations」或右键容器「Reset Location」方生效,实机验证须用干净 profile。② `visibility:"hidden"` ≠ `when:"false"`:前者「默认隐藏但用户可经视图菜单勾选恢复」(Stash/Shelf),后者「恒不渲染」(changesBadge 角标承载专用)——诉求「默认不显示但用户可自行开启」**必须**用 `hidden`,误用 `when:false` 会致用户无法启用。③ 容器**内**视图相对顺序可控(声明顺序驱动),但容器相对内置页签的顺序不可控(见 #13),勿承诺后者。④ 三态语义以 VS Code schema 为权威,勿据「本仓此前只用过 `visible`/`collapsed`」臆断 `hidden` 不存在。 +- **同类问题影响**:所有以 `contributes.views` 声明默认布局的 VS Code 扩展;凡将「默认隐藏但可恢复」误用 `when:false`(致用户无法启用)或反向混淆的实现;以及把「仅初始态生效」误当「持久强制」而困惑于老用户升级后不生效的排障。 + diff --git a/docs/i18n/zh-CN/README.md b/docs/i18n/zh-CN/README.md index 67883e3..7387354 100644 --- a/docs/i18n/zh-CN/README.md +++ b/docs/i18n/zh-CN/README.md @@ -16,7 +16,7 @@ English · 简体中文

-

6 视图 · 101 命令 · 11 配置项 · 372 单元测试

+

6 视图 · 101 命令 · 11 配置项 · 375 单元测试

## 核心能力 @@ -78,7 +78,7 @@ pnpm install # 安装依赖 pnpm run compile # 类型检查 + lint + 构建 pnpm run watch # 监听构建(F5 启动 Extension Host 调试) -pnpm run test:unit # 单元测试(engine 纯逻辑,Vitest,324 例) +pnpm run test:unit # 单元测试(engine 纯逻辑,Vitest,375 例) pnpm run test:integration # 集成测试(@vscode/test-electron) pnpm run package # 生产构建 pnpm dlx @vscode/vsce package # 打包 .vsix diff --git a/package.json b/package.json index 01a087d..d2eded3 100644 --- a/package.json +++ b/package.json @@ -62,9 +62,15 @@ "id": "hyperGit.commit", "name": "Commit", "type": "webview", - "visibility": "visible", + "visibility": "collapsed", "initialSize": 3 }, + { + "id": "hyperGit.branches", + "name": "Branches", + "visibility": "visible", + "initialSize": 2 + }, { "id": "hyperGit.log", "name": "Graph", @@ -73,27 +79,21 @@ "initialSize": 3 }, { - "id": "hyperGit.branches", - "name": "Branches", - "visibility": "visible", - "initialSize": 2 + "id": "hyperGit.worktrees", + "name": "Worktrees", + "visibility": "collapsed", + "initialSize": 1 }, { "id": "hyperGit.stash", "name": "Stash", - "visibility": "collapsed", + "visibility": "hidden", "initialSize": 1 }, { "id": "hyperGit.shelf", "name": "Shelf", - "visibility": "collapsed", - "initialSize": 1 - }, - { - "id": "hyperGit.worktrees", - "name": "Worktrees", - "visibility": "visible", + "visibility": "hidden", "initialSize": 1 }, { diff --git a/tests/unit/views-layout.test.ts b/tests/unit/views-layout.test.ts new file mode 100644 index 0000000..a4a6ab2 --- /dev/null +++ b/tests/unit/views-layout.test.ts @@ -0,0 +1,52 @@ +import { describe, it, expect } from 'vitest'; +import pkg from '../../package.json'; + +/** + * 面板视图默认布局护栏:`contributes.views["hyper-git"]` 的声明顺序与各视图 + * `visibility` 纯由 package.json 驱动(`src/` 无代码断言/依赖),一旦被误改, + * 用户可见的默认排序与显隐即随之漂移。此处锁定「设计基线」,呼应本仓 + * `--topo-order` 回归护栏文化。语义见 docs/.agents/issue.md #16(决策)/ #12(平台约束)。 + */ + +/** VS Code view descriptor 的最小子集(仅取本护栏关心的字段)。 */ +interface ViewDescriptor { + id: string; + visibility?: string; + when?: string; +} + +const views = pkg.contributes.views['hyper-git'] as unknown as ViewDescriptor[]; +/** 用户可见视图 = 排除 `when:false` 的角标承载视图(changesBadge,永不渲染)。 */ +const userViews = views.filter((v) => v.when !== 'false'); + +describe('Hyper Git 面板视图默认布局(package.json 声明式护栏)', () => { + it('用户可见视图声明顺序固定为 Commit·Branches·Graph·Worktrees·Stash·Shelf', () => { + expect(userViews.map((v) => v.id)).toEqual([ + 'hyperGit.commit', + 'hyperGit.branches', + 'hyperGit.log', + 'hyperGit.worktrees', + 'hyperGit.stash', + 'hyperGit.shelf', + ]); + }); + + it('各视图默认 visibility 符合设计(Commit/Worktrees 折叠、Branches/Graph 展开、Stash/Shelf 隐藏)', () => { + const visibilityById = Object.fromEntries(userViews.map((v) => [v.id, v.visibility])); + expect(visibilityById).toEqual({ + 'hyperGit.commit': 'collapsed', + 'hyperGit.branches': 'visible', + 'hyperGit.log': 'visible', + 'hyperGit.worktrees': 'collapsed', + 'hyperGit.stash': 'hidden', + 'hyperGit.shelf': 'hidden', + }); + }); + + it('changesBadge 为 when:false 的隐藏角标承载视图,且恒定末位', () => { + const badge = views.find((v) => v.id === 'hyperGit.changesBadge'); + expect(badge?.when).toBe('false'); + expect(badge?.visibility).toBeUndefined(); + expect(views[views.length - 1].id).toBe('hyperGit.changesBadge'); + }); +});