Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .agents/issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,21 @@
> 用于跨上下文留存问题处理经验,避免重复踩坑。新条目追加在末尾,同 Issue 只维护一处。
>
> 每条摘要包含:**表因 / 根因 / 处理方式 / 后续防范 / 同类问题影响**。

---

## #1 JSDoc 块注释中的 `*/` 提前闭合注释

- **表因**:`pnpm run check-types` 在 `src/engine/model/index.ts` 报大量 `TS1127 Invalid character` / `TS1109 Expression expected`,指向一段纯中文注释行。
- **根因**:注释文本「`INDEX_*/工作区/冲突`」中的 `*/` 序列被 TypeScript 解析为块注释终止符,导致其后中文文本暴露为代码,触发语法错误。
- **处理方式**:改写注释,移除 `*/` 序列(`INDEX_*/工作区` → `INDEX 系列、工作区`)。
- **后续防范**:在任何 `/* ... */` 块注释内引用含 `*/` 的内容(如 `gitDecoration.*`、正则 `*/`、glob)时,必须转义或改写;可用 `grep -rn '\*/' src/ | grep -vE '\*/\s*$'` 扫描提前闭合。
- **同类问题影响**:所有含中文技术注释的 TS 文件,尤以注释内出现路径/枚举/正则片段时高发。

## #2 pnpm 11 构建脚本审批与配置迁移

- **表因**:`pnpm install` 输出 `[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: esbuild, @vscode/vsce-sign, keytar`,导致 esbuild 原生二进制未安装,后续构建可能失败;且 `package.json` 的 `pnpm.onlyBuiltDependencies` 字段被忽略并告警。
- **根因**:pnpm 10/11 出于供应链安全默认拦截依赖 postinstall;同时 pnpm 11.9 将 `onlyBuiltDependencies` 等设置**移出 package.json**,新位置为 `pnpm-workspace.yaml`(本版本使用 `allowBuilds:` 审批格式,由 pnpm 自动生成脚手架)。
- **处理方式**:删除 package.json 的 `pnpm` 字段;在 `pnpm-workspace.yaml` 写入 `allowBuilds: { esbuild: true, '@vscode/vsce-sign': true, keytar: true }` 后重新 `pnpm install`,三个 postinstall 正常执行。
- **后续防范**:pnpm 项目一律在 `pnpm-workspace.yaml` 管理构建脚本审批;新增含原生二进制的依赖时,需在此文件追加放行;CI 首次 `pnpm install` 后确认无 `ERR_PNPM_IGNORED_BUILDS`。
- **同类问题影响**:所有 pnpm 11 工程;凡依赖 esbuild / keytar / @vscode/vsce-sign / prebuild-install 类原生模块的扩展。
23 changes: 23 additions & 0 deletions .agents/knowledge-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,26 @@

> 项目内文档与关键能力索引;按主题正交分组,链接为相对路径以便跨上下文跳转。
> 新增/变更文档时应即时同步本表。

## 工程协议与基线
- [AGENTS.md](../AGENTS.md) — 协作协议与工程行为准则(熵减心法 / 架构原则 / 执行规范)。
- [README.md](../README.md) — Hyper Git 项目说明、架构(路径 B)与 M0-M5 路线图。
- [CHANGELOG.md](../CHANGELOG.md) — 版本变更记录(Keep a Changelog 格式)。
- [LICENSE](../LICENSE) — MIT。

## Agents 知识库(本目录)
- [Issue 记录](./issue.md) — 跨上下文问题处理经验(表因 / 根因 / 处理 / 防范)。
- [引用规范 IEEE](./reference-specifications.md) — 文献引用格式与上标锚定。
- [浏览器验证协议](./browser-validation.md) — OAuth/SSO 红线与 E2E 验证协议。

## 架构分层(src/)
> 依赖方向单向:`UI → Adapter → Engine`;`Agent` 以接口注入 `Engine`/`CommitPipeline`,不反向依赖 UI。

- `engine/` — 纯领域逻辑(零 vscode 依赖,Vitest 可测):`model/`、`scm-mapping/`、`commit/pipeline.ts`、`diff/`(M4)。
- `adapter/` — 唯一接触 vscode API:`GitRepositoryAdapter`、`ChangelistRegistry`、`tree/`、`webview/`、`diff/`、`storage/`(M1+)。
- `agent/` — AI 接缝(M5 实现):`ILlmProvider`、`IPreCommitInspector`、`IChangelistGrouper`、`IConflictResolver`、`IChatToolRegistrar`。
- `shared/protocol.ts` — Webview ↔ Host 消息契约【单一事实源】。
- `infra/` — 日志(OutputChannel)/ 错误处理 / 事件总线 / 配置。

## 里程碑
M0 脚手架 + CI ✅ → M1 Git Adapter + Changes(多 changelist)→ M2 Commit 窗口 → M3 Log/Branches/Diff → M4 Shelf/Partial/Stash → M5 AI Agent。
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
root = true

[*]
indent_style = tab
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml,json}]
indent_style = tab
indent_size = 2
102 changes: 102 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: CI

on:
push:
branches: [master, feature/1.x.x]
tags:
- 'v*'
pull_request:

permissions:
contents: read

jobs:
# 闸门:类型检查 + lint + 生产构建(快门,ubuntu 单格)
lint-build:
name: Lint & Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm run check-types
- run: pnpm run lint
- run: pnpm run package

# 集成测试矩阵:main/tag 跑三平台,PR 仅 ubuntu 快门
test:
name: Test (${{ matrix.os }})
needs: lint-build
strategy:
fail-fast: false
matrix:
os: ${{ (github.event_name == 'pull_request') && fromJson('["ubuntu-latest"]') || fromJson('["ubuntu-latest", "macos-latest", "windows-latest"]') }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: 构建 dist/extension.js(集成测试需加载扩展)
run: node esbuild.js
- run: pnpm run test:unit
- name: 集成测试(Linux 需 xvfb 包装 Electron)
run: xvfb-run -a pnpm run test:integration
if: runner.os == 'Linux'
- name: 集成测试
run: pnpm run test:integration
if: runner.os != 'Linux'

# 打包 vsix(Linux 保 POSIX 文件属性)
package:
name: Package vsix
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm dlx @vscode/vsce package --no-yarn
- uses: actions/upload-artifact@v4
with:
name: vsix
path: '*.vsix'
if-no-files-found: error

# 发布:仅 tag 触发,双市场(Marketplace + OpenVSX),生产环境审批门
publish:
name: Publish
needs: package
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- uses: actions/download-artifact@v4
with:
name: vsix
- name: 发布到 VS Code Marketplace
run: pnpm dlx @vscode/vsce publish --packagePath *.vsix
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
- name: 发布到 OpenVSX(覆盖 Cursor / Windsurf 等 AI IDE)
run: pnpm dlx ovsx publish *.vsix
env:
OVSX_PAT: ${{ secrets.OVSX_PAT }}
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
# 本地 MCP 配置(不入仓)
.mcp.json

# 依赖与构建产物
node_modules/
dist/
out/
*.vsix

# VS Code Test 临时
.vscode-test/

# 临时产物(执行计划等,一律收敛至此并即时清理)
.temp/

# 系统/编辑器
.DS_Store
Thumbs.db
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# 规避 vsce 打包与 pnpm 符号链接 node_modules 的 hoisting 兼容问题(循证:Track3 §一/§4)
node-linker=hoisted
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dist/**
out/**
node_modules/**
*.vsix
media/**
pnpm-lock.yaml
8 changes: 8 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"useTabs": true,
"tabWidth": 2,
"singleQuote": true,
"semi": true,
"printWidth": 120,
"trailingComma": "all"
}
6 changes: 6 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
13 changes: 13 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "运行扩展(Extension Host)",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "pnpm: watch"
}
]
}
26 changes: 26 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "watch",
"problemMatcher": "$esbuild-watch",
"isBackground": true,
"label": "pnpm: watch",
"group": { "kind": "build", "isDefault": true },
"presentation": { "reveal": "never" }
},
{
"type": "npm",
"script": "check-types",
"problemMatcher": ["$tsc"],
"label": "pnpm: check-types"
},
{
"type": "npm",
"script": "lint",
"problemMatcher": ["$eslint-stylish"],
"label": "pnpm: lint"
}
]
}
27 changes: 27 additions & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.vscode/**
.vscode-test/**
src/**
tests/**
node_modules/**
.github/**
.agents/**
.context/**
.temp/**
media-src/**
AGENTS.md
CLAUDE.md
pnpm-lock.yaml
pnpm-workspace.yaml
**/*.ts
**/*.map
tsconfig.json
esbuild.js
eslint.config.mjs
.prettierrc
.prettierignore
.editorconfig
.npmrc
.gitignore
.gitattributes
vitest.config.ts
**/.DS_Store
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Changelog

本项目的所有重要变更均记录于此文件。格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。

## [Unreleased]

### Added — M0 脚手架 + CI

- 初始化 pnpm + esbuild + TypeScript(strict)工程骨架,对齐官方 `esbuild-sample`。
- 正交分层目录:`engine/`(纯逻辑,零 vscode 依赖)、`adapter/`、`agent/`(AI 接缝预留)、`ui/`、`shared/`、`infra/`。
- 质量基础设施:ESLint 9 flat config + typescript-eslint + @stylistic、Prettier、Vitest(engine 单测)、@vscode/test-electron + Mocha(集成测试)。
- 工程约束:`.npmrc`(`node-linker=hoisted` 规避 vsce/pnpm hoisting)、`.vscodeignore`、`engines.vscode ^1.85.0` 与 `@types/vscode 1.85.0` 严格对齐。
- 扩展贡献点:活动栏视图容器 `hyper-git` + `hyperGit.changes` 树视图(M0 占位,M1 接入真实 changelist)+ `hyperGit.showVersion` 命令 + 配置项(commit 模板 / Conventional Commits 开关 / AI 开关预留)。
- 引擎层纯逻辑:`engine/scm-mapping`(FileStatus → gitDecoration.* 主题色映射)、`engine/commit/pipeline`(Checkin hook 责任链,对齐 IDEA `CheckinHandler.ReturnResult`)。
- AI 接缝接口 + Null 实现:`agent/llm-provider.ts`(`ILlmProvider`)、`agent/pre-commit.ts`(`IPreCommitInspector`)。
- Webview ↔ Host 消息契约单一事实源:`shared/protocol.ts`。
- CI 流水线 `.github/workflows/ci.yml`:lint → build → test 矩阵(ubuntu/mac/win + Linux xvfb)→ package vsix → artifact;`tag v*` → 双市场发布(Marketplace + OpenVSX)。
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Hyper Git

> 在 VS Code 上完整复刻 IntelliJ IDEA 的 **Git 工具窗口** 与 **Commit 提交窗口**,并为未来 git 管理的 AI Agent 自主代理能力预留架构接缝。

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)

## 为什么需要 Hyper Git

IntelliJ IDEA 的统一 Git 工具窗口(顶部 `Commit / Shelf / Stash` 标签页 + Changes 变更树 + Commit Message 编辑区 + 提交前 Inspection)是开发者高频依赖的工作流。迁移到 VS Code 后,原生 Source Control 视图**缺少**:多 changelist、忠实的 Commit 窗口、提交前检查流水线、Shelf/行级提交等能力。Hyper Git 旨在 1:1 补齐这一体验。

## 架构(路径 B:消费 + 自绘)

- **消费** 内置 `vscode.git` 扩展导出的稳定 `Repository` API 作为 git 操作底座(不重造 git 状态机)。
- **自建** changelist registry(IDEA 的 active 列表 / 跨列表行级归属无法用原生 SCM group 表达)。
- **自绘** 独立视图容器承载 IDEA 风格 UI,与原生 Source Control 视图零冲突、平行共存。
- **AI**:现仅预留接口接缝(`ILlmProvider` / `IPreCommitInspector` 等,对齐 IDEA `CheckinHandler` 生命周期),实现延后至 M5。

详见[工程实施方案](./.claude/plans)(决策循证基线)与[知识索引](./.agents/knowledge-map.md)。

## 路线图

| 里程碑 | 主题 | 状态 |
|---|---|---|
| **M0** | 脚手架 + CI | ✅ 进行中 |
| M1 | Git Adapter + Changes TreeView(多 changelist) | ⏳ |
| M2 | Commit 提交窗口(模板 / Amend / CC 校验 / hook 链) | ⏳ |
| M3 | Log 提交图 + Branches + Diff/Blame | ⏳ |
| M4 | Shelf + Partial/行级提交 + Stash UI | ⏳ |
| M5 | AI Agent(实现接缝) | ⏳ |

## 开发

```bash
pnpm install # 安装依赖
pnpm run compile # 类型检查 + lint + 构建
pnpm run watch # 监听构建(F5 启动 Extension Host 调试)
pnpm run test:unit # 单元测试(engine 纯逻辑,Vitest)
pnpm run test:integration # 集成测试(@vscode/test-electron)
pnpm run package # 生产构建
pnpm dlx @vscode/vsce package # 打包 .vsix
```

> 包管理与脚本统一使用 `pnpm`(遵循 [AGENTS.md](./AGENTS.md) 工程规范)。

## 许可证

[MIT](./LICENSE)
50 changes: 50 additions & 0 deletions esbuild.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const esbuild = require('esbuild');

const production = process.argv.includes('--production');
const watch = process.argv.includes('--watch');

/**
* @type {import('esbuild').Plugin}
*/
const esbuildProblemMatcherPlugin = {
name: 'esbuild-problem-matcher',
setup(build) {
build.onStart(() => {
console.log('[watch] build started');
});
build.onEnd((result) => {
result.errors.forEach(({ text, location }) => {
console.error(`✘ [ERROR] ${text}`);
console.error(` ${location.file}:${location.line}:${location.column}:`);
});
console.log('[watch] build finished');
});
},
};

async function main() {
const ctx = await esbuild.context({
entryPoints: ['src/extension.ts'],
bundle: true,
format: 'cjs',
minify: production,
sourcemap: !production,
sourcesContent: false,
platform: 'node',
outfile: 'dist/extension.js',
external: ['vscode'],
logLevel: 'silent',
plugins: [esbuildProblemMatcherPlugin],
});
if (watch) {
await ctx.watch();
} else {
await ctx.rebuild();
await ctx.dispose();
}
}

main().catch((e) => {
console.error(e);
process.exit(1);
});
Loading
Loading