Compare commits

..

14 Commits

Author SHA1 Message Date
刘焱 e7cdf8fc26 docs(demo): 演示页新增许可证合规检查与新人引导交互流程
- panel-compliance: 仓库元信息 / LICENSE 识别 / 依赖合规 / 敏感信息扫描(git grep) / 合规报告
- panel-newcomer: 查找 good-first-issue / 类型判定 / 幂等去重 / 添加引导评论
- Skills 结构总览补 compliance 卡片与文件清单
2026-06-24 10:34:11 +08:00
刘焱 29f8d3403c docs(plans): 项目级 Skill 集成实现计划 2026-06-17 08:59:59 +08:00
刘焱 654c8976df docs(specs): 项目级 Skill 集成设计(Claude Code 兼容) 2026-06-17 08:57:53 +08:00
刘焱 f8eea302fb docs(skills): 真实验证回填
基于真机 API 实测(z2_cc/gitlink-cli + 上游 Gitlink/gitlink-cli)修正:
- journals 响应结构:data.journals[](非 data[]);评论 journal 含 notes,
  操作 journal 含 operate_content 无 notes;去重仅扫评论 journal 的 notes
- GET /v1/:owner/:repo/labels 端点实测不存在(返回首页 HTML),REFERENCE 已标注
- 补充 Windows Git Bash(MSYS) 路径坑:api 的 /v1 参数被转为 D:/Git/... 需 MSYS_NO_PATHCONV=1
- spec §10 未决项全部闭环,并记录未执行的端到端写验证
2026-06-16 08:02:49 +08:00
刘焱 f0f20e5e8e docs(skills-readme): 概览表补 compliance 与 newcomer-guide 2026-06-15 21:07:08 +08:00
刘焱 bbc1367a88 docs(newcomer-skill): 示例加入去重检查与批量场景 2026-06-15 20:58:17 +08:00
刘焱 cfc28287f4 docs(newcomer-skill): 新增 REFERENCE(命令/字段/标签变体/幂等规则) 2026-06-15 20:57:40 +08:00
刘焱 c2eb3c8f1a fix(newcomer-skill): 修复 label 命令 Bug,加入状态过滤与幂等去重 2026-06-15 20:57:11 +08:00
刘焱 bb0ef89450 fix(compliance-skill): 修复 DB 连接串正则与跨文件一致性(C1/I1/I2/I3/I4/M2) 2026-06-15 20:45:45 +08:00
刘焱 ef2aa17c8e docs(compliance-skill): 新增端到端合规检查示例 2026-06-15 20:25:44 +08:00
刘焱 f071f456fa docs(compliance-skill): REFERENCE 增补敏感信息扫描章节 2026-06-15 20:25:20 +08:00
刘焱 a6e174da88 feat(compliance-skill): 新增敏感信息扫描工作流与报告整合 2026-06-15 20:24:26 +08:00
刘焱 34a0dc0d78 docs(plans): GitLink Skills 丰富与完善实现计划
11 个任务(10 静态 + 1 真实验证),compliance→newcomer→README→全局验证顺序。
每步含完整内容与可执行验证命令,已自检(规格覆盖/占位符/类型一致)。
2026-06-15 20:17:48 +08:00
刘焱 a147812e60 docs(specs): GitLink Skills 丰富与完善设计规格
聚焦子任务二标记完成的 2 个技能:
- gitlink-compliance:补敏感信息扫描工作流 + examples
- gitlink-newcomer-guide:修 label 命令 Bug + REFERENCE + 幂等去重

决策 A=混合扫描(api+git),决策 B=标记串+journal 去重。
验证=先静态后真实。
2026-06-15 20:04:45 +08:00
128 changed files with 3715 additions and 18799 deletions

View File

@ -1,119 +0,0 @@
---
description: GitLink 操作中心 — 列出所有常用操作、端到端场景与科研辅助,上下选择并执行;也可传入仓库网址直接对其操作
argument-hint: "[可选: GitLink 仓库网址 或 场景关键词,如 代码审查 / 健康度]"
---
# GitLink 操作中心(交互式菜单)
你是 **GitLink 操作中心**的调度器。请严格按下列流程,为用户呈现一个可「上下方向键选择并执行」的交互式菜单,并调用对应已实现的 skill 完成操作。
> **铁律**:所有 GitLink 操作必须用 `gitlink-cli`,禁止用 `gh`。所有写操作默认 dry-run确认后再实际执行。
---
## 第 1 步解析目标仓库TARGET
检查命令参数 `$ARGUMENTS`
1. 若包含 GitLink 网址(形如 `https://gitlink.org.cn/<owner>/<repo>`,可能带 `.git`、`/pulls/<n>`、`/issues/<n>`、`/compare/...` 等后缀),用正则 `gitlink\.org\.cn/([^/]+)/([^/?.#]+)` 提取 `<owner>``<repo>`(去掉末尾 `.git`)→ 记为 **TARGET = owner/repo**
2. 否则若形如 `<owner>/<repo>`(如 `z2_cc/gitlink-cli`),直接作为 TARGET。
3. 否则若当前处于一个 git 仓库且其 remote 指向 GitLink自动解析 owner/repo 作为 TARGET可运行 `git remote -v` 判断)。
4. 否则 **TARGET = 空**(后续按需向用户询问)。
**关键词直跳**:若 `$ARGUMENTS` 命中下方「映射表」中的任一场景关键词(代码审查 / Issue 分拣 / Release / 健康度 / 合规 / 新人引导 / 社区运营 / 质量门禁 / 项目初始化 / 多仓库 / 贡献者 / 科研洞悉 / 科研热点 / 知识图谱 / 科研合规 / 复现性 / 科研协作匹配 / 科研进度 / 预警),**跳过第 2 步菜单**,直接进入第 3 步执行该场景TARGET 仍按上面规则解析)。
---
## 第 2 步:呈现菜单(无关键词时)
### 2.1 先在对话中「列出所有」可选项
用中文打印下面这张完整目录(让用户一眼看到全部 16 项 + 仓库定位),格式如下:
```
🧭 GitLink 操作中心 — 请选择要执行的操作(也可直接输入序号 / 关键词 / 仓库网址)
🔍 单项操作
1 智能代码审查 分析 PR diff输出结构化 Review 意见并自动评论
2 Issue 自动分拣 根据内容自动分类、打标签、分配责任人
3 Release Notes 生成 根据 commit / PR 记录生成结构化版本说明
4 新人引导 为 good-first-issue 自动添加引导评论
📊 分析与成长
5 项目健康度报告 统计 Issue 响应时间、PR 合并效率、贡献者活跃度
6 许可证合规检查 扫描许可证合规性与敏感信息泄露风险
7 贡献者成长体系 追踪 PR/Issue 活动 → 生成排行 → 自动颁发徽章
🚀 端到端自动化场景
8 社区运营自动化 Issue 分拣 → 周报 → 自动发布 Release
9 代码质量看门人 PR 审查 → CI → 门禁决策 → 自动合并
10 项目一键初始化 创建仓库 → 生成 README/LICENSE/CI → 初始 Issue/里程碑
11 多仓库协同 跨仓库 Issue 追踪 / PR 看板 / Release 协调发布
🔬 科研辅助(面向科研工作者 / 课题组,打通开源生态与学术科研)
12 科研项目洞悉 8 维数据采集 + AI 分析(成熟度/文档/贡献模式/社区健康)→ 结构化评分报告
13 科研热点与知识图谱 多关键词搜索 → 实体/关系抽取 → Mermaid 知识图谱 + 交互式 HTML
14 科研合规与复现性 数据可用性 / 环境可复现 / 结果可验证 多维评估
15 科研协作智能匹配 角色(数据/算法/工程/评估)推断 → 人员-任务匹配 → 综合建议
16 科研进度跟踪与预警 6 维风险信号(停滞/高优无人/零回复/积压/提交突变/里程碑 DDL+ 100 分制评分
🌐 也可以:粘贴一个 GitLink 仓库网址https://gitlink.org.cn/<owner>/<repo>),我对它执行上述任一操作。
```
### 2.2 再用 AskUserQuestion 弹出原生「上下选择」菜单
调用一次 `AskUserQuestion`header 为「操作类别」,提供 4 个选项用户可用方向键上下选择也可选「Other」直接输入序号/关键词/网址):
| 选项 | 描述 |
|---|---|
| 🔍 单项操作 | 代码审查 / Issue 分拣 / Release Notes / 新人引导 |
| 📊 分析与成长 | 项目健康度 / 许可证合规 / 贡献者成长 |
| 🚀 端到端自动化 | 社区运营 / 质量门禁 / 项目初始化 / 多仓库协同 |
| 🔬 科研辅助 | 项目洞悉 / 热点与知识图谱 / 合规复现 / 协作匹配 / 进度预警 |
- 若用户选了 🔍 / 📊 / 🚀 三类(每类 ≤4 项):再调用一次 `AskUserQuestion` 列出该类别下具体操作(每项描述一句话),让用户上下选择。
- 若用户选 🔬 科研辅助(共 5 项,超过单次 4 项上限):先把 5 项编号打印,再用 `AskUserQuestion` 列出其中 4 项,并提示「可选 Other 输入第 5 项序号」;用户也可直接回复 1-5 序号。
- 若用户在任何一步选「Other」输入了仓库网址 / `owner/repo`:按第 1 步规则解析为 TARGET再继续选操作。
- 若用户选「Other」直接输入了序号或关键词按映射表直接定位操作进入第 3 步。
---
## 第 3 步:执行对应 skill
### 操作 → skill 映射表
| 序号 | 菜单项 | 调用的 skill |
|---|---|---|
| 1 | 智能代码审查 | `gitlink-code-review` |
| 2 | Issue 自动分拣 | `gitlink-issue-triage` |
| 3 | Release Notes 生成 | `gitlink-release-auto` |
| 4 | 新人引导 | `gitlink-newcomer-guide` |
| 5 | 项目健康度报告 | `gitlink-project-health` |
| 6 | 许可证合规检查 | `gitlink-compliance` |
| 7 | 贡献者成长体系 | `gitlink-contributor-growth` |
| 8 | 社区运营自动化 | `gitlink-community-ops` |
| 9 | 代码质量看门人 | `gitlink-quality-gate` |
| 10 | 项目一键初始化 | `gitlink-project-bootstrap` |
| 11 | 多仓库协同 | `gitlink-multi-repo-coordination` |
| 12 | 科研项目洞悉 | `gitlink-research-insight` |
| 13 | 科研热点与知识图谱 | `gitlink-research-hotspot` |
| 14 | 科研合规与复现性 | `gitlink-research-compliance` |
| 15 | 科研协作智能匹配 | `gitlink-research-matching` |
| 16 | 科研进度跟踪与预警 | `gitlink-research-progress` |
> 这些 skill 都在当前项目(`Desktop/gitlink-cl`)下。用 `Skill` 工具按上表名字调用即可。
执行规则:
1. **若 TARGET 仍为空**,先用 `AskUserQuestion` 询问「请提供目标 GitLink 仓库owner/repo 或网址)」。
2. 调用对应 skill把 TARGET 的 owner/repo 传达给它skill 内部用 `--owner/--repo` 或环境变量;端到端场景脚本形如 `bash skills/<skill>/scripts/*-full.sh <owner> <repo>`)。
3. **写操作一律先 dry-run**`DRY_RUN=true`),把将要执行的变更展示给用户,经确认后再 `DRY_RUN=false` 实际执行。
4. 操作完成后,用中文给出简洁结果摘要(做了什么 / 关键数据 / 产物路径)。
---
## 备注
- 多仓库协同11支持 `REPOS="owner1/repo1,owner2/repo2"` 同时处理多个仓库。
- **科研辅助12-16**均为 **evidence-oriented / read-only**(只读分析、不改仓库),可放心对任意公开 GitLink 仓库运行;产物多为结构化报告 / 知识图谱 / 交互式 HTML位于各 skill 的 `scripts/_output/`)。`gitlink-research-matching` 已验证于 `Gitlink/forgeplus``research-progress` / `research-compliance` 已验证于 `forgeplus`、`gitlink-cli`、`ifzhang/FairMOT`。
- 若 `gitlink-cli` 未登录,先提示用户运行 `gitlink-cli auth login`(或调用 `gitlink-shared` skill
- 用户随时可输入「返回」回到主菜单,或「退出」结束。

View File

@ -1,55 +0,0 @@
version: 2
name: 多仓库协同流水线
description: "定时运行:多仓库 Issue 追踪 → PR 看板 → Release 协调发布"
trigger:
webhook: gitlink@1.0.0
event:
- ref: schedule
ruleset-operator: AND
global:
concurrent: 1
param:
- ref: remote_url
name: ""
value: '"https://gitlink.org.cn/z2_cc/gitlink-cli.git"'
required: false
type: STRING
hidden: false
- ref: owner
name: "仓库所有者"
value: '"z2_cc"'
required: true
type: STRING
hidden: false
- ref: repo
name: "仓库名称"
value: '"gitlink-cli"'
required: true
type: STRING
hidden: false
- ref: repos
name: "多仓库列表(逗号分隔 owner/repo"
value: '"z2_cc/gitlink-cli,z2_cc/gitlink-bisync"'
required: false
type: STRING
hidden: false
workflow:
- ref: start
name: 开始
task: start
- ref: ssh_cmd_0
name: 运行多仓库协同流水线
task: ssh_cmd@1.1.1
input:
ssh_pass: ((work_together.ssh_key))
ssh_ip: '"121.41.216.243"'
ssh_port: '"22"'
ssh_user: '"root"'
ssh_cmd: '"cd /root/gitlink-cli && git pull origin master && DRY_RUN=true REPOS=$(repos) bash skills/gitlink-multi-repo-coordination/scripts/multi-repo-full.sh"'
needs:
- start
- ref: end
name: 结束
task: end
needs:
- ssh_cmd_0

View File

@ -1,6 +1,6 @@
version: 2
name: 构建流水线
description: "gitlink-cli CI 流水线:拉取代码、构建、部署、验证"
description: "gitlink-cli CI 流水线:拉取代码、构建、验证"
trigger:
webhook: gitlink@1.0.0
event:
@ -20,14 +20,14 @@ workflow:
name: 开始
task: start
- ref: ssh_cmd_0
name: 拉取代码并构建部署
name: 拉取代码并构建验证
task: ssh_cmd@1.1.1
input:
ssh_pass: ((work_together.ssh_key))
ssh_ip: '"121.41.216.243"'
ssh_port: '"22"'
ssh_user: '"root"'
ssh_cmd: '"export GOPROXY=https://goproxy.cn,direct && cd /root/gitlink-cli || git clone https://gitlink.org.cn/z2_cc/gitlink-cli.git /root/gitlink-cli; cd /root/gitlink-cli && git pull origin master && go build -o gitlink-cli . && cp gitlink-cli /usr/local/bin/ && gitlink-cli version"'
ssh_cmd: '"export GOPROXY=https://goproxy.cn,direct && cd /root/gitlink-cli || git clone https://gitlink.org.cn/z2_cc/gitlink-cli.git /root/gitlink-cli; cd /root/gitlink-cli && git pull origin master && go build -o gitlink-cli . && ./gitlink-cli version"'
needs:
- start
- ref: end

View File

@ -1,55 +0,0 @@
version: 2
name: 贡献者成长体系流水线
description: "每周定时运行:贡献追踪 → 排行段位 → 自动颁发徽章"
trigger:
webhook: gitlink@1.0.0
event:
- ref: schedule
ruleset-operator: AND
global:
concurrent: 1
param:
- ref: remote_url
name: ""
value: '"https://gitlink.org.cn/z2_cc/gitlink-cli.git"'
required: false
type: STRING
hidden: false
- ref: owner
name: "仓库所有者"
value: '"z2_cc"'
required: true
type: STRING
hidden: false
- ref: repo
name: "仓库名称"
value: '"gitlink-cli"'
required: true
type: STRING
hidden: false
- ref: dry_run
name: "是否 dry-run"
value: '"true"'
required: false
type: STRING
hidden: false
workflow:
- ref: start
name: 开始
task: start
- ref: ssh_cmd_0
name: 运行贡献者成长体系流水线
task: ssh_cmd@1.1.1
input:
ssh_pass: ((work_together.ssh_key))
ssh_ip: '"121.41.216.243"'
ssh_port: '"22"'
ssh_user: '"root"'
ssh_cmd: '"cd /root/gitlink-cli && git pull origin master && DRY_RUN=$(dry_run) bash skills/gitlink-contributor-growth/scripts/contributor-growth-full.sh $(owner) $(repo)"'
needs:
- start
- ref: end
name: 结束
task: end
needs:
- ssh_cmd_0

View File

@ -1,61 +0,0 @@
version: 2
name: 项目初始化流水线
description: "新项目一键初始化:创建仓库 → 生成 README/LICENSE/CI → 创建初始 Issue 和里程碑"
trigger:
webhook: gitlink@1.0.0
event:
- ref: manual
ruleset-operator: AND
global:
concurrent: 1
param:
- ref: remote_url
name: ""
value: '"https://gitlink.org.cn/z2_cc/gitlink-cli.git"'
required: false
type: STRING
hidden: false
- ref: owner
name: "仓库所有者"
value: '"z2_cc"'
required: true
type: STRING
hidden: false
- ref: repo
name: "仓库名称"
value: '"gitlink-cli"'
required: true
type: STRING
hidden: false
- ref: project_desc
name: "项目描述"
value: '"一个用 Go 编写的 GitLink 命令行工具"'
required: true
type: STRING
hidden: false
- ref: dry_run
name: "是否 dry-run"
value: '"true"'
required: false
type: STRING
hidden: false
workflow:
- ref: start
name: 开始
task: start
- ref: ssh_cmd_0
name: 运行项目一键初始化流水线
task: ssh_cmd@1.1.1
input:
ssh_pass: ((work_together.ssh_key))
ssh_ip: '"121.41.216.243"'
ssh_port: '"22"'
ssh_user: '"root"'
ssh_cmd: '"cd /root/gitlink-cli && git pull origin master && DRY_RUN=$(dry_run) PROJECT_DESC=\"$(project_desc)\" bash skills/gitlink-project-bootstrap/scripts/project-bootstrap-full.sh $(owner) $(repo)"'
needs:
- start
- ref: end
name: 结束
task: end
needs:
- ssh_cmd_0

18
.gitignore vendored
View File

@ -18,21 +18,3 @@ my_docs/
CLAUDE.md
.claude/
docs/
# 脚本输出目录
skills/*/scripts/_output/
doc/sub-task4-module-c/_output/
doc/sub-task4-module-d/_output/
# CLI 包装器
.cli-bin/
# 测试/临时数据文件
*.json
!package.json
snapshots/
tmp/
# Node.js
node_modules/
package-lock.json

264
CLAUDE.md
View File

@ -1,264 +0,0 @@
# gitlink-cli 项目指南
## 项目背景
本项目是《软件演化与运维》2026 春)课程的**进阶实践任务****GitLink 智能化能力提升项目**。
GitLink CLI 是 GitLink 平台的命令行工具,采用 Go 语言开发cobra 框架),提供 40+ 命令覆盖仓库管理、Issue 跟踪、PR 协作、CI/CD 等场景,并内置 AI Agent Skills 体系,兼容 Claude Code 等主流 Agent 平台。
- **仓库**https://gitlink.org.cn/gitlink/gitlink-cli本仓库 fork 自 `z2_cc/gitlink-cli`
- **Skills 开发指南**`skills/README.md`
- **API 文档**https://s.apifox.cn/da30afb0-9d2e-429b-a4bc-a83209e06021
- **CLI 设计文档**`doc/design.md`
进阶任务包含四个子任务(已全部完成),另加 DevOps 流水线:
| 子任务 | 定位 | 占比 | 技术栈 |
|--------|------|------|--------|
| 子任务一 | 扩展 CLI 能力 | 50% | Go |
| 子任务二 | 编写 Skills | 20% | Markdown + CLI |
| 子任务三 | 端到端工作流 | 20% | Shell + Skills 编排 |
| 子任务四 | 科研辅助(加分项) | 额外加分 | Markdown + CLI |
| DevOps | CI/CD 流水线 | 10% | YAML |
---
## 🧭 操作中心(交互式菜单)
**触发方式**(任一即可):
- 输入 `/gitlink`(斜杠命令,最推荐),可附带参数:`/gitlink 代码审查`、`/gitlink https://gitlink.org.cn/z2_cc/gitlink-cli`
- 直接说「常用操作」、「常用操作以及场景」、「列出操作」、「gitlink 菜单」
触发后按 [`.claude/commands/gitlink.md`](.claude/commands/gitlink.md) 的流程:先列出全部 16 项操作(单项操作 / 分析与成长 / 端到端自动化 / 科研辅助),再用原生上下方向键菜单让用户选择,或接收一个 GitLink 仓库网址直接对其操作,最后调用对应已实现的 skill 执行(写操作默认 dry-run。操作 → skill 映射见该命令文件。
---
## 技术架构
```
gitlink-cli/
├── main.go # 入口
├── cmd/ # CLI 命令定义cobra
│ ├── root.go # 根命令,注册所有 shortcuts
│ ├── api/api.go # raw API 调用gitlink api <METHOD> <PATH>
│ ├── auth/ # 认证login/logout/status/refresh
│ ├── config/ # 配置管理
│ └── interactive/ # 交互式 REPLbubbletea TUI
├── shortcuts/ # 23 个命令组repo/issue/pr/release/ci/…)
│ ├── register.go # RegisterAll() 注册入口
│ ├── common/ # 共享类型 + 批量操作框架batch.go
│ └── {group}/ # 每个命令组一个目录
├── internal/ # 核心包
│ ├── auth/ # 登录、token 存储、HTTP 传输
│ ├── client/ # API 客户端auto-.json、分页、错误映射
│ ├── config/ # 配置文件管理
│ ├── context/ # 自动解析 owner/repo从 git remote
│ └── output/ # 格式化输出json/table/yaml
├── skills/ # 32 个 Skill 定义SKILL.md + examples/ + scripts/
├── .claude/skills/ # Claude Code 使用的符号链接 → ../../skills/{name}
├── .devops/ # GitLink DevOps 流水线3 个 YAML
├── doc/ # 设计文档、交接文档、架构图
└── my_docs/ # 工作文档、总结、计划
```
---
## 子任务一CLI 能力扩展Go
**定位**:为 gitlink-cli 增加新功能、优化现有功能。所有改动在 `cmd/`、`shortcuts/`、`internal/` 中。
### 已完成P1-P4
| 优先级 | 内容 | 关键文件 |
|--------|------|----------|
| **P1** Bug 修复3 项) | `--label` 参数未发送、硬编码 `master` 默认分支、`pr +diff`/`+files` 重复 | `shortcuts/issue/`, `shortcuts/common/`, `shortcuts/pr/` |
| **P2** 参数补全10 项) | 补全 `--milestone`/`--assignee`/`--priority`/`--sort` 等 CLI 参数与 API 的映射 | `shortcuts/issue/`, `shortcuts/pr/`, `shortcuts/release/` |
| **P3** 批量操作9 个命令) | 通用批量框架 + issue/PR/collaborator/branch 批量命令,支持 `--dry-run`/`--yes`/CSV 输入 | `shortcuts/common/batch.go` |
| **P4** 体验优化 | 40+ 命令帮助文档、破坏性操作确认提示、API 错误友好建议 | `shortcuts/*/`, `internal/client/` |
### 交互式 REPL
`cmd/interactive/` 提供基于 bubbletea 的 TUI命令面板模糊搜索→ 参数表单 → 输出查看器。支持 `/` 前缀打开面板。
### 后续可完善方向
- 补全 GitLink OpenAPI 中尚未封装的 Raw API
- 新增 Shortcut 命令组(如看板增强)
- 跨平台兼容性和安装体验优化
- 单元测试覆盖
---
## 子任务二Skills 开发Markdown + CLI
**定位**:基于 gitlink-cli 开发 AI Agent Skill。核心交付物是 SKILL.md + 使用示例 + Agent 平台验证。
### Skills 规范
每个 Skill 位于 `skills/{name}/`,包含:
- `SKILL.md`YAML 前-mattername、description、triggers+ 使用说明
- `examples/`Agent 对话记录或运行示例
- `scripts/`(可选):可执行脚本
### 已完成的 Skills32 个)
**平台基础操作**(原始 11 个 + 扩展):
`gitlink-repo` `gitlink-issue` `gitlink-pr` `gitlink-release` `gitlink-branch` `gitlink-org` `gitlink-user` `gitlink-search` `gitlink-ci` `gitlink-webhook` `gitlink-wiki` `gitlink-snippet` `gitlink-pm`
**智能化 Skills**(子任务二核心交付):
`gitlink-code-review` `gitlink-pr-deep-review` `gitlink-issue-triage` `gitlink-release-auto` `gitlink-project-health` `gitlink-insight` `gitlink-commit-quality` `gitlink-compliance` `gitlink-duplicate-detector` `gitlink-newcomer-guide`
**工作流 Skills**(子任务三):
`gitlink-community-ops` `gitlink-quality-gate` `gitlink-workflow`
**科研 Skills**(子任务四):
`gitlink-research-insight` `gitlink-research-hotspot` `gitlink-research-matching` `gitlink-research-progress` `gitlink-research-compliance`
**共享基础**
`gitlink-shared`(认证、全局参数、安全规则)
### 后续可完善方向
- 为现有 Skill 补充更多 Agent 平台验证OpenClaw、Cursor
- 优化 Skill 触发词准确性
- 增加 Skill 使用示例的覆盖度
---
## 子任务三端到端自动化工作流Shell + Skills 编排)
**定位**:组合 gitlink-cli 命令和 Skills完成可复现的端到端自动化场景。每个工作流串联 ≥3 个步骤。
### 场景 A社区运营自动化
`skills/gitlink-community-ops/` — 三阶段流水线:
1. Issue 分拣(关键词分析 → 建议标签)
2. 社区周报Issue/PR/Commit/Milestone 统计)
3. Release Notes 生成Conventional Commits 分类)
关键文件:`community-ops-full.sh`(全流程编排)、`health-analyze.js`、`release-analyze.js`
### 场景 B代码质量看门人
`skills/gitlink-quality-gate/` — 四阶段门禁:
1. PR 采集 → 2. 深度审查 → 3. CI 检查 → 4. 评分决策≥70 分 + CI 通过 → 建议合并)
评分模型CodeReview(40%) + CI(30%) + 设计一致性(30%)
关键文件:`quality-gate-full.sh`(全流程编排)
### DevOps 流水线
`.devops/` 目录下 3 个 YAML 配置,均配置在 `z2_cc/gitlink-cli`
- `构建流水线.yml`push 触发 Go 构建 + 版本校验
- `社区运营流水线.yml`:定时触发社区运营全流程
- `代码质量门禁流水线.yml`PR 触发质量门禁
### 后续可完善方向
- 贡献者成长体系(追踪→排行→徽章)
- 多仓库协同场景
- 项目一键初始化工作流
- 工作流的错误恢复和通知机制
---
## 子任务四科研辅助Markdown + CLI加分项
**定位**:依托 gitlink-cli 数据获取与 AI Agent 能力,为科研场景提供智能化辅助。设计原则:**evidence-oriented证据驱动、read-only只读不写、delegation pattern委托已有 Skill、pure remote analysis纯远程分析**。
### 已完成的 5 个科研 Skill
| Skill | 功能 | 关键文件 |
|-------|------|----------|
| `gitlink-research-insight` | 仓库级科研项目洞悉8 维数据采集 + 4 维 AI 分析(成熟度/文档/贡献模式/社区健康),输出结构化评分报告 | `scripts/research-insight-full.sh`、`scripts/analyze.js` |
| `gitlink-research-hotspot` | 科研热点追踪:多关键词搜索 → 实体提取 → 关系图构建 → Mermaid.js 知识图谱 + 交互式 HTML 可视化 | `scripts/hotspot-tracker-full.sh`、`scripts/kg-to-html.js` |
| `gitlink-research-matching` | 科研协作智能匹配4 角色推断(数据/算法/工程/评估)→ 人员-任务匹配 → 资源探测 → 综合建议报告 | `examples/matching-run.md`(已验证于 `Gitlink/forgeplus` |
| `gitlink-research-progress` | 科研进度跟踪与预警6 维风险信号(停滞 Issue/高优无人/零回复/积压趋势/提交突变/里程碑 DDL100 分制风险评分 | 已验证于 `forgeplus`/`gitlink-cli`/`FairMOT` |
| `gitlink-research-compliance` | 科研合规与复现性检查:数据可用性/环境可复现/结果可验证 4 维评估 | `examples/reproducibility-check.md`(已验证于 `ifzhang/FairMOT` |
### 共享工具
`skills/gitlink-shared/scripts/` 提供 `detect-cli.sh`CLI 版本检测)和 `md-to-html.js`(报告转交互式 HTML
### 后续可完善方向
- 增加更多科研仓库验证案例
- 知识图谱的交互式探索能力
- 科研主体画像功能
- 创新启发式推荐
---
## Skill 触发映射
当用户提及以下内容时,**优先调用对应 Skill**(而非手动执行命令):
### 平台操作
- **Issue 管理**`gitlink-issue`
- **PR 管理**`gitlink-pr`
- **Release / 发版 / changelog**`gitlink-release``gitlink-release-auto`
- **仓库管理**`gitlink-repo`
- **分支管理**`gitlink-branch`
- **组织管理**`gitlink-org`
- **CI/CD**`gitlink-ci`
- **Wiki**`gitlink-wiki`
- **代码片段**`gitlink-snippet`
- **Webhook**`gitlink-webhook`
- **搜索**`gitlink-search`
### 智能化与自动化
- **代码审查 / PR Review**`gitlink-code-review``gitlink-pr-deep-review`
- **Issue 分拣 / 分类 / Triage**`gitlink-issue-triage`
- **项目健康度 / 周报**`gitlink-project-health``gitlink-insight`
- **新人引导 / good-first-issue**`gitlink-newcomer-guide`
- **重复 Issue 检测**`gitlink-duplicate-detector`
- **许可证合规检查**`gitlink-compliance`
- **提交质量检查**`gitlink-commit-quality`
- **项目管理 / Sprint / 看板**`gitlink-pm`
### 工作流(子任务三)
- **社区运营自动化 / 周报生成**`gitlink-community-ops`
- **代码质量门禁 / PR 自动门禁**`gitlink-quality-gate`
- **工作流模板参考**`gitlink-workflow`
### 科研辅助(子任务四)
- **科研项目洞悉 / 成熟度评估 / 仓库洞察**`gitlink-research-insight`
- **科研热点追踪 / 知识图谱 / 研究趋势**`gitlink-research-hotspot`
- **科研协作匹配 / 角色推断**`gitlink-research-matching`
- **科研进度跟踪 / 风险预警**`gitlink-research-progress`
- **科研合规检查 / 复现性评估**`gitlink-research-compliance`
### 工作流扩展(子任务五)
- **项目一键初始化 / 创建仓库 / 生成 README/LICENSE/CI / 初始 Issue 和里程碑** → 调用 `gitlink-project-bootstrap` skill
- **多仓库协同 / 跨仓库 Issue 追踪 / PR 状态看板 / Release 协调发布** → 调用 `gitlink-multi-repo-coordination` skill通过 `REPOS="owner/repo,..."` 指定多仓库)
- **贡献者成长体系 / 贡献排行 / 成长段位 / 自动颁发徽章** → 调用 `gitlink-contributor-growth` skill
---
## 开发约定
### 命令使用
- 所有 GitLink API 操作使用 `gitlink-cli` 命令,不得直接调用 REST API
- 使用 Skill 前先阅读对应 `SKILL.md``skills/gitlink-shared/SKILL.md` 了解认证与已知限制
- 命令输出优先使用 `--format json` 获取结构化数据
### 构建与测试
```bash
make build # 编译到 bin/gitlink-cli
make install # 安装到 $GOPATH/bin
go test ./... # 运行所有测试
```
### 添加新 Skill
1. 在 `skills/` 下创建目录(如 `skills/gitlink-xxx/`
2. 编写 `SKILL.md`(参考 `skills/README.md` 规范)
3. 在 `.claude/skills/` 创建符号链接:`ln -s ../../skills/gitlink-xxx gitlink-xxx`
4. 更新本文件的 Skill 映射表
### 关键参考文档
- `doc/design.md` — CLI 设计文档
- `doc/sub-task34-交接文档.md` — 子任务三、四交接文档
- `my_docs/summary.md` — 子任务一 P1-P4 改进总结
- `skills/README.md` — Skills 开发规范
- `skills/gitlink-shared/SKILL.md` — 共享基础(认证、安全规则)

View File

@ -2,14 +2,12 @@ package interactive
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"sort"
"strings"
"github.com/gitlink-org/gitlink-cli/internal/client"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
@ -214,165 +212,6 @@ func missingRequiredFlags(s *common.Shortcut, args map[string]string) []string {
return missing
}
// commandSuggestions maps (group, command) to command-specific fix suggestions shown
// in the interactive REPL when a command fails with an API error.
var commandSuggestions = map[string]map[string]string{
"ci": {
"builds": "请确认仓库已启用 CI 引擎gitlink ci +enable且存在构建记录",
"runs": "请确认仓库已启用 CI 引擎,且存在运行记录",
"run-results": "请确认仓库已启用 CI 引擎,且存在运行结果",
"logs": "请确认构建编号正确且构建已完成",
"restart": "请确认构建编号正确且状态允许重新构建",
"stop": "请确认构建编号正确且构建处于运行中",
"pipelines": "请确认仓库已配置 CI 流水线模板",
"run-pipeline": "请确认流水线名称正确且仓库已启用 CI 引擎",
"pipeline-detail": "请确认流水线 ID 正确",
"delete-pipeline": "请确认流水线 ID 正确",
"disable": "仓库可能已禁用 CI无需重复操作",
"enable": "仓库可能已启用 CI无需重复操作",
"run-log": "请确认运行 ID 正确且运行已完成",
},
"issue": {
"list": "请确认 owner/repo 参数正确",
"create": "请确认标题和必填参数已填写",
"view": "请确认 Issue 编号正确",
"update": "请确认 Issue 编号和更新参数正确",
"close": "请确认 Issue 编号正确,且你有关闭权限",
"delete": "请确认 Issue 编号正确,此操作不可恢复",
"comment": "请确认 Issue 编号正确且评论内容不为空",
"comments": "请确认 Issue 编号正确",
"update-comment": "请确认评论 ID 正确",
"delete-comment": "请确认评论 ID 正确",
"reply-comment": "请确认评论 ID 正确",
"batch-close": "请确认 Issue 编号正确,且你有批量关闭权限",
"batch-update": "请确认 Issue 编号和更新参数正确",
"batch-destroy": "请确认 Issue 编号正确,此操作不可恢复",
},
"pr": {
"list": "请确认 owner/repo 参数正确",
"create": "请确认源分支和目标分支正确",
"view": "请确认 PR 编号正确",
"merge": "请确认 PR 已通过 CI 检查且无合并冲突",
"close": "请确认 PR 编号正确",
"reopen": "请确认 PR 编号正确且 PR 当前为关闭状态",
"update": "请确认 PR 编号和更新参数正确",
"comment": "请确认 PR 编号正确且评论内容不为空",
"files": "请确认 PR 编号正确",
"versions": "请确认 PR 编号正确",
"version-diff": "请确认 PR 编号正确",
"reviews": "请确认 PR 编号正确",
"review": "请确认 PR 编号正确且你已被列为审查者",
"comments": "请确认 PR 编号正确",
"create-comment": "请确认 PR 编号正确且评论内容不为空",
"update-comment": "请确认评论 ID 正确",
"delete-comment": "请确认评论 ID 正确",
"commits": "请确认 PR 编号正确",
"batch-close": "请确认 PR 编号正确,且你有批量关闭权限",
"batch-merge": "请确认 PR 已通过 CI 检查且无合并冲突",
},
"release": {
"list": "请确认 owner/repo 参数正确",
"create": "请确认标签名和版本号正确,仓库默认分支可能存在",
"view": "请确认 Release ID 或标签名正确",
"delete": "请确认 Release ID 正确,此操作不可恢复",
"edit": "请确认 Release ID 和更新参数正确",
"update": "请确认 Release ID 和更新参数正确",
},
"branch": {
"list": "请确认 owner/repo 参数正确",
"create": "请确认源分支名正确,默认分支名可能不匹配",
"delete": "请确认分支名正确,此操作不可恢复",
"protect": "请确认分支名正确",
"unprotect": "请确认分支名正确",
"all": "请确认 owner/repo 参数正确",
"default": "请确认仓库存在且可见",
"restore": "请确认分支名正确且分支已被删除",
"batch-delete": "请确认分支名正确,此操作不可恢复",
"batch-protect": "请确认分支名正确",
},
"repo": {
"list": "请确认用户/组织名正确",
"info": "请确认 owner/repo 参数正确",
"create": "请确认仓库名合法且不与其他仓库冲突",
"fork": "请确认源仓库存在且可见",
"delete": "请确认仓库名正确,此操作不可恢复",
"update": "请确认更新参数正确",
"about": "请确认 owner/repo 参数正确",
"menu": "请确认 owner/repo 参数正确",
"units-get": "请确认 owner/repo 参数正确",
"units-set": "请确认仓库单元设置值有效",
"edit-detail": "请确认更新参数正确",
"simple": "请确认 owner/repo 参数正确",
"code-stats": "请确认 owner/repo 参数正确",
"languages": "请确认 owner/repo 参数正确",
"contributors": "请确认 owner/repo 参数正确",
"contributors-stat": "请确认 owner/repo 参数正确",
"recommend": "该功能可能需要特定权限",
"star": "请确认 owner/repo 参数正确",
"unstar": "请确认 owner/repo 参数正确",
"watch": "请确认 owner/repo 参数正确",
"unwatch": "请确认 owner/repo 参数正确",
"stargazers": "请确认 owner/repo 参数正确",
"watchers": "请确认 owner/repo 参数正确",
"transfer": "请确认目标所有者正确,且你有仓库转让权限",
"cancel-transfer": "请确认存在待处理的转让请求",
"transfer-orgs": "请确认你的组织列表中存在目标组织",
"invite-link": "请确认 owner/repo 参数正确",
"join": "请确认邀请链接有效",
"quit": "请确认 owner/repo 参数正确",
"migrate": "请确认源仓库地址正确且可访问",
"sync-mirror": "请确认仓库为镜像仓库",
"topics": "请确认 owner/repo 参数正确",
"create-topic": "请确认标签名合法",
"delete-topic": "请确认标签名正确",
},
}
// formatInteractiveError wraps a command execution error for display in the
// interactive REPL. It hides raw HTTP/API technical details and provides
// command-specific suggestions. The original error is appended in a dim line.
func formatInteractiveError(group string, s *common.Shortcut, err error) string {
var apiErr *client.APIError
if errors.As(err, &apiErr) {
return formatAPIError(group, s, apiErr)
}
return fmt.Sprintf("✗ %s +%s 执行失败\n 原因:%v", group, s.Name, err)
}
// formatAPIError builds a user-friendly error message from an APIError.
func formatAPIError(group string, s *common.Shortcut, e *client.APIError) string {
var sb strings.Builder
sb.WriteString(fmt.Sprintf("✗ %s +%s 执行失败", group, s.Name))
// Reason — use the API message directly, it's already Chinese in most cases
reason := e.Message
if reason == "" {
reason = fmt.Sprintf("服务器返回错误码 [%v]", e.Code)
}
sb.WriteString(fmt.Sprintf("\n 原因:%s", reason))
// Suggestion — command-specific first, then generic fallback
if suggestion := lookupSuggestion(group, s.Name); suggestion != "" {
sb.WriteString(fmt.Sprintf("\n 建议:%s", suggestion))
}
// Original error in dim text
sb.WriteString(fmt.Sprintf("\n [原始: %s]", e.Error()))
return sb.String()
}
// lookupSuggestion returns a command-specific suggestion, or empty string.
func lookupSuggestion(group, cmd string) string {
if cmds, ok := commandSuggestions[group]; ok {
if suggestion, ok := cmds[cmd]; ok {
return suggestion
}
}
return ""
}
// formatCommandDisplay formats a command for display, e.g. "issue +create --title hello --body world".
func formatCommandDisplay(group string, s *common.Shortcut, args map[string]string) string {
var b strings.Builder

View File

@ -39,9 +39,6 @@ var formHelpStyle = lipgloss.NewStyle().Faint(true)
var formHintStyle = lipgloss.NewStyle().Faint(true).Foreground(lipgloss.Color("11"))
var formLabelStyle = lipgloss.NewStyle().Bold(true)
var formRequiredMark = lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Bold(true)
var formRequiredTag = lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Faint(true)
var formOptionalTag = lipgloss.NewStyle().Faint(true)
var formDefaultTag = lipgloss.NewStyle().Foreground(lipgloss.Color("3")).Faint(true)
// newFormModel creates a new form model from a shortcut's flags.
func newFormModel(group string, shortcut *common.Shortcut, width, height int, prefill map[string]string) formModel {
@ -233,20 +230,6 @@ func (m *formModel) prevField() {
}
}
// fieldMetaTag builds the metadata tag string for a flag (required/optional, default).
func fieldMetaTag(f formField) string {
var parts []string
if f.flag.Required {
parts = append(parts, formRequiredTag.Render("[必填]"))
} else {
parts = append(parts, formOptionalTag.Render("[可选]"))
}
if !f.isBool && f.flag.Default != "" {
parts = append(parts, formDefaultTag.Render(fmt.Sprintf("默认=%s", f.flag.Default)))
}
return strings.Join(parts, " ")
}
// View renders the form.
func (m formModel) View() string {
var sb strings.Builder
@ -262,7 +245,6 @@ func (m formModel) View() string {
if f.flag.Required {
label = label + formRequiredMark.Render(" *")
}
meta := fieldMetaTag(f)
if f.isBool {
// Bool field
@ -270,7 +252,7 @@ func (m formModel) View() string {
if f.boolValue {
check = "[✓]"
}
line := fmt.Sprintf(" %s %s %s", check, label, meta)
line := fmt.Sprintf(" %s %s", check, label)
if i == m.focusIdx {
line = selectedStyle.Render(line)
}
@ -281,16 +263,13 @@ func (m formModel) View() string {
sb.WriteString("\n")
}
} else {
// Text field — show label with meta on first line, input on second
// First line: name * [必填] 默认=1
header := fmt.Sprintf(" %s %s:", label, meta)
// Text field
prompt := fmt.Sprintf(" %s: ", label)
if i == m.focusIdx {
header = formLabelStyle.Render(header)
prompt = formLabelStyle.Render(prompt)
}
sb.WriteString(header)
sb.WriteString("\n")
// Second line: input field, indented
sb.WriteString(fmt.Sprintf(" %s", f.input.View()))
sb.WriteString(prompt)
sb.WriteString(f.input.View())
sb.WriteString("\n")
if f.flag.Usage != "" {
sb.WriteString(formHintStyle.Render(fmt.Sprintf(" %s", f.flag.Usage)))

View File

@ -298,7 +298,7 @@ func (m replModel) updateExecuting(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case execResultMsg:
if msg.err != nil {
m.lastError = formatInteractiveError(msg.group, msg.shortcut, msg.err)
m.lastError = fmt.Sprintf("命令执行失败: %s", msg.err)
m.lastOutput = ""
m.state = stateError
return m, nil

3173
cover.out

File diff suppressed because it is too large Load Diff

694
demo.html Normal file
View File

@ -0,0 +1,694 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GitLink CLI Skills 演示</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, "Microsoft YaHei", sans-serif; background: #f0f2f5; color: #333; }
.header { background: linear-gradient(135deg, #1a1a2e, #16213e); color: #fff; padding: 40px 20px; text-align: center; }
.header h1 { font-size: 28px; margin-bottom: 8px; }
.header p { color: #a0aec0; font-size: 15px; }
.container { max-width: 1100px; margin: 0 auto; padding: 24px 20px; }
/* Tab navigation */
.tabs { display: flex; gap: 8px; margin-bottom: 24px; flex-wrap: wrap; }
.tab { padding: 10px 20px; border-radius: 8px; border: none; cursor: pointer; font-size: 14px;
background: #e2e8f0; color: #4a5568; transition: all 0.2s; }
.tab:hover { background: #cbd5e0; }
.tab.active { background: #1a73e8; color: #fff; }
.tab .badge { display: inline-block; background: rgba(255,255,255,0.3); padding: 0 8px; border-radius: 10px; font-size: 11px; margin-left: 6px; }
/* Panel */
.panel { display: none; }
.panel.active { display: block; }
/* Skill intro */
.skill-intro { background: #fff; border-radius: 12px; padding: 20px 24px; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
.skill-intro h2 { font-size: 20px; color: #1a1a2e; margin-bottom: 6px; }
.skill-intro p { font-size: 14px; color: #555; line-height: 1.7; }
.skill-intro .tags { margin-top: 10px; }
.skill-intro .tag { display: inline-block; background: #e8f0fe; color: #1a73e8; padding: 3px 12px; border-radius: 12px; font-size: 12px; margin: 2px 4px 2px 0; }
.skill-intro .file-link { display: inline-block; margin-top: 8px; font-size: 13px; color: #1a73e8; text-decoration: none; }
.skill-intro .file-link:hover { text-decoration: underline; }
/* Steps */
.step-card { background: #fff; border-radius: 12px; margin-bottom: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); overflow: hidden; }
.step-header { display: flex; align-items: center; padding: 16px 20px; cursor: pointer; transition: background 0.2s; }
.step-header:hover { background: #f8f9fa; }
.step-num { width: 28px; height: 28px; background: #1a73e8; color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; margin-right: 12px; flex-shrink: 0; }
.step-header .title { flex: 1; font-size: 15px; font-weight: 600; color: #1a1a2e; }
.step-header .arrow { font-size: 18px; color: #999; transition: transform 0.2s; }
.step-header.open .arrow { transform: rotate(90deg); }
.step-body { display: none; padding: 0 20px 16px; }
.step-body.open { display: block; }
.step-body .cmd { background: #1e1e2e; color: #cdd6f4; padding: 12px 16px; border-radius: 8px; font-family: "Consolas", monospace; font-size: 13px; overflow-x: auto; margin-bottom: 12px; }
.step-body .cmd .prompt { color: #89b4fa; }
.step-body .output { background: #f8f9fa; border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px 16px; font-family: "Consolas", monospace; font-size: 12px; overflow-x: auto; max-height: 300px; overflow-y: auto; color: #333; white-space: pre; }
.step-body .desc { font-size: 14px; color: #555; margin-bottom: 10px; }
/* Run button */
.run-btn { background: #34a853; color: #fff; border: none; padding: 6px 16px; border-radius: 6px; cursor: pointer; font-size: 13px; margin-top: 8px; }
.run-btn:hover { background: #2d8f47; }
.run-btn:disabled { background: #a0aec0; cursor: not-allowed; }
/* extra info */
.info-box { background: #e8f0fe; border-radius: 8px; padding: 12px 16px; font-size: 13px; color: #1a56db; margin-top: 12px; }
.info-box strong { color: #1a1a2e; }
/* copy */
.copy-btn { float: right; background: none; border: 1px solid #ddd; padding: 3px 10px; border-radius: 4px; cursor: pointer; font-size: 11px; color: #666; }
.copy-btn:hover { background: #f0f0f0; }
@media (max-width: 768px) { .tabs { flex-direction: column; } }
</style>
</head>
<body>
<div class="header">
<h1>GitLink CLI Skills 交互式演示</h1>
<p>点击按钮查看命令执行结果 &mdash; 展示 AI Agent 能自动完成的工作</p>
</div>
<div class="container">
<!-- Tab navigation -->
<div class="tabs" id="tabs">
<button class="tab active" data-tab="release">Release Notes 生成</button>
<button class="tab" data-tab="health">项目健康度报告</button>
<button class="tab" data-tab="triage">Issue 自动分拣</button>
<button class="tab" data-tab="compliance">许可证合规检查</button>
<button class="tab" data-tab="newcomer">新人引导</button>
<button class="tab" data-tab="skill">Skills 文件结构</button>
</div>
<!-- ============= Panel 1: Release Notes ============= -->
<div class="panel active" id="panel-release">
<div class="skill-intro">
<h2>Release Notes 生成</h2>
<p>根据 commit 和 PR 记录自动生成结构化的版本说明,按 Conventional Commits 规范分类。</p>
<div class="tags">
<span class="tag">gitlink-cli release +list</span>
<span class="tag">gitlink-cli pr +list</span>
<span class="tag">gitlink-cli release +create</span>
</div>
<a class="file-link" href="../skills/gitlink-release-auto/examples/release-notes-workflow.md" target="_blank">查看 SKILL.md →</a>
</div>
<!-- Step 1 -->
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">1</span>
<span class="title">获取最新 Release</span>
<span class="arrow"></span>
</div>
<div class="step-body" id="release-step1-body">
<div class="desc">查看项目当前最新的 Release 版本信息,确定上次发布的位置。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli release +list --owner z2_cc --repo gitlink-cli --format json</div>
<div class="output" id="release-step1-output">{
"data": [
{
"tag_name": "v1.0.0",
"name": "v1.0.0",
"body": "初始版本发布",
"created_at": "2026-05-25"
}
]
}</div>
</div>
</div>
<!-- Step 2 -->
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">2</span>
<span class="title">获取提交记录</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">获取自上次发布以来的所有 commit 记录,用于生成变更日志。</div>
<div class="cmd"><span class="prompt">$</span> git log v1.0.0..HEAD --format="%H %s %an %ad" --date=short</div>
<div class="output">a4587f9 feat: add webhook +failed and +task-view commands wqer 2026-06-04
37a0f21 docs: add release notes workflow example wqer 2026-06-17
6c0ad3b feat: add three new skills wqer 2026-06-17
d1cc68b docs: add workflow examples wqer 2026-06-17
9a51db0 feat: add wiki and snippet skills wqer 2026-06-17</div>
</div>
</div>
<!-- Step 3 -->
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">3</span>
<span class="title">获取 PR 列表</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">获取本期合并的 PR 列表,用于补充 Release Notes 中的 PR 引用。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state merged --limit 10 --format json</div>
<div class="output">{
"data": {
"pull_requests": [
{ "number": 31, "title": "fix: normalize issue list output", "state": "merged" }
]
}
}</div>
</div>
</div>
<!-- Step 4 -->
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">4</span>
<span class="title">生成 Release Notes</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">AI 分析数据,按规范生成结构化的发布说明。</div>
<div class="info-box">
<strong>AI 生成结果:</strong><br><br>
## v1.3.0 (2026-06-17)<br><br>
### ✨ 新功能<br>
- 新增 Webhook 投递监控failed / task-view<br>
- 新增 Wiki 管理 Skill<br>
- 新增代码片段管理 Skill<br><br>
### 📦 其他变更<br>
- 更新文档和工作流示例
</div>
</div>
</div>
</div>
<!-- ============= Panel 2: 项目健康度 ============= -->
<div class="panel" id="panel-health">
<div class="skill-intro">
<h2>项目健康度报告</h2>
<p>统计 Issue 响应时间、PR 合并效率、贡献者活跃度,生成项目健康度分析报告。</p>
<div class="tags">
<span class="tag">gitlink-cli repo +info</span>
<span class="tag">gitlink-cli issue +list</span>
<span class="tag">gitlink-cli pr +list</span>
<span class="tag">gitlink-cli commit +list</span>
</div>
<a class="file-link" href="../skills/gitlink-project-health/examples/health-report-workflow.md" target="_blank">查看 SKILL.md →</a>
</div>
<!-- Step 1 -->
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">1</span>
<span class="title">获取项目基本信息</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">获取仓库的基本信息Star 数、Fork 数、描述等。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli repo +info --owner z2_cc --repo gitlink-cli --format json</div>
<div class="output">{
"data": {
"full_name": "z2_cc/gitlink-cli",
"default_branch": "master",
"issues_count": 12,
"pull_requests_count": 5,
"forked_count": 0,
"watchers_count": 1,
"size": "2.3 MB"
}
}</div>
</div>
</div>
<!-- Step 2 -->
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">2</span>
<span class="title">统计 Issue</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">获取 Issue 统计数据:总数、打开数、关闭数。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state all --format json</div>
<div class="output">{
"data": {
"issues": [
{ "number": 10, "subject": "新增 Shortcut: Wiki 管理", "status_id": 5 },
{ "number": 12, "subject": "新增 Shortcut: 代码片段", "status_id": 5 },
{ "number": 14, "subject": "Webhook 投递监控", "status_id": 1 },
{ "number": 15, "subject": "新增 Webhook 投递监控", "status_id": 1 }
],
"closed_count": 3,
"has_created_issues": true
}
}</div>
</div>
</div>
<!-- Step 3 -->
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">3</span>
<span class="title">统计 PR</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">获取 PR 统计数据:总数、打开数、已合并数。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state all --format json</div>
<div class="output">{
"data": {
"pull_requests": [
{ "number": 31, "title": "fix: normalize issue list output", "state": "merged" }
]
}
}</div>
</div>
</div>
<!-- Step 4 -->
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">4</span>
<span class="title">查看提交活跃度</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">获取近期提交记录,分析贡献者活跃度和提交频率。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli commit +list --owner z2_cc --repo gitlink-cli --limit 10</div>
<div class="output">[
{ "sha": "a4587f9", "author": "wqer", "message": "feat: add webhook +failed..." },
{ "sha": "37a0f21", "author": "wqer", "message": "docs: add release notes..." },
{ "sha": "6c0ad3b", "author": "wqer", "message": "feat: add three new skills" },
{ "sha": "9a51db0", "author": "wqer", "message": "feat: add wiki and snippet skills" }
]</div>
</div>
</div>
<!-- Result summary -->
<div class="step-card">
<div class="step-header" onclick="toggle(this)" style="background:#e8f0fe;">
<span class="step-num" style="background:#34a853;">R</span>
<span class="title" style="color:#1a73e8;">AI 生成的健康度报告</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="info-box">
<strong>项目健康度报告</strong><br><br>
<strong>基本信息</strong><br>
- 项目z2_cc/gitlink-cli<br>
- 默认分支master<br><br>
<strong>Issue 状况</strong><br>
- 总 Issue 数12<br>
- 已关闭3<br>
- 打开中2<br><br>
<strong>PR 状况</strong><br>
- 总 PR 数5<br>
- 已合并1<br>
- 打开中0<br><br>
<strong>活跃度</strong><br>
- 近期提交15+ 次<br>
- 活跃贡献者1 人<br><br>
🟢 总体评价:项目健康
</div>
</div>
</div>
</div>
<!-- ============= Panel 3: Issue 自动分拣 ============= -->
<div class="panel" id="panel-triage">
<div class="skill-intro">
<h2>Issue 自动分拣</h2>
<p>根据 Issue 内容自动分类Bug / 功能 / 文档)、打标签、分配责任人、添加引导评论。</p>
<div class="tags">
<span class="tag">gitlink-cli issue +list</span>
<span class="tag">gitlink-cli issue +view</span>
<span class="tag">gitlink-cli issue +comment</span>
</div>
<a class="file-link" href="../skills/gitlink-issue-triage/examples/triage-workflow.md" target="_blank">查看 SKILL.md →</a>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">1</span>
<span class="title">获取待处理 Issue</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">列出所有打开的 Issue筛选需要分类的任务。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state open --format json</div>
<div class="output">{
"issues": [
{ "number": 14, "subject": "新增 Shortcut: Webhook 投递监控", "status_id": 1 },
{ "number": 15, "subject": "Webhook 投递监控failed + task-view", "status_id": 1 }
]
}</div>
</div>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">2</span>
<span class="title">分析 Issue 内容</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">AI 根据标题和描述关键词判断 Issue 类别。</div>
<div class="info-box">
<strong>分类规则示例:</strong><br>
"报错、错误、bug" → Bug<br>
"建议、希望" → 功能需求<br>
"文档、拼写" → 文档<br>
"请问、怎么" → 问题咨询
</div>
</div>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">3</span>
<span class="title">添加分类评论</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">AI 根据分类结果自动添加引导评论。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 14 --body "感谢提交 Issue已自动分类为 **功能需求**..."</div>
<div class="info-box">
<strong>AI 自动生成的评论示例:</strong><br><br>
感谢提交 Issue已自动分类为 <strong>功能需求</strong><br><br>
请补充以下信息:<br>
1. 这个功能解决了什么场景的问题?<br>
2. 预期的行为是什么?<br>
3. 是否有参考实现?
</div>
</div>
</div>
</div>
<!-- ============= Panel: 许可证合规检查 ============= -->
<div class="panel" id="panel-compliance">
<div class="skill-intro">
<h2>许可证合规检查</h2>
<p>扫描仓库的许可证合规性和敏感信息泄露风险:识别 LICENSE、核对依赖兼容性、批量扫描密钥 / Token / 数据库连接串,生成结构化合规报告与修复建议。</p>
<div class="tags">
<span class="tag">gitlink-cli repo +info</span>
<span class="tag">gitlink-cli api GET .../raw</span>
<span class="tag">git clone + git grep</span>
<span class="tag">gitlink-cli api GET .../sub_entries</span>
</div>
<a class="file-link" href="../skills/gitlink-compliance/examples/compliance-check-workflow.md" target="_blank">查看 SKILL.md →</a>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">1</span>
<span class="title">获取仓库元信息</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">确认 owner/repo、默认分支以及平台返回的许可证字段。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli repo +info --owner z2_cc --repo gitlink-cli --format json</div>
<div class="output">{
"data": {
"full_name": "z2_cc/gitlink-cli",
"default_branch": "master",
"license": null
}
}</div>
</div>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">2</span>
<span class="title">识别 LICENSE 类型</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">读取根目录 LICENSE 文件内容按关键词识别许可证类型MIT / Apache-2.0 / MulanPSL-2 等)。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli api GET /z2_cc/gitlink-cli/raw/master/LICENSE</div>
<div class="output">MIT License
Copyright (c) 2026 Gitlink
Permission is hereby granted, free of charge ...
... → 识别为 MIT 许可证</div>
</div>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">3</span>
<span class="title">依赖合规分析</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">读取依赖声明文件,逐依赖对照兼容性矩阵评估与项目主许可证的兼容性。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli api GET /z2_cc/gitlink-cli/raw/master/go.mod</div>
<div class="output">module github.com/gitlink/gitlink-cli
go 1.21
require (
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
)
→ 依赖均为 MIT 兼容许可证 ✅</div>
</div>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">4</span>
<span class="title">敏感信息扫描(批量)</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">clone 仓库后用 git grep 对高危特征做正则扫描AWS Key、GitHub Token、私钥、数据库连接串等。命令中的 AKIA[0-9A-Z]{16} 等是正则模式,非真实凭据。</div>
<div class="cmd"><span class="prompt">$</span> git clone https://www.gitlink.org.cn/z2_cc/gitlink-cli.git /tmp/gitlink-cli-scan<br><span class="prompt">$</span> cd /tmp/gitlink-cli-scan<br><span class="prompt">$</span> git grep -nE 'AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|glpat-[A-Za-z0-9\-_]{20}|-----BEGIN .*PRIVATE KEY-----' HEAD</div>
<div class="output">examples/demo.go:45:token: "example_token_for_demo" # 🟢 低风险(占位假值)</div>
<div class="info-box">
<strong>风险分级:</strong><br>
🔴 严重:真实密钥 / Token / 私钥 → 立即撤销并清理 Git 历史<br>
🟠 高:数据库连接串硬编码 → 改用环境变量<br>
🟡 中:内网地址 / 测试账号 → 评估影响<br>
🟢 低:疑似但可能为示例 → 人工确认
</div>
</div>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)" style="background:#e8f0fe;">
<span class="step-num" style="background:#34a853;">R</span>
<span class="title" style="color:#1a73e8;">AI 生成的合规检查报告</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="info-box">
<strong>⚖️ 合规检查报告 — z2_cc/gitlink-cli</strong><br><br>
📋 项目许可证MIT<br><br>
<strong>🔴 必须修复</strong><br>
- 无<br><br>
<strong>🟡 建议修复</strong><br>
- 缺少 SECURITY.md → 添加安全披露流程<br><br>
<strong>🔴 敏感信息扫描</strong><br>
- 🟢 examples/demo.go:45 — token 占位假值(加注释说明即可)<br><br>
<strong>📊 合规评分</strong><br>
📜 许可证 ✅ 🏷️ 版权声明 ⚠️ 📦 依赖合规 ✅ 🔒 安全策略 ⚠️ 🔒 敏感信息管控 ✅<br>
<strong>总体合规评分82/100</strong>
</div>
</div>
</div>
</div>
<!-- ============= Panel: 新人引导 ============= -->
<div class="panel" id="panel-newcomer">
<div class="skill-intro">
<h2>新人引导</h2>
<p>为 good-first-issue 自动添加引导评论,降低新贡献者参与门槛:识别入门标签、按 Issue 类型选模板、用标记串幂等去重不刷屏。</p>
<div class="tags">
<span class="tag">gitlink-cli issue +list</span>
<span class="tag">gitlink-cli issue +view</span>
<span class="tag">gitlink-cli api GET .../journals</span>
<span class="tag">gitlink-cli issue +comment</span>
</div>
<a class="file-link" href="../skills/gitlink-newcomer-guide/examples/newcomer-guide-workflow.md" target="_blank">查看 SKILL.md →</a>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">1</span>
<span class="title">查找 good-first-issue</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">列出开放 Issue用返回的 tags[].name 匹配入门标签good-first-issue / 新手 / help-wanted 等),并按 status_id ∈ {1,2} 二次过滤。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state open --format json</div>
<div class="output">{
"issues": [
{
"number": 10,
"subject": "新增 Shortcut: Wiki 管理",
"status_id": 1,
"tags": [{ "name": "good first issue" }],
"assigners": []
}
]
}</div>
</div>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">2</span>
<span class="title">查看 Issue 详情判断类型</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">查看 Issue 详情根据描述判断类型Bug / 功能需求 / 文档),选择对应的引导评论模板。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli issue +view --owner z2_cc --repo gitlink-cli --number 10 --format json</div>
<div class="info-box">
<strong>类型判定规则:</strong><br>
"报错、bug" → Bug 模板<br>
"建议、希望、新增" → 功能需求模板<br>
"文档、拼写" → 文档模板
</div>
</div>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">3</span>
<span class="title">幂等去重检查</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">读取已有评论,扫描是否含标记串 gitlink-newcomer-guide:v1命中则跳过避免重复刷屏。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli api GET /v1/z2_cc/gitlink-cli/issues/10/journals --format json</div>
<div class="output">{
"data": { "journals": [] }
}
→ 未命中标记串,继续添加引导评论</div>
</div>
</div>
<div class="step-card">
<div class="step-header" onclick="toggle(this)">
<span class="step-num">4</span>
<span class="title">添加引导评论(写操作,先确认)</span>
<span class="arrow"></span>
</div>
<div class="step-body">
<div class="desc">写操作,执行前确认用户意图。评论末尾带上标记串,便于下次去重。</div>
<div class="cmd"><span class="prompt">$</span> gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 10 --body "..."</div>
<div class="info-box">
<strong>AI 自动生成的引导评论:</strong><br><br>
你好!欢迎参与贡献 🎉<br><br>
这个 Issue 被标记为 <strong>good first issue</strong>,非常适合作为你的第一个贡献。<br><br>
<strong>如何开始</strong><br>
1. 在评论区留言"我想认领",我们会把你添加到 Assignee<br>
2. Fork 本仓库并创建你的功能分支<br>
3. 修复问题后提交 Pull Request<br><br>
祝你编码愉快!<br>
&lt;!-- gitlink-newcomer-guide:v1 --&gt;
</div>
</div>
</div>
</div>
<!-- ============= Panel 4: Skills 结构 ============= -->
<div class="panel" id="panel-skill">
<div class="skill-intro">
<h2>Skills 文件结构总览</h2>
<p>展示所有新增和更新的 Skill 文件,以及每个 Skill 所包含的内容。</p>
</div>
<div style="display:grid; grid-template-columns: repeat(2, 1fr); gap:16px;">
<div style="background:#fff; border-radius:12px; padding:20px; box-shadow:0 2px 8px rgba(0,0,0,0.06); border-left:4px solid #34a853;">
<h3 style="font-size:16px; margin-bottom:4px;">Release Notes 生成</h3>
<p style="font-size:13px; color:#555;">根据 commit/PR 生成版本说明</p>
<div style="font-size:12px; color:#999; margin-top:8px;">
SKILL.md + examples/<br>
<span style="color:#34a853;">涉及命令release +list, pr +list</span>
</div>
</div>
<div style="background:#fff; border-radius:12px; padding:20px; box-shadow:0 2px 8px rgba(0,0,0,0.06); border-left:4px solid #34a853;">
<h3 style="font-size:16px; margin-bottom:4px;">项目健康度报告</h3>
<p style="font-size:13px; color:#555;">统计 Issue/PR/commit 数据</p>
<div style="font-size:12px; color:#999; margin-top:8px;">
SKILL.md + examples/<br>
<span style="color:#34a853;">涉及命令repo +info, issue +list, pr +list, commit +list</span>
</div>
</div>
<div style="background:#fff; border-radius:12px; padding:20px; box-shadow:0 2px 8px rgba(0,0,0,0.06); border-left:4px solid #34a853;">
<h3 style="font-size:16px; margin-bottom:4px;">Issue 自动分拣</h3>
<p style="font-size:13px; color:#555;">自动分类 Issue 并添加评论</p>
<div style="font-size:12px; color:#999; margin-top:8px;">
SKILL.md + examples/<br>
<span style="color:#34a853;">涉及命令issue +list, issue +view, issue +comment</span>
</div>
</div>
<div style="background:#fff; border-radius:12px; padding:20px; box-shadow:0 2px 8px rgba(0,0,0,0.06); border-left:4px solid #34a853;">
<h3 style="font-size:16px; margin-bottom:4px;">许可证合规检查</h3>
<p style="font-size:13px; color:#555;">许可证 / 依赖 / 敏感信息扫描</p>
<div style="font-size:12px; color:#999; margin-top:8px;">
SKILL.md + REFERENCE.md + examples/<br>
<span style="color:#34a853;">涉及命令repo +info, api raw, git grep</span>
</div>
</div>
<div style="background:#fff; border-radius:12px; padding:20px; box-shadow:0 2px 8px rgba(0,0,0,0.06); border-left:4px solid #34a853;">
<h3 style="font-size:16px; margin-bottom:4px;">新人引导</h3>
<p style="font-size:13px; color:#555;">为 good-first-issue 添加引导</p>
<div style="font-size:12px; color:#999; margin-top:8px;">
SKILL.md + examples/<br>
<span style="color:#34a853;">涉及命令issue +view, issue +comment</span>
</div>
</div>
</div>
<div style="margin-top:20px; background:#fff; border-radius:12px; padding:20px; box-shadow:0 2px 8px rgba(0,0,0,0.06);">
<h3 style="font-size:16px; margin-bottom:12px;">新建和更新的 Skill 文件</h3>
<table style="width:100%; border-collapse:collapse; font-size:14px;">
<thead><tr style="background:#f8f9fa;"><th style="text-align:left; padding:8px 12px;">文件路径</th><th style="text-align:left; padding:8px 12px;">状态</th></tr></thead>
<tbody>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-release-auto/examples/release-notes-workflow.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-project-health/SKILL.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-project-health/examples/health-report-workflow.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-issue-triage/SKILL.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-issue-triage/examples/triage-workflow.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-compliance/SKILL.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-compliance/REFERENCE.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-compliance/examples/compliance-check-workflow.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-newcomer-guide/SKILL.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-newcomer-guide/examples/newcomer-guide-workflow.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-wiki/SKILL.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-snippet/SKILL.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#34a853;">新增</td></tr>
<tr><td style="padding:8px 12px; border-top:1px solid #eee;">skills/gitlink-webhook/SKILL.md</td><td style="padding:8px 12px; border-top:1px solid #eee; color:#fbbc04;">更新</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
function toggle(el) {
el.classList.toggle('open');
var body = el.nextElementSibling;
body.classList.toggle('open');
}
// Tab switching
document.querySelectorAll('.tab').forEach(function(tab) {
tab.addEventListener('click', function() {
document.querySelectorAll('.tab').forEach(function(t) { t.classList.remove('active'); });
document.querySelectorAll('.panel').forEach(function(p) { p.classList.remove('active'); });
this.classList.add('active');
document.getElementById('panel-' + this.dataset.tab).classList.add('active');
});
});
</script>
</body>
</html>

View File

@ -1,308 +0,0 @@
# Release Notes — gitlink-cli
> 官方 [GitLink](https://www.gitlink.org.cn) 命令行工具,面向人类用户和 AI Agent。
> 支持 macOS、Linux 和 Windows覆盖仓库管理、Issue 跟踪、Pull Request、Webhook、CI/CD 及 AI 驱动的工作流。
---
## v0.2.0 (2026-06-17) — 交互式 REPL 与输出大重构
### 里程碑亮点
- ✨ **交互式 REPL 模式**:新增基于 Bubble Tea TUI 框架的命令面板、参数表单与滚动视口
- 📊 **输出系统重构**:统一表格渲染,终结 JSON 回退;支持嵌套对象层级展开、值截断、动态列合并
- 🌏 **全命令中文覆盖**:全部 25+ 命令组的子命令描述、参数注释、帮助文本完成中文化
- 🐛 **P1-P4 缺陷修复**:修复 16 项实测发现的问题,涉及 collaborator、branch、file、tag、interactive 等多个模块
- 🧩 **3 个新 AI Agent Skill**issue-triage、project-health、newcomer-guide
- 🧪 **大规模测试**新增交互模式冒烟测试、output 表格渲染单元测试、hook-runner 测试等
### 新增功能
#### 交互式 REPL (Bubble Tea TUI)
- **命令面板** (`/` 快捷键唤起):实时搜索 80+ 命令,支持模糊匹配
- **参数表单**:选中命令后自动弹出表单填写 flags支持必填/可选参数
- **滚动视口**:长输出支持上下滚动浏览,不再截断
- **默认 table 输出**REPL 中统一使用表格格式,告别 JSON 裸输出
- **Ctrl+C/Esc**:正确的退出与返回行为
- **Smoke Test**:所有注册命令执行不 panic 的自动化验证
#### 输出系统重构
- **`printSliceTable` 增强**:表头取自所有行的字段并集,不再仅依赖第一行
- **嵌套 Map 详情视图**:单对象详情(如 `tag +view`、`repo +info`)渲染为可读层级表格,`└` 缩进展开子字段,不再回退 JSON
- **原生 Map Slice 表格化**`[]map[string]string` 等本地构造数据也渲染为表格,不再显示 `[N items]`
- **值截断与列限制**超长值URL、SHA、commit message自动截断核心列优先固定
- **已废弃**`hasOnlyNestedMaps` JSON 回退逻辑移除
#### Skill 与 Workflow
- 新增 3 个 AI Agent Skill
- `gitlink-issue-triage` — Issue 分类与优先级评估
- `gitlink-project-health` — 项目健康度洞察
- `gitlink-newcomer-guide` — 新贡献者引导
- `gitlink-webhook` Skill新增 `+failed`、`+task-view` 命令
- 新增 `gitlink-wiki`、`gitlink-snippet` Skill
- 新增 Workflow 自动化示例issue-triage、project-health、newcomer-guide
#### 命令增强
- **Webhook**`+failed` 查看失败投递、`+task-view` 支持 UUID/数字 ID 双查询、`--limit` 分页支持
- **Shortcuts**:导出 `GetAllShortcuts` / `GetDescriptions` 供交互模式消费
### Bug 修复
| 模块 | 问题 | 修复 |
|------|------|------|
| **collaborator** | `change-role`/`batch-role` 请求体格式错误导致"未找到用户" | 改为 `{user_id: 整数, role: string}` 格式;自动解析用户名到数字 ID |
| **branch** | protect/unprotect 接口路径误加 `/v1` 导致 404 | 走无 `/v1` 老接口 |
| **branch** | `+list` 字段过多导致表格不稳定 | 投影到核心列name/protected/last_commit/commit_time |
| **file** | `+get` 端点调用了错误 API | 改为 `/entries` 提取单文件元信息 |
| **file** | `+tree --recursive` 参数被 API 拒绝 | 移除无效 flag |
| **file** | `+create`/`+update`/`+delete` 缺少必需参数 | 补 `--new-branch`、`--sha` 改为必填 |
| **file** | `+replace` 端点已废弃 | 移除该命令 |
| **tag** | `+view` 调用了不存在端点导致"标签不存在" | 改用列表过滤,新增 `findTagByName` |
| **interactive** | 带可选参数的命令跳过表单直接执行 | 改为"有任何 flag 都弹表单" |
| **interactive** | nil Client 导致 panic | `NewRuntimeContext` 初始化 |
| **interactive** | `/` 键响应延迟 | 立即响应而非等待后续输入 |
| **output** | 原生 `[]map[string]string` 不识别为表格 | reflect 统一处理 |
| **output** | 单对象嵌套 Map 回退 JSON | 层级表格展开 |
### 文档与国际化
- **全部 25+ 命令组描述中文化**repo / pr / issue / branch / tag / file / wiki / webhook / snippet / user / org / ci / search / label / milestone / release / commit / collaborator / attachment / dataset / template / util / sshkey / shortcut / interactive
- **Shortcuts 模块详细中文注释**参数映射CLI→API、批处理模式、设计决策
- **P1-P4 缺陷中文标记**issue +create --label 遗漏、hardcoded 'master' 等已知问题文档化
- **交互模式设计文档**:实现计划 + 命令面板设计规格
### 基础设施
- **依赖**:引入 `bubbletea`、`bubbles`、`huh` TUI 框架
- **CI**DevOps 流水线(构建+验证)
- **测试**interactive smoke test、output 表格渲染回归测试、tag `+view` 单元测试、hook-runner 单元测试
### 贡献者
自 v0.1.18 以来的贡献者(按字母顺序):
2403_89190320, Leo77, Mengz, Tiger, s2_cc, wangyue789, wqer, yangsai01, 刘焱, 赵昌
---
## v0.1.18 (2026-05-19) — Webhook 集成与 Skills 扩展
> 这也是 v0.2.0 之前带交互式 REPL 内测功能的过渡版本。
### 核心变更
- **交互模式 MVP**:首次合入 Bubble Tea REPL 基础框架(命令执行器 + flag 解析 + TUI 入口),但随后回退(`Revert "Add TUI foundation"`),留待 v0.2.0 正式发布
- **npm 安装**:修复 Windows 二进制缺失问题,改进安装后诊断
---
## v0.1.17 (2026-05-17) — Skills 生态与包管理器支持
### 新功能
- **3 个新 Skill**`gitlink-code-review`(代码审查)、`gitlink-insight`(仓库洞察)、`gitlink-compliance`(合规检查)
- **2 个自动化 Skill**`gitlink-release-auto`(自动发版)、`gitlink-commit-quality`(提交信息规范检查)
- **包管理器支持**HomebrewmacOS/Linux、ScoopWindows、ChocolateyWindows
- **CI**GitHub Release 工作流与 npm 自动发布
- **npm 安装增强**:校验和验证、错误消息改进、版本检查
### 命令增强
- **PR**:新增 `+review` 审查快捷、`+patchset` 补丁集版本切换
- **PR**`+comment` 评论 CRUD
- **Issue**`+batch-close` 批量关闭dry-run 支持)
- **PR/Issue**:统一使用 project-level 编号替代数据库 ID
### Bug 修复
- **Issue**: `+list` 输出使用项目级 Issue 编号
- **PR**: 统一使用 `pull_request_number` 替代 `pull_request_id`
- **Issue**: `update` 时保留描述字段
- **npm**: Windows 二进制缺失导致静默退出
### 文档
- Skills REFERENCE.md 参考文档
- README 更新至 v0.1.1712 Skills、npm 一键安装)
- Fork-based PR 工作流指南
- Skill 工具边界规则(防止在 GitLink 上误用 gh/hub
---
## v0.1.14 (2026-05-17) — 全 API 覆盖里程碑
### 新功能
- **40+ 新命令 shortcut**
- **Repo**22 个新 shortcutsettings/stats/social/transfer/invite/migrate/topics
- **User**22 个新 shortcutmessages/stats/transfers/settings/feedback
- **PR**comments CRUD、commits、reopen、update
- **Issue**comments CRUD、delete、batch-update、batch-destroy
- **Branch**all/default/restore**Release**edit/update
- **协作**org team-projects**File**batch/entries/replace
- **CI 流水线**、**Wiki 导入/导出**、**Repo 加入/退出/迁移/话题**
- **Util**、**Dataset**、**Template**、**Attachment** 快捷组
- **代码片段管理**`snippet +list/+view/+create/+delete`
- **看板**`board +view/+columns/+move`
- **OAuth2 认证**、**颜色检测与 CJK 宽度支持**
- **Wiki 命令改用 Git 操作**`+list/+view/+create/+update/+delete` 重构为 Git-based
### 跨平台
- **Windows (x64/arm64)** 完整支持
- 终端颜色自动检测与中文字符宽度适配
### Skills
- **6 个新 Skills**`gitlink-repo`、`gitlink-issue`、`gitlink-pr`、`gitlink-ci`、`gitlink-search`、`gitlink-workflow`
- **Skill 架构升级**Anthropic Agent Skills 标准
- **pm / org / user / release / branch** 等 Skill 持续完善
### 基础设施
- npm 包 `@gitlink-ai/cli` 分发上线
- `GITLINK_TOKEN` 环境变量支持非交互式认证
- `gitlink-cli-install-skills` 跨平台安装命令
### 项目健康
- 新增 CONTRIBUTORS 章节展示项目贡献者
- 许可证切换至 MulanPSL-2.0(木兰宽松许可证)
- README 中英双语
---
## v0.1.8 ~ v0.1.13 (2026-04-07 ~ 2026-04-15) — 功能夯实
### v0.1.13 (2026-04-15)
- **npm 安装方案**:修复 GitHub Release asset 匹配回退与相对 URL 拼接问题
- 改进 release 创建时默认 `target_commitish=master`
- Issue 创建默认 `priority_id=2`
### v0.1.12 (2026-04-15)
- Webhook 快捷命令组正式合入
- `hook-runner` 集成为 `webhook` 子命令
- 新增 `--limit` 标志与 UUID 显示改进
### v0.1.11 (2026-04-08)
- **PR 审查**`+review` 审查提交
- **PR 补丁集**`+patchset-versions` 版本切换
- 3 个新 Skills`gitlink-code-review`、`gitlink-insight`、`gitlink-compliance`
### v0.1.10 (2026-04-08)
- 2 个自动化 Skill`gitlink-release-auto`、`gitlink-commit-quality`
- Webhook 端点测试修复
### v0.1.9 (2026-04-07)
- **Webhook shortcut 组**正式版
- Skills 文档完善
### v0.1.8 (2026-04-07)
- **Branch Skill**`gitlink-branch` 保护分支管理
- PR `+comment` 快捷
- Issue `+batch-close` 批量关闭
- Issue v1 API 迁移,使用 `project_issues_index` 替代数据库 ID
- 修复 Issue 描述 update 丢失问题
---
## v0.1.0-skill-test (2026-04-04) — Skill 概念验证
- Skill PR 全流程测试
- 首个 Skill 原型验证
- PR 创建、合入工作流测试
---
## v0.0.1-test-del / initial (2026-04-03) — 项目初始化
- `github.com/gitlink-org/gitlink-cli` 项目启动
- 基础 CLI 框架Cobra
- 初始命令auth、repo、issue、pr
- npm 分发基础 (`@gitlink-ai/cli`)
- Cookie-based 登录与 token 认证
---
## 统计一览
| 版本 | 日期 | 新增文件 | 代码变更 | 贡献者 |
|------|------|----------|----------|--------|
| init → v0.1.8 | 2026-04 | ~30 | ~8k | 5 |
| v0.1.8 → v0.1.14 | 2026-04~05 | ~60 | ~15k | 8 |
| v0.1.14 → v0.1.18 | 2026-05 | ~22 | +514/-1015 | 4 |
| v0.1.18 → v0.2.0 | 2026-05~06 | 114 | +24531/-324 | 10 |
## Skills 一览
| Skill | 用途 | 引入版本 |
|-------|------|----------|
| `gitlink-repo` | 仓库管理 | v0.1.14 |
| `gitlink-issue` | Issue 跟踪 | v0.1.14 |
| `gitlink-pr` | Pull Request 管理 | v0.1.14 |
| `gitlink-ci` | CI/CD 流水线 | v0.1.14 |
| `gitlink-search` | 全局搜索 | v0.1.14 |
| `gitlink-workflow` | 工作流自动化 | v0.1.14 |
| `gitlink-branch` | 保护分支管理 | v0.1.8 |
| `gitlink-pm` | 项目管理 | v0.1.14 |
| `gitlink-org` | 组织管理 | v0.1.14 |
| `gitlink-user` | 用户管理 | v0.1.14 |
| `gitlink-release` | 发布管理 | v0.1.14 |
| `gitlink-code-review` | 代码审查 | v0.1.11 |
| `gitlink-insight` | 仓库洞察 | v0.1.11 |
| `gitlink-compliance` | 合规检查 | v0.1.11 |
| `gitlink-release-auto` | 自动发版 | v0.1.10 |
| `gitlink-commit-quality` | 提交信息规范 | v0.1.10 |
| `gitlink-webhook` | Webhook 管理 | v0.1.9 |
| `gitlink-wiki` | Wiki 管理 | v0.2.0 |
| `gitlink-snippet` | 代码片段管理 | v0.2.0 |
| `gitlink-issue-triage` | Issue 分类与优先级 | v0.2.0 |
| `gitlink-project-health` | 项目健康度 | v0.2.0 |
| `gitlink-newcomer-guide` | 新贡献者引导 | v0.2.0 |
| `gitlink-shared` | 共享工具库 | v0.2.0 |
| `gitlink-workflow` | 工作流定义 | v0.2.0 |
---
## 升级指南
### v0.1.x → v0.2.0
- **交互模式**:运行 `gitlink-cli interactive``gitlink-cli tui` 进入 REPL
- **输出格式**v0.2.0 默认输出格式为 table如需 JSON 请使用 `--output json``--json`
- **File 命令**`+replace` 已移除,请改用 `+create`/`+update`
- **Tag 命令**`+view` 行为变更(从单端点改为列表过滤),功能一致
### 首次安装
```bash
# npm (推荐)
npm install -g @gitlink-ai/cli
# macOS (Homebrew)
brew tap gitlink-ai/tap
brew install gitlink-cli
# Windows (Scoop)
scoop bucket add gitlink https://github.com/gitlink-ai/scoop-bucket
scoop install gitlink-cli
# Windows (Chocolatey)
choco install gitlink-cli
```
---
> 完整的提交历史请参阅 [CHANGELOG](./changes/) 目录。
>
> 如发现任何问题,欢迎在 [GitLink Issues](https://www.gitlink.org.cn/Gitlink/gitlink-cli/issues) 反馈。

View File

@ -1,116 +0,0 @@
# 变更说明汇总
> 本文件汇总 GitLink CLI 智能化能力提升项目所有变更,按子任务分类。
> 最后更新2026-07-07
---
## 子任务一CLI 能力扩展
### 新增 Shortcut 命令组
在原有 10 个命令组branch/ci/common/issue/org/pr/release/repo/search/user基础上新增 13 个命令组:
| 命令组 | 子命令数 | 代码行数 | 单元测试 | 作者 | 说明 |
|--------|---------|---------|---------|------|------|
| webhook | 20 | 533 | ✅ | Mengz | Webhook 管理(增删改查+测试) |
| wiki | 13 | 555 | ✅ | 赵昌 | 仓库 Wiki 页面管理 |
| snippet | 9 | 271 | ✅ | 赵昌 | 代码片段管理 |
| file | 18 | 490 | ❌ | 刘焱 | 文件管理(上传/下载/批量推送) |
| collaborator | 13 | 69 | ✅ | 刘焱 | 协作者管理 |
| milestone | 14 | 224 | ❌ | 刘焱 | 里程碑管理 |
| commit | 13 | 172 | ❌ | 刘焱 | 提交记录查询 |
| template | 10 | 150 | ❌ | 刘焱 | 模板管理(导入/导出) |
| label | 11 | 218 | ❌ | 刘焱 | 标签管理 |
| dataset | 9 | 123 | ❌ | 刘焱 | 数据集管理 |
| tag | 7 | 138 | ✅ | 刘焱 | 标签Release Tag管理 |
| sshkey | 8 | 96 | ❌ | 刘焱 | SSH 公钥管理 |
| attachment | 4 | 53 | ❌ | 刘焱 | 附件管理 |
| util | 3 | 46 | ❌ | 刘焱 | 通用工具函数 |
**合计**:新增 149 个子命令,约 3000 行 Go 代码6 个命令组配有单元测试。
### 已有命令组扩展
对原有命令组也进行了功能增强:
- `ci` — 新增 save-yaml、run-pipeline、delete-pipeline 等 DevOps 流水线管理命令
- `pr` — 新增 batch-merge、batch-close、version-diff、versions 等批量操作命令
- `issue` — 新增 batch-update 批量更新命令
- `repo` — 新增 code-stats、contributors-stat 等统计分析命令
详细变更说明:[webhook-shortcut.md](./webhook-shortcut.md)
---
## 子任务二AI Agent Skills
### 新增 Skills
在原有 Skills 基础上,团队新增 16 个自定义 Skill
| Skill | 作者 | 说明 |
|-------|------|------|
| gitlink-community-ops | 赵昌 | 社区运营自动化Issue 分拣→周报→Release Notes |
| gitlink-quality-gate | 赵昌 | 代码质量门禁PR 审查→CI 检查→门禁决策) |
| gitlink-project-health | 赵昌 | 项目健康度分析 |
| gitlink-issue-triage | 赵昌 | Issue 自动分拣 |
| gitlink-newcomer-guide | 赵昌 | 新人引导 |
| gitlink-pr-deep-review | 赵昌 | PR 深度审查 |
| gitlink-research-hotspot | 赵昌 | 科研热点追踪与知识图谱 |
| gitlink-research-insight | 赵昌 | 科研项目洞悉 |
| gitlink-snippet | 赵昌 | 代码片段 Skill |
| gitlink-wiki | 赵昌 | Wiki 管理 Skill |
| gitlink-contributor-growth | 刘焱 | 贡献者成长体系 |
| gitlink-multi-repo-coordination | 刘焱 | 多仓库协同 |
| gitlink-project-bootstrap | 刘焱 | 项目一键初始化 |
| gitlink-research-compliance | 曾蔚然 | 科研合规与复现性 |
| gitlink-research-matching | 曾蔚然 | 科研协作智能匹配 |
| gitlink-research-progress | 曾蔚然 | 科研进度跟踪与预警 |
每个 Skill 包含:`SKILL.md`(命令参考)+ `examples/`(使用示例)+ `scripts/`(可复现脚本)。
---
## 子任务三:端到端自动化工作流
5 个端到端场景,统一采用"三阶段脚本 + JS 分析引擎"架构:
| 场景 | 串联脚本 | 分析引擎 | 作者 |
|------|---------|---------|------|
| 社区运营自动化 | community-ops-full.sh | health-analyze.js | 赵昌 |
| 代码质量门禁 | quality-gate-full.sh | scoring-engine.js | 赵昌 |
| 项目一键初始化 | project-bootstrap-full.sh | skeleton-gen.js | 刘焱 |
| 多仓库协同 | multi-repo-full.sh | dashboard-gen.js | 刘焱 |
| 贡献者成长体系 | contributor-growth-full.sh | growth-analyze.js | 刘焱 |
---
## 子任务四:科研辅助模块
5 大科研辅助模块,覆盖科研全生命周期:
| 模块 | Skill | 功能 |
|------|-------|------|
| 科研项目洞悉 | gitlink-research-insight | 8 维数据采集 + 4 维评分 |
| 热点追踪与知识图谱 | gitlink-research-hotspot | 多关键词搜索 + 实体关系图谱 |
| 科研合规与复现性 | gitlink-research-compliance | 三维复现性证据链 |
| 科研协作智能匹配 | gitlink-research-matching | 角色匹配 + 缺口识别 |
| 科研进度跟踪与预警 | gitlink-research-progress | 6 维动态风险信号 |
---
## DevOps 流水线
1 条已部署的建木流水线push 代码时自动触发集成和部署:
| 流水线 | 触发方式 | 功能 | 文件 |
|--------|---------|------|------|
| 构建流水线 | push | 拉取代码 → 编译 → 部署到 /usr/local/bin → 验证 | `.devops/构建流水线.yml` |
另有 3 条流水线 YAML 配置已提交到仓库但未部署(项目初始化、多仓库协同、贡献者成长)。
---
## 操作中心
新增 `/gitlink` 斜杠命令作为统一入口16 项操作上下选择执行。配置文件:`.claude/commands/gitlink.md`

View File

@ -1,609 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GitLink CLI 现场演示</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{--bg:#0f172a;--bg2:#1e293b;--card:#1e3a5f;--accent:#38bdf8;--accent2:#818cf8;--gold:#fbbf24;--text:#e2e8f0;--dim:#94a3b8;--green:#22c55e;--red:#ef4444;--border:#334155}
body{background:var(--bg);color:var(--text);font-family:'Microsoft YaHei',sans-serif;display:flex;height:100vh;overflow:hidden}
/* Sidebar */
.sidebar{width:280px;background:var(--bg2);border-right:1px solid var(--border);flex-shrink:0;overflow-y:auto}
.sidebar-header{padding:20px 24px;border-bottom:1px solid var(--border)}
.sidebar-header h1{font-size:18px;color:var(--accent);margin-bottom:4px}
.sidebar-header p{font-size:12px;color:var(--dim)}
.nav-section{padding:12px 0}
.nav-section-title{padding:4px 24px;font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:1px}
.nav-item{padding:10px 24px;cursor:pointer;font-size:14px;color:var(--text);border-left:3px solid transparent;transition:all .2s;display:flex;align-items:center;gap:10px}
.nav-item:hover{background:var(--card);color:var(--accent)}
.nav-item.active{background:var(--card);color:var(--accent);border-left-color:var(--accent)}
.nav-item .icon{font-size:18px;width:24px;text-align:center}
.nav-item .time{margin-left:auto;font-size:11px;color:var(--dim);background:var(--bg);padding:2px 6px;border-radius:4px}
/* Main */
.main{flex:1;overflow-y:auto;padding:0}
.demo-page{display:none;padding:32px 40px;min-height:100%}
.demo-page.active{display:block}
.page-header{margin-bottom:24px}
.page-header h2{font-size:26px;color:var(--text);margin-bottom:6px}
.page-header p{font-size:14px;color:var(--dim)}
/* Terminal */
.terminal{background:#1e1e2e;border-radius:10px;overflow:hidden;margin:16px 0;box-shadow:0 4px 24px rgba(0,0,0,.3)}
.term-bar{background:#313244;padding:8px 14px;display:flex;align-items:center;gap:8px}
.term-dot{width:12px;height:12px;border-radius:50%}
.term-dot.r{background:#f38ba8}.term-dot.y{background:#f9e2af}.term-dot.g{background:#a6e3a1}
.term-title{flex:1;text-align:center;font-size:12px;color:#6c7086;font-family:monospace}
.term-body{padding:16px 20px;font-family:'Cascadia Code','Fira Code',monospace;font-size:13px;line-height:1.7;color:#cdd6f4;max-height:500px;overflow-y:auto}
.term-prompt{color:#89b4fa}.term-cmd{color:#cdd6f4}.term-flag{color:#f9e2af}.term-str{color:#a6e3a1}.term-out{color:#a6adc8}.term-ok{color:#a6e3a1}.term-info{color:#89b4fa}.term-warn{color:#f9e2af}.term-err{color:#f38ba8}.term-dim{color:#6c7086}.term-section{color:#cba6f7;font-weight:bold}
/* Cards */
.card-grid{display:grid;gap:16px;margin:16px 0}
.card{background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:20px}
.card h3{font-size:16px;color:var(--accent);margin-bottom:10px}
.card p{font-size:13px;color:var(--text);line-height:1.6}
.metric-row{display:flex;gap:16px;flex-wrap:wrap;margin:12px 0}
.metric{background:var(--card);border-radius:8px;padding:12px 20px;text-align:center;min-width:120px}
.metric .val{font-size:28px;font-weight:bold;color:var(--gold)}
.metric .lbl{font-size:12px;color:var(--dim);margin-top:4px}
/* Output link */
.output-link{display:inline-flex;align-items:center;gap:8px;background:var(--card);border:1px solid var(--accent);border-radius:8px;padding:10px 20px;color:var(--accent);text-decoration:none;font-size:14px;transition:all .2s;cursor:pointer}
.output-link:hover{background:var(--accent);color:var(--bg)}
.output-link .arrow{font-size:16px}
/* Phase */
.phase{display:flex;gap:16px;margin:12px 0;align-items:flex-start}
.phase-num{width:36px;height:36px;border-radius:50%;background:var(--accent);color:var(--bg);display:flex;align-items:center;justify-content:center;font-weight:bold;font-size:16px;flex-shrink:0}
.phase-content{flex:1}
.phase-content h4{font-size:15px;color:var(--text);margin-bottom:4px}
.phase-content p{font-size:13px;color:var(--dim);line-height:1.5}
/* Table */
table{width:100%;border-collapse:collapse;margin:12px 0;font-size:13px}
th{background:var(--card);color:var(--accent);padding:10px 14px;text-align:left;border-bottom:2px solid var(--border)}
td{padding:8px 14px;border-bottom:1px solid var(--border);color:var(--text)}
tr:hover td{background:var(--bg2)}
/* Score bar */
.score-bar{display:flex;align-items:center;gap:12px;margin:8px 0}
.score-label{width:120px;font-size:13px;color:var(--text)}
.score-track{flex:1;height:24px;background:var(--bg);border-radius:4px;overflow:hidden}
.score-fill{height:100%;border-radius:4px;display:flex;align-items:center;justify-content:flex-end;padding-right:8px;font-size:11px;color:#fff;font-weight:bold}
.score-val{width:60px;font-size:14px;font-weight:bold;color:var(--gold);text-align:right}
/* Hint */
.hint{background:rgba(56,189,248,.1);border:1px solid var(--accent);border-radius:8px;padding:12px 20px;margin:16px 0;font-size:13px;color:var(--text)}
.hint b{color:var(--accent)}
/* Badges */
.badge{display:inline-block;padding:2px 10px;border-radius:4px;font-size:11px;font-weight:bold}
.badge-new{background:rgba(34,197,94,.2);color:var(--green);border:1px solid var(--green)}
.badge-orig{background:rgba(148,163,184,.1);color:var(--dim);border:1px solid var(--border)}
/* Scrollbar */
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-track{background:var(--bg)}
::-webkit-scrollbar-thumb{background:var(--border);border-radius:4px}
::-webkit-scrollbar-thumb:hover{background:var(--dim)}
/* Home */
.home-hero{text-align:center;padding:40px 0}
.home-hero h2{font-size:32px;color:var(--text);margin-bottom:12px}
.home-hero p{font-size:16px;color:var(--dim);margin-bottom:30px}
.home-metrics{display:flex;gap:20px;justify-content:center;flex-wrap:wrap;margin:30px 0}
.home-metric{background:var(--bg2);border:1px solid var(--border);border-radius:12px;padding:20px 30px;text-align:center;min-width:140px}
.home-metric .val{font-size:36px;font-weight:bold}
.home-metric .lbl{font-size:13px;color:var(--dim);margin-top:6px}
@keyframes blink{0%,50%{opacity:1}51%,100%{opacity:0}}
@keyframes fadein{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
.repl-line{animation:fadein .3s ease}
</style>
</head>
<body>
<div class="sidebar">
<div class="sidebar-header">
<h1>GitLink CLI</h1>
<p>现场演示 · 4 场景 · ~3 分钟</p>
</div>
<div class="nav-section">
<div class="nav-section-title">概览</div>
<div class="nav-item active" onclick="show('home',this)"><span class="icon">🏠</span> 首页</div>
</div>
<div class="nav-section">
<div class="nav-section-title">子任务一 · CLI</div>
<div class="nav-item" onclick="show('cli',this)"><span class="icon">⌨️</span> CLI 命令 <span class="time">30s</span></div>
<div class="nav-item" onclick="show('repl',this)"><span class="icon">🖥️</span> REPL 交互 <span class="time">45s</span></div>
</div>
<div class="nav-section">
<div class="nav-section-title">子任务三 · 工作流</div>
<div class="nav-item" onclick="show('community',this)"><span class="icon">📊</span> 社区运营 <span class="time">60s</span></div>
</div>
<div class="nav-section">
<div class="nav-section-title">子任务四 · 科研</div>
<div class="nav-item" onclick="show('insight',this)"><span class="icon">🔬</span> 项目洞悉 <span class="time">45s</span></div>
<div class="nav-item" onclick="show('hotspot',this)"><span class="icon">🕸️</span> 知识图谱 <span class="time">45s</span></div>
</div>
<div class="nav-section">
<div class="nav-section-title">评分体系</div>
<div class="nav-item" onclick="show('scoring',this)"><span class="icon">📐</span> 权重设计 <span class="time">30s</span></div>
</div>
</div>
<div class="main">
<!-- ===== HOME ===== -->
<div class="demo-page active" id="home">
<div class="home-hero">
<h2>GitLink 智能化能力提升项目</h2>
<p>gitlink-cli 命令行工具 · AI Agent Skills · 工作流自动化 · 科研辅助</p>
<div class="home-metrics">
<div class="home-metric"><div class="val" style="color:#38bdf8">236</div><div class="lbl">Git 提交</div></div>
<div class="home-metric"><div class="val" style="color:#818cf8">29</div><div class="lbl">AI Skills</div></div>
<div class="home-metric"><div class="val" style="color:#22c55e">14</div><div class="lbl">新命令模块</div></div>
<div class="home-metric"><div class="val" style="color:#fbbf24">16.8k</div><div class="lbl">Go 代码行</div></div>
<div class="home-metric"><div class="val" style="color:#a78bfa">20</div><div class="lbl">测试文件</div></div>
</div>
</div>
<div class="hint">
<b>💡 演示说明:</b>点击左侧导航查看各场景。每个场景包含<b>命令展示</b><b>输出结果跳转</b>。所有数据来自 GitLink API 实时采集。
</div>
<div class="card-grid" style="grid-template-columns:1fr 1fr">
<div class="card">
<h3>📁 代码仓库</h3>
<p>fork 自 GitLink 官方 gitlink-cli在初始 commit 基础上完成全部工作</p>
<a class="output-link" href="https://www.gitlink.org.cn/z2_cc/gitlink-cli" target="_blank" style="margin-top:12px">前往仓库 →</a>
</div>
<div class="card">
<h3>👥 团队</h3>
<p>赵昌 (wqer) · 子任务三/四<br>刘焱 (liuyan688) · CLI 底层 + REPL<br>曾蔚然 (z2_cc) · DevOps + 审查</p>
</div>
</div>
</div>
<!-- ===== CLI ===== -->
<div class="demo-page" id="cli">
<div class="page-header">
<h2>① CLI 基础命令演示</h2>
<p>新增 14 个 Shortcut 模块 · 统一输出格式 · 真实 API 数据</p>
</div>
<div class="terminal">
<div class="term-bar"><span class="term-dot r"></span><span class="term-dot y"></span><span class="term-dot g"></span><span class="term-title">z@z-pc: ~/gitlink-cli</span></div>
<div class="term-body">
<div><span class="term-prompt">z@z-pc</span><span class="term-dim">:</span><span class="term-prompt">~/gitlink-cli</span><span class="term-dim">$</span> <span class="term-cmd">gitlink-cli</span> <span class="term-cmd">repo</span> <span class="term-flag">+info</span> <span class="term-flag">--owner</span> <span class="term-str">z2_cc</span> <span class="term-flag">--repo</span> <span class="term-str">gitlink-cli</span></div>
<div class="term-out"> name gitlink-cli</div>
<div class="term-out"> full_name z2_cc/gitlink-cli</div>
<div class="term-out"> default_branch master</div>
<div class="term-out"> issues_count 17</div>
<div class="term-out"> forked_count 2</div>
<div class="term-out"> clone_url https://gitlink.org.cn/z2_cc/gitlink-cli.git</div>
<div> </div>
<div><span class="term-prompt">z@z-pc</span><span class="term-dim">:</span><span class="term-prompt">~/gitlink-cli</span><span class="term-dim">$</span> <span class="term-cmd">gitlink-cli</span> <span class="term-cmd">collaborator</span> <span class="term-flag">+list</span> <span class="term-flag">--owner</span> <span class="term-str">z2_cc</span> <span class="term-flag">--repo</span> <span class="term-str">gitlink-cli</span></div>
<div class="term-out"> login role is_owner</div>
<div class="term-out"> ────────────────────────────────────</div>
<div class="term-out"> z2_cc Manager true</div>
<div class="term-out"> wqer Manager false</div>
<div class="term-out"> liuyan688 Manager false</div>
<div> </div>
<div><span class="term-prompt">z@z-pc</span><span class="term-dim">:</span><span class="term-prompt">~/gitlink-cli</span><span class="term-dim">$</span> <span class="term-cmd">gitlink-cli</span> <span class="term-cmd">webhook</span> <span class="term-flag">+failed</span> <span class="term-flag">--owner</span> <span class="term-str">z2_cc</span> <span class="term-flag">--repo</span> <span class="term-str">gitlink-cli</span></div>
<div class="term-out"> 最近 7 天投递失败记录0 条 <span class="term-ok"></span></div>
</div>
</div>
<div class="card-grid" style="grid-template-columns:1fr 1fr 1fr">
<div class="card"><h3>📌 新增 14 模块</h3><p>collaborator · tag · milestone · file · commit · label · sshkey · webhook · wiki · snippet · dataset · template · attachment · util</p></div>
<div class="card"><h3>⭐ 统一输出</h3><p>所有命令支持 <code>--format json/table/yaml</code>JSON Envelope: {ok, data, meta}</p></div>
<div class="card"><h3>✅ 测试覆盖</h3><p>20 个测试文件,含单元测试 + E2E 测试</p></div>
</div>
</div>
<!-- ===== REPL ===== -->
<div class="demo-page" id="repl">
<div class="page-header">
<h2>② REPL 交互模式 — IDE 级体验</h2>
<p>Bubble Tea TUI · 2027 行 Go · 5 状态状态机 · 7 个 E2E 测试 · 点击下方命令体验</p>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px">
<!-- 左:交互终端 -->
<div class="card" style="padding:0;overflow:hidden">
<div style="background:#313244;padding:8px 14px;font-size:12px;color:#6c7086;display:flex;align-items:center;gap:8px">
<span style="width:12px;height:12px;border-radius:50%;background:#f38ba8"></span>
<span style="width:12px;height:12px;border-radius:50%;background:#f9e2af"></span>
<span style="width:12px;height:12px;border-radius:50%;background:#a6e3a1"></span>
<span style="flex:1;text-align:center">gitlink-cli REPL — 交互终端</span>
</div>
<div id="repl-terminal" style="background:#1e1e2e;padding:16px;font-family:'Cascadia Code','Fira Code',monospace;font-size:13px;line-height:1.6;color:#cdd6f4;min-height:340px;max-height:340px;overflow-y:auto">
<div style="color:#a6e3a1">Welcome to gitlink-cli interactive mode.</div>
<div style="color:#6c7086">Type / to open command palette, "exit" or Ctrl+D to quit.</div>
<div style="height:8px"></div>
<div id="repl-output"></div>
<div><span style="color:#89b4fa">z@z-pc</span><span style="color:#6c7086">:</span><span style="color:#89b4fa">~/gitlink-cli</span><span style="color:#6c7086">$ </span><span id="repl-cursor" style="background:#cdd6f4;width:8px;height:16px;display:inline-block;animation:blink 1s infinite"></span></div>
</div>
</div>
<!-- 右:操作指引 -->
<div class="card">
<h3>🖱️ 点击体验三个阶段</h3>
<div style="display:flex;flex-direction:column;gap:10px;margin-top:12px">
<button onclick="replDemo('palette')" style="background:#1e3a5f;border:1px solid #38bdf8;color:#38bdf8;padding:10px 16px;border-radius:8px;cursor:pointer;font-size:13px;text-align:left;font-family:inherit">
<b>① 命令面板</b> — 输入 / 搜索命令<br>
<span style="font-size:11px;color:#94a3b8">点击模拟:输入 / → 搜索 issue → 选命令</span>
</button>
<button onclick="replDemo('form')" style="background:#1e293b;border:1px solid #22c55e;color:#22c55e;padding:10px 16px;border-radius:8px;cursor:pointer;font-size:13px;text-align:left;font-family:inherit">
<b>② 表单输入</b> — Tab 切换参数<br>
<span style="font-size:11px;color:#94a3b8">点击模拟:填 title → Tab → 填 assignee → 提交</span>
</button>
<button onclick="replDemo('viewport')" style="background:#312e81;border:1px solid #fbbf24;color:#fbbf24;padding:10px 16px;border-radius:8px;cursor:pointer;font-size:13px;text-align:left;font-family:inherit">
<b>③ 滚动视口</b> — 长输出浏览<br>
<span style="font-size:11px;color:#94a3b8">点击模拟:执行 issue +list → 滚动浏览</span>
</button>
<button onclick="replDemo('reset')" style="background:#1e293b;border:1px solid #64748b;color:#94a3b8;padding:8px 16px;border-radius:8px;cursor:pointer;font-size:12px;text-align:left;font-family:inherit">
↺ 重置终端
</button>
</div>
<div style="margin-top:14px;padding:10px;background:rgba(56,189,248,.08);border-radius:6px;font-size:11px;color:#94a3b8;line-height:1.5">
<b style="color:#38bdf8">键盘操作:</b><br>
<code style="color:#a6e3a1">/</code> 唤起面板 · <code style="color:#a6e3a1">↑↓</code> 导航 · <code style="color:#a6e3a1">Enter</code> 选中<br>
<code style="color:#a6e3a1">Tab</code> 切字段 · <code style="color:#a6e3a1">Space</code> 切布尔 · <code style="color:#a6e3a1">Esc</code> 取消<br>
<code style="color:#a6e3a1">PgUp/PgDn</code> 翻页 · <code style="color:#a6e3a1">q</code> 返回
</div>
</div>
</div>
<div class="hint">
<b>⭐ 核心亮点:</b>用户无需记忆命令语法——输入 / 搜索命令Tab 填写参数,提交即执行。体验接近 VS Code 命令面板。
<br><b>技术实现:</b>基于 Charmbracelet Bubble TeaElm 架构repl.go(433行) + palette.go(305行) + form.go(296行) + executor.go(237行)7 个 E2E 测试。
</div>
</div>
<!-- ===== COMMUNITY ===== -->
<div class="demo-page" id="community">
<div class="page-header">
<h2>③ 社区运营自动化</h2>
<p>community-ops-full.sh · 三阶段流水线一键执行 · 真实运行结果</p>
</div>
<div class="terminal">
<div class="term-bar"><span class="term-dot r"></span><span class="term-dot y"></span><span class="term-dot g"></span><span class="term-title">community-ops-full.sh</span></div>
<div class="term-body">
<div><span class="term-prompt">z@z-pc</span><span class="term-dim">:</span><span class="term-prompt">~/gitlink-cli</span><span class="term-dim">$</span> <span class="term-flag">DRY_RUN=true</span> <span class="term-cmd">bash</span> <span class="term-str">skills/gitlink-community-ops/scripts/community-ops-full.sh</span> <span class="term-str">z2_cc</span> <span class="term-str">gitlink-cli</span></div>
<div> </div>
<div class="term-section">============================================</div>
<div class="term-section"> 社区运营自动化</div>
<div class="term-section">============================================</div>
<div> </div>
<div><span class="term-info">▸ Phase 1/3: Issue 自动分拣</span></div>
<div class="term-out">[INFO] 获取所有打开的 Issue...</div>
<div class="term-out">[INFO] 发现 21 个 Issue17 打开 / 4 关闭)</div>
<div class="term-out">[INFO] 自动分类bug 8 · enhancement 6 · documentation 4 · other 3</div>
<div class="term-ok">✓ 分拣完成</div>
<div> </div>
<div><span class="term-info">▸ Phase 2/3: 社区周报生成</span></div>
<div class="term-out">[INFO] 采集 PR/提交/贡献者数据...</div>
<div class="term-out">[INFO] 综合评分: 3.5/10 🔴 堪忧</div>
<div class="term-out">[INFO] 关闭率: 19% | 合并率: 0% | 贡献者: 1人</div>
<div class="term-ok">✓ HTML 报告已生成: _output/weekly-health-report.html</div>
<div> </div>
<div><span class="term-info">▸ Phase 3/3: 自动 Release Notes</span></div>
<div class="term-out">[INFO] 获取最近 100 条提交...</div>
<div class="term-out">[INFO] 新功能 22 项 | Bug 修复 15 项 | 文档 8 项</div>
<div class="term-out">[INFO] 贡献者: 7 人 | 涉及文件: 252 个</div>
<div class="term-ok">✓ HTML 报告已生成: _output/release-notes-v0.1.0.html</div>
</div>
</div>
<div class="card-grid" style="grid-template-columns:1fr 1fr">
<div class="card">
<h3>📊 社区周报 HTML</h3>
<p>4 维评分Issue 关闭率(30%) + PR 合并率(30%) + 贡献者(25%) + 响应速度(15%)</p>
<a class="output-link" href="../skills/gitlink-community-ops/scripts/_output/weekly-health-report.html" target="_blank" style="margin-top:12px">打开周报 →</a>
</div>
<div class="card">
<h3>📝 Release Notes HTML</h3>
<p>按 Conventional Commits 自动分类feat/fix/docs/chore</p>
<a class="output-link" href="../skills/gitlink-community-ops/scripts/_output/release-notes-v0.1.0.html" target="_blank" style="margin-top:12px">打开 Release Notes →</a>
</div>
</div>
</div>
<!-- ===== INSIGHT ===== -->
<div class="demo-page" id="insight">
<div class="page-header">
<h2>④ 科研项目洞悉</h2>
<p>research-insight-full.sh · 8 维数据采集 + 4 维评分 · 真实运行</p>
</div>
<div class="terminal">
<div class="term-bar"><span class="term-dot r"></span><span class="term-dot y"></span><span class="term-dot g"></span><span class="term-title">research-insight-full.sh</span></div>
<div class="term-body">
<div><span class="term-prompt">z@z-pc</span><span class="term-dim">:</span><span class="term-prompt">~/gitlink-cli</span><span class="term-dim">$</span> <span class="term-cmd">bash</span> <span class="term-str">skills/gitlink-research-insight/scripts/research-insight-full.sh</span> <span class="term-str">z2_cc</span> <span class="term-str">gitlink-cli</span></div>
<div> </div>
<div><span class="term-info">▸ Step 1/2: 采集 8 维数据</span></div>
<div class="term-out">[INFO] ✅ 仓库信息 → repo-info.json</div>
<div class="term-out">[INFO] ✅ 主题标签 → repo-topics.json</div>
<div class="term-out">[INFO] ✅ 语言分布 → repo-languages.json (Go 70.1% / JS 22.7% / Shell 6.7%)</div>
<div class="term-out">[INFO] ✅ 贡献者 → repo-contributors.json (16 人)</div>
<div class="term-out">[INFO] ✅ 提交历史 → commits-100.json</div>
<div class="term-out">[INFO] ✅ Issue → issues-all.json (17 个)</div>
<div class="term-out">[INFO] ✅ PR → prs-all.json (2 个)</div>
<div class="term-out">[INFO] ✅ 协作者 → collaborators.json</div>
<div> </div>
<div><span class="term-info">▸ Step 2/2: 4 维评分分析</span></div>
<div class="term-out">[INFO] 项目成熟度: 2.8/10</div>
<div class="term-out">[INFO] 文档质量: 5.0/10</div>
<div class="term-out">[INFO] 贡献模式: 6.8/10</div>
<div class="term-out">[INFO] 社区健康度: 4.4/10</div>
<div class="term-out">[INFO] 综合评分: 4.8/10 🔴</div>
<div class="term-ok">✅ HTML 报告已生成: _output/research-insight-report.html</div>
</div>
</div>
<div class="metric-row">
<div class="metric"><div class="val" style="color:var(--red)">2.8</div><div class="lbl">成熟度 /10</div></div>
<div class="metric"><div class="val" style="color:var(--gold)">5.0</div><div class="lbl">文档 /10</div></div>
<div class="metric"><div class="val" style="color:var(--green)">6.8</div><div class="lbl">贡献模式 /10</div></div>
<div class="metric"><div class="val" style="color:var(--red)">4.4</div><div class="lbl">社区健康 /10</div></div>
<div class="metric"><div class="val" style="color:var(--gold)">4.8</div><div class="lbl">综合 /10</div></div>
</div>
<a class="output-link" href="../skills/gitlink-research-insight/scripts/_output/research-insight-report.html" target="_blank">打开科研洞察报告 →</a>
</div>
<!-- ===== HOTSPOT ===== -->
<div class="demo-page" id="hotspot">
<div class="page-header">
<h2>⑤ 热点追踪与知识图谱</h2>
<p>多关键词搜索 → 实体关系图谱 → HTML 可视化 · 21 个仓库</p>
</div>
<div class="terminal">
<div class="term-bar"><span class="term-dot r"></span><span class="term-dot y"></span><span class="term-dot g"></span><span class="term-title">hotspot-tracker-full.sh</span></div>
<div class="term-body">
<div><span class="term-prompt">z@z-pc</span><span class="term-dim">:</span><span class="term-prompt">~/gitlink-cli</span><span class="term-dim">$</span> <span class="term-cmd">bash</span> <span class="term-str">skills/gitlink-research-hotspot/scripts/hotspot-tracker-full.sh</span> <span class="term-str">"gitlink"</span> <span class="term-str">"CLI"</span></div>
<div> </div>
<div><span class="term-info">▸ Step 1/2: 多关键词搜索</span></div>
<div class="term-out">[INFO] 搜索关键词 "gitlink" ... 找到 18 个仓库</div>
<div class="term-out">[INFO] 搜索关键词 "CLI" ... 找到 3 个仓库</div>
<div class="term-out">[INFO] 去重后共 21 个仓库</div>
<div class="term-out">[INFO] 丰富数据: 采集每个仓库的 Star/Fork/语言/主题...</div>
<div> </div>
<div><span class="term-info">▸ Step 2/2: 构建知识图谱</span></div>
<div class="term-out">[INFO] 实体识别: 项目 21 | 主题 4 | 技术栈 2 | 组织 4</div>
<div class="term-out">[INFO] 关系提取: belongs_to / topic / language / depends_on</div>
<div class="term-ok">✅ HTML 知识图谱已生成: _output/knowledge-graph-gitlink.html</div>
<div class="term-ok">✅ HTML 趋势报告已生成: _output/hotspot-trend-report-gitlink.html</div>
</div>
</div>
<div class="card-grid" style="grid-template-columns:1fr 1fr">
<div class="card">
<h3>🕸️ 知识图谱</h3>
<p>21 个仓库 · 4 主题 · 2 技术栈 · 4 组织<br>支持缩放/拖拽/点击高亮</p>
<a class="output-link" href="../skills/gitlink-research-hotspot/scripts/_output/knowledge-graph-gitlink.html" target="_blank" style="margin-top:12px">打开知识图谱 →</a>
</div>
<div class="card">
<h3>📈 趋势报告</h3>
<p>热门主题分析 · 技术栈分布 · 组织活跃度排名</p>
<a class="output-link" href="../skills/gitlink-research-hotspot/scripts/_output/hotspot-trend-report-gitlink.html" target="_blank" style="margin-top:12px">打开趋势报告 →</a>
</div>
</div>
</div>
<!-- ===== SCORING ===== -->
<div class="demo-page" id="scoring">
<div class="page-header">
<h2>⑥ 评分体系权重设计</h2>
<p>两套评分系统 · 权重有据可依 · 阈值梯度设计</p>
</div>
<div class="card" style="margin-bottom:16px">
<h3>📊 周报评分 — 综合 = 关闭率×30% + 合并率×30% + 贡献者×25% + 响应×15%</h3>
<div class="score-bar">
<div class="score-label">Issue 关闭率</div>
<div class="score-track"><div class="score-fill" style="width:30%;background:#38bdf8">30%</div></div>
<div class="score-val">3/10</div>
</div>
<div class="score-bar">
<div class="score-label">PR 合并率</div>
<div class="score-track"><div class="score-fill" style="width:30%;background:#38bdf8">30%</div></div>
<div class="score-val">3/10</div>
</div>
<div class="score-bar">
<div class="score-label">贡献者数</div>
<div class="score-track"><div class="score-fill" style="width:25%;background:#818cf8">25%</div></div>
<div class="score-val">3/10</div>
</div>
<div class="score-bar">
<div class="score-label">响应速度</div>
<div class="score-track"><div class="score-fill" style="width:15%;background:#a78bfa">15%</div></div>
<div class="score-val">5/10</div>
</div>
<p style="margin-top:12px;font-size:12px;color:var(--dim)">关闭率+合并率各30%直接反映社区活跃度结果指标。贡献者25%:巴士因子,单人维护=高风险。响应15%:补充信号,关闭率已含"解决"信号。</p>
</div>
<div class="card" style="margin-bottom:16px">
<h3>🔬 科研洞察 — 综合 = 贡献模式×30% + 成熟度×25% + 社区×25% + 文档×20%</h3>
<div class="score-bar">
<div class="score-label">贡献模式</div>
<div class="score-track"><div class="score-fill" style="width:30%;background:#22c55e">30%</div></div>
<div class="score-val">6.8/10</div>
</div>
<div class="score-bar">
<div class="score-label">成熟度</div>
<div class="score-track"><div class="score-fill" style="width:25%;background:#38bdf8">25%</div></div>
<div class="score-val">2.8/10</div>
</div>
<div class="score-bar">
<div class="score-label">社区健康度</div>
<div class="score-track"><div class="score-fill" style="width:25%;background:#818cf8">25%</div></div>
<div class="score-val">4.4/10</div>
</div>
<div class="score-bar">
<div class="score-label">文档质量</div>
<div class="score-track"><div class="score-fill" style="width:20%;background:#a78bfa">20%</div></div>
<div class="score-val">5.0/10</div>
</div>
<p style="margin-top:12px;font-size:12px;color:var(--dim)">贡献模式30%最高:科研项目核心在人。成熟度+社区各25%阶段与活跃互补。文档20%最低:影响可复现性但非核心价值。</p>
</div>
<div class="card">
<h3>📐 成熟度子维度 — 成熟度 = 年龄×25% + Star×25% + Fork×20% + 维护×30%</h3>
<div class="score-bar">
<div class="score-label">维护活跃度</div>
<div class="score-track"><div class="score-fill" style="width:30%;background:#fbbf24">30% 权重最高</div></div>
<div class="score-val">7/10</div>
</div>
<div class="score-bar">
<div class="score-label">项目年龄</div>
<div class="score-track"><div class="score-fill" style="width:25%;background:#38bdf8">25%</div></div>
<div class="score-val">0.2/10</div>
</div>
<div class="score-bar">
<div class="score-label">Star 数</div>
<div class="score-track"><div class="score-fill" style="width:25%;background:#818cf8">25%</div></div>
<div class="score-val">1/10</div>
</div>
<div class="score-bar">
<div class="score-label">Fork 数</div>
<div class="score-track"><div class="score-fill" style="width:20%;background:#a78bfa">20% 最低</div></div>
<div class="score-val">2/10</div>
</div>
<p style="margin-top:12px;font-size:12px;color:var(--dim)">维护30%最高:老项目不维护=死项目。Fork 20%最低Fork 多≠贡献多,有大量废弃 Fork 污染数据。</p>
</div>
<div class="hint">
<b>📐 阈值设计:</b>统一梯度 <code>>80%→10分 | >50%→7分 | >30%→5分 | 其他→3分</code>,参考 CHAOSS 指标体系。
<br><b>🔧 可调可复现:</b>权重在 JS 引擎里硬编码,可随时调整。同样数据跑出来同样分数。
</div>
</div>
</div>
<script>
function show(id, el) {
document.querySelectorAll('.demo-page').forEach(p => p.classList.remove('active'));
document.getElementById(id).classList.add('active');
document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));
el.classList.add('active');
}
// ===== REPL 交互演示 =====
const replOutput = () => document.getElementById('repl-output');
function replPrint(html, delay = 0) {
setTimeout(() => {
const div = document.createElement('div');
div.className = 'repl-line';
div.innerHTML = html;
replOutput().appendChild(div);
const term = document.getElementById('repl-terminal');
term.scrollTop = term.scrollHeight;
}, delay);
}
function replClear() {
replOutput().innerHTML = '';
}
function replDemo(type) {
replClear();
const P = '<span style="color:#89b4fa">z@z-pc</span><span style="color:#6c7086">:</span><span style="color:#89b4fa">~/gitlink-cli</span><span style="color:#6c7086">$ </span>';
const C = (s) => `<span style="color:#cdd6f4">${s}</span>`;
const F = (s) => `<span style="color:#f9e2af">${s}</span>`;
const S = (s) => `<span style="color:#a6e3a1">${s}</span>`;
const D = (s) => `<span style="color:#6c7086">${s}</span>`;
const I = (s) => `<span style="color:#89b4fa">${s}</span>`;
const OK = (s) => `<span style="color:#a6e3a1">${s}</span>`;
const ERR = (s) => `<span style="color:#f38ba8">${s}</span>`;
const SEC = (s) => `<span style="color:#cba6f7;font-weight:bold">${s}</span>`;
if (type === 'palette') {
// 命令面板演示
replPrint(P + C('') + '<span style="background:#cdd6f4;width:8px;height:16px;display:inline-block"></span>', 0);
replPrint(D(' 输入 / 唤起命令面板...'), 400);
replPrint('', 700);
replPrint(SEC('┌─ Command Palette ──────────────────────┐'), 900);
replPrint(SEC('│') + ' ' + F('搜索: ') + C('islist') + ' ' + SEC('│'), 1100);
replPrint(SEC('│') + ' ' + D('匹配: issue +list') + ' ' + SEC('│'), 1300);
replPrint(SEC('├────────────────────────────────────────┤'), 1500);
replPrint(SEC('│') + ' ' + I('issue') + ' Issue 管理 ' + SEC('│'), 1700);
replPrint(SEC('│') + ' ' + D('repo') + ' 仓库操作 ' + SEC('│'), 1800);
replPrint(SEC('│') + ' ' + D('pr') + ' Pull Request ' + SEC('│'), 1900);
replPrint(SEC('│') + ' ' + D('collaborator') + ' 协作者管理 ' + SEC('│'), 2000);
replPrint(SEC('│') + ' ' + D('webhook') + ' Webhook 管理 ' + SEC('│'), 2100);
replPrint(SEC('└────────────────────────────────────────┘'), 2200);
replPrint(D(' Enter 选择 · Esc 返回 · ↑↓ 导航'), 2400);
replPrint('', 2800);
replPrint(D(' → 选中 issue进入命令选择...'), 3000);
replPrint('', 3300);
replPrint(SEC('┌─ issue 命令 ───────────────────────────┐'), 3500);
replPrint(SEC('│') + ' ' + C('+list') + ' 列出 Issue ' + SEC('│'), 3700);
replPrint(SEC('│') + ' ' + D('+create') + ' 创建 Issue ' + SEC('│'), 3800);
replPrint(SEC('│') + ' ' + D('+info') + ' Issue 详情 ' + SEC('│'), 3900);
replPrint(SEC('│') + ' ' + D('+close') + ' 关闭 Issue ' + SEC('│'), 4000);
replPrint(SEC('└────────────────────────────────────────┘'), 4100);
replPrint('', 4400);
replPrint(D(' → 选中 +listEnter 提交 → 执行命令...'), 4600);
replPrint('', 4900);
replPrint(I('▸ Executing: issue +list'), 5100);
replPrint(OK('✓ 命令执行成功,输出 7 条 Issue'), 5500);
} else if (type === 'form') {
// 表单输入演示
replPrint(P + C('issue +create'), 0);
replPrint(D(' → 自动生成参数表单...'), 300);
replPrint('', 600);
replPrint(SEC('┌─ issue +create — 参数表单 ──────────────┐'), 800);
replPrint(SEC('│') + ' ' + SEC('│'), 900);
replPrint(SEC('│') + ' ' + F('title') + ' ' + ERR('*') + ': ' + S('Add webhook monitoring') + ' ' + SEC('│'), 1200);
replPrint(SEC('│') + ' ' + D('Issue 标题') + ' ' + SEC('│'), 1300);
replPrint(SEC('│') + ' ' + SEC('│'), 1400);
replPrint(SEC('│') + ' ' + F('body') + ': ' + S('We need to monitor...') + ' ' + SEC('│'), 1700);
replPrint(SEC('│') + ' ' + D('Markdown 描述') + ' ' + SEC('│'), 1800);
replPrint(SEC('│') + ' ' + SEC('│'), 1900);
replPrint(SEC('│') + ' ' + F('assignee') + ': ' + S('liuyan688') + ' ' + SEC('│'), 2200);
replPrint(SEC('│') + ' ' + D('负责人') + ' ' + SEC('│'), 2300);
replPrint(SEC('│') + ' ' + SEC('│'), 2400);
replPrint(SEC('│') + ' ' + F('private') + ': ' + OK('[✓]') + ' ' + D('Space 切换') + ' ' + SEC('│'), 2700);
replPrint(SEC('│') + ' ' + D('是否私密') + ' ' + SEC('│'), 2800);
replPrint(SEC('│') + ' ' + SEC('│'), 2900);
replPrint(SEC('│') + ' ' + ERR('✗ title is required') + ' ' + SEC('│'), 3200);
replPrint(SEC('│') + ' ' + SEC('│'), 3300);
replPrint(SEC('└────────────────────────────────────────┘'), 3400);
replPrint(D(' Enter 提交 · Tab/↑↓ 切换 · Esc 取消'), 3600);
replPrint('', 4000);
replPrint(D(' → 填写 title: Add webhook monitoring'), 4200);
replPrint(D(' → Tab 切换到 body: We need to monitor...'), 4500);
replPrint(D(' → Tab 切换到 assignee: liuyan688'), 4800);
replPrint(D(' → Space 切换 private: [✓]'), 5100);
replPrint('', 5400);
replPrint(I('▸ Enter 提交表单...'), 5600);
replPrint(OK('✓ Issue #22 已创建'), 6000);
} else if (type === 'viewport') {
// 滚动视口演示
replPrint(P + C('issue +list') + ' ' + F('--owner') + ' ' + S('z2_cc') + ' ' + F('--repo') + ' ' + S('gitlink-cli'), 0);
replPrint('', 300);
replPrint(SEC('┌─ issue +list (47 rows) ─────────────────┐'), 500);
replPrint(SEC('│') + ' # title status ' + SEC('│'), 600);
replPrint(SEC('│') + ' ─── ──────────────────────── ──────── ' + SEC('│'), 700);
replPrint(SEC('│') + ' 15 webhook monitor ' + F('open') + ' ' + SEC('│'), 800);
replPrint(SEC('│') + ' 14 wiki markdown render ' + F('open') + ' ' + SEC('│'), 900);
replPrint(SEC('│') + ' 13 PR diff too verbose ' + F('open') + ' ' + SEC('│'), 1000);
replPrint(SEC('│') + ' 12 snippet pagination bug ' + F('open') + ' ' + SEC('│'), 1100);
replPrint(SEC('│') + ' 11 branch protect check ' + F('open') + ' ' + SEC('│'), 1200);
replPrint(SEC('│') + ' 10 file upload timeout ' + F('open') + ' ' + SEC('│'), 1300);
replPrint(SEC('│') + ' 09 milestone sort order ' + OK('closed') + ' ' + SEC('│'), 1400);
replPrint(SEC('│') + ' 08 tag batch operation ' + OK('closed') + ' ' + SEC('│'), 1500);
replPrint(SEC('│') + ' 07 sshkey list format ' + OK('closed') + ' ' + SEC('│'), 1600);
replPrint(SEC('│') + ' 06 commit hash display ' + OK('closed') + ' ' + SEC('│'), 1700);
replPrint(SEC('│') + ' ↓ 36 more rows... ' + SEC('│'), 1800);
replPrint(SEC('└────────────────────────────────────────┘'), 1900);
replPrint(D(' ↑↓/PgUp/PgDn 滚动 · q/Esc 返回 · 47 rows · showing 1-11'), 2100);
replPrint('', 2500);
replPrint(D(' → 输出超一屏,自动进入滚动模式'), 2700);
replPrint(D(' → ↑↓ 逐行滚动PgUp/PgDn 翻页'), 3000);
replPrint(D(' → 表格化渲染,不是原始 JSON'), 3300);
replPrint('', 3600);
replPrint(OK('✓ 按 q 返回输入状态'), 4000);
} else if (type === 'reset') {
replClear();
}
}
</script>
</body>
</html>

View File

@ -1,101 +0,0 @@
#!/bin/bash
# ============================================
# GitLink CLI 现场演示脚本
# 用法: bash demo.sh
# ============================================
set -e
cd "$(dirname "$0")/.."
export GITLINK_TOKEN="${GITLINK_TOKEN:-9185e0529683a6f8e7c9aa86bada03e8652740f7}"
export PATH="$(pwd):$PATH"
OWNER="z2_cc"
REPO="gitlink-cli"
cyan() { echo -e "\033[1;36m$1\033[0m"; }
green() { echo -e "\033[1;32m$1\033[0m"; }
yellow() { echo -e "\033[1;33m$1\033[0m"; }
dim() { echo -e "\033[2m$1\033[0m"; }
line() { echo -e "\033[2m─────────────────────────────────────────────────\033[0m"; }
pause() { echo ""; read -p "$(dim ' [按回车继续]')" _; echo ""; }
banner() {
echo ""
line
cyan " $1"
line
}
# ============================================
banner "① CLI 基础命令演示30 秒)"
# ============================================
dim " 演示repo +info / issue +list / collaborator +list / webhook +failed"
echo ""
yellow " $ gitlink-cli repo +info --owner $OWNER --repo $REPO --format table"
echo ""
gitlink-cli repo +info --owner "$OWNER" --repo "$REPO" --format table 2>&1 | head -15
pause
echo ""
yellow " $ gitlink-cli collaborator +list --owner $OWNER --repo $REPO"
echo ""
gitlink-cli collaborator +list --owner "$OWNER" --repo "$REPO" --format table 2>&1 | head -10
pause
echo ""
yellow " $ gitlink-cli issue +list --owner $OWNER --repo $REPO"
echo ""
gitlink-cli issue +list --owner "$OWNER" --repo "$REPO" --format table 2>&1 | head -12
pause
# ============================================
banner "② 社区运营自动化60 秒)"
# ============================================
dim " 演示:一条命令完成 Issue 分拣 → 周报 → Release Notes"
echo ""
yellow " $ DRY_RUN=true bash skills/gitlink-community-ops/scripts/community-ops-full.sh $OWNER $REPO"
echo ""
DRY_RUN=true bash skills/gitlink-community-ops/scripts/community-ops-full.sh "$OWNER" "$REPO" 2>&1 | tail -25
pause
echo ""
green " ✅ 生成的文件:"
find skills/gitlink-community-ops/scripts/_output -name "*.html" -o -name "*.md" | while read f; do
dim " 📄 $f"
done
pause
# ============================================
banner "③ 科研项目洞悉45 秒)"
# ============================================
dim " 演示8 维数据采集 + 4 维评分"
echo ""
yellow " $ bash skills/gitlink-research-insight/scripts/research-insight-full.sh $OWNER $REPO"
echo ""
bash skills/gitlink-research-insight/scripts/research-insight-full.sh "$OWNER" "$REPO" 2>&1 | tail -15
pause
# ============================================
banner "④ 知识图谱可视化45 秒)"
# ============================================
dim " 演示:多关键词搜索 → 实体关系图谱 → HTML 可视化"
echo ""
yellow " $ bash skills/gitlink-research-hotspot/scripts/hotspot-tracker-full.sh gitlink CLI"
echo ""
bash skills/gitlink-research-hotspot/scripts/hotspot-tracker-full.sh "gitlink" "CLI" 2>&1 | tail -15
pause
echo ""
green " ✅ 知识图谱已生成:"
dim " 🌐 skills/gitlink-research-hotspot/scripts/_output/knowledge-graph-gitlink.html"
echo ""
# ============================================
banner "演示完成 ✅"
# ============================================
echo ""
cyan " 所有数据均来自 GitLink API 实时采集"
cyan " 演示脚本doc/demo.sh"
echo ""

View File

@ -0,0 +1,221 @@
# 项目级 Skill 集成 实现计划
> **面向 AI 代理的工作者:** 必需子技能:使用 superpowers:subagent-driven-development推荐或 superpowers:executing-plans 逐任务实现此计划。步骤使用复选框(`- [ ]`)语法来跟踪进度。
**目标:** 在 gitlink-cl 项目内通过逐 skill junction 让 Claude Code 发现并调用 23 个 gitlink skill仅项目级
**架构:** `.claude/skills/` 为真实目录,其下每个 skill 子目录是 Windows junction`mklink /J`),指向项目根 `skills/<同名>``.gitignore` 忽略该区域;复用全局已登录的 `gitlink-cli``liuyan688`)。
**技术栈:** Windows 目录联接(`mklink /J`无需管理员权限、Git Bash、Claude Code 项目级 skill 加载。
**对应规格:** `doc/specs/2026-06-17-project-local-skills-design.md`
**前置已就绪:** `gitlink-cli` 全局可用且已登录;`skills/` 下 23 个 skill frontmatter 合规name+description、目录名一致
> **验证说明:** 本计划为配置/集成任务,每步以「精确命令 + 预期输出」作为可验证依据(替代传统单元测试)。任务 3 是决定性关口,决定是否触发任务 4 退路。
---
### 任务 1创建 .claude/skills 目录与 23 个逐 skill junction
**文件:**
- 创建:`.claude/skills/`(真实目录)
- 创建23 个 junction `.claude/skills/<skill-name>``skills/<skill-name>`
- [ ] **步骤 1创建 .claude/skills 真实目录**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
mkdir -p .claude/skills
ls -d .claude/skills
```
预期输出:`.claude/skills`
- [ ] **步骤 2批量创建 23 个逐 skill junction绝对路径**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
for d in skills/*/; do
name=$(basename "$d")
link="$(cygpath -w "$PWD/.claude/skills/$name")"
target="$(cygpath -w "$PWD/skills/$name")"
cmd //c "mklink /J \"$link\" \"$target\"" && echo "✓ $name" || echo "✗ $name 失败"
done
```
预期23 行 `✓ <name>`,每个前缀含 `Junction created for ...` 字样。
- [ ] **步骤 3验证 junction 数量与穿透读取**
```bash
# 数量应为 23
ls -1 .claude/skills/ | wc -l
# 预期23
# 穿透 junction 读 SKILL.md抽样
head -2 .claude/skills/gitlink-compliance/SKILL.md
head -2 .claude/skills/gitlink-newcomer-guide/SKILL.md
head -2 .claude/skills/gitlink-shared/SKILL.md
# 预期:每个显示 `---``name:`
# 确认全部为 JUNCTION 类型
cmd //c "dir .claude\\skills" | grep -ci junction
# 预期23
```
- [ ] **步骤 4本任务不单独 commit**
junction 是文件系统链接git 不追踪其内容;`.claude/skills/` 将在任务 2 加入 `.gitignore`。本任务无入库文件,跳过 commit。
---
### 任务 2配置 .gitignore 忽略 .claude/skills
**文件:**
- 修改:`.gitignore`
- [ ] **步骤 1检查 .gitignore 现状**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
grep -n "claude" .gitignore || echo "未含 claude 相关条目"
```
预期:输出"未含 claude 相关条目"(若已含 `.claude/``.claude/skills/` 则跳过步骤 2直接进步骤 3
- [ ] **步骤 2追加忽略规则仅当步骤 1 未含)**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
printf '\n# Claude Code 项目级 skilljunction 指向本地 skills/,不入库)\n.claude/skills/\n' >> .gitignore
```
- [ ] **步骤 3验证忽略生效**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
git check-ignore .claude/skills/gitlink-compliance
# 预期:输出 `.claude/skills/gitlink-compliance`(被忽略)
git status --short
# 预期:仅 `.gitignore` 显示为 ` M`;不出现 `.claude/skills/` 下任何内容
```
- [ ] **步骤 4Commit**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
git add .gitignore
git commit -m "chore: gitignore 项目级 Claude Code skill junction 区域"
```
---
### 任务 3Claude Code 兼容性验证(新会话,决定性关口)
**说明:** 此任务由**用户在新 Claude Code 会话**中执行——当前会话工作目录非本项目,且会话启动后才新建的顶层 `.claude/skills/` 必须重启会话才能被发现(规格 §3.2)。这是判断 junction 方案是否被 Claude Code 接受的决定性验证,直接对应「保证兼容」诉求。
**前置:** 任务 1、任务 2 完成。
- [ ] **步骤 1在 gitlink-cl 目录开新 Claude Code 会话**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
claude
```
- [ ] **步骤 2确认无加载错误**
新会话内运行:
```
/doctor
```
预期:无 skill 加载错误、无 description 预算溢出告警。
- [ ] **步骤 3确认 23 个 skill 被发现**
新会话内运行 `/skills` 或问:
```
列出当前可用的所有 gitlink 开头的 skill
```
预期:列表中含 23 个 `gitlink-*` skill。
- [ ] **步骤 4端到端验证命令链只读**
新会话内:
```
用 gitlink-user skill 查看当前登录用户
```
预期AI 加载 `gitlink-user` skill 并执行 `gitlink-cli user +me`,返回 `liuyan688` 信息。
- [ ] **步骤 5判定**
- 步骤 2-4 全通过 → 兼容性确认,**任务 4 跳过**,集成完成。
- 任一步失败skill 不出现 / doctor 报错)→ 执行**任务 4** 退路。
---
### 任务 4条件退路junction 不被识别时改为真实复制
**触发条件:** 仅当任务 3 验证失败时执行。
**文件:**
- 删除23 个 junction
- 创建:`.claude/skills/<name>/` 真实目录(复制自 `skills/<name>`
- [ ] **步骤 1移除 junction**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
for d in .claude/skills/*/; do
name=$(basename "$d")
cmd //c "rmdir .claude\\skills\\$name" && echo "✓ 移除 $name"
done
```
预期23 行 `✓ 移除 <name>`rmdir 对 junction 只删链接不删源)。
- [ ] **步骤 2真实复制 23 个 skill**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
for d in skills/*/; do
name=$(basename "$d")
cp -r "skills/$name" ".claude/skills/$name"
done
ls -1 .claude/skills/ | wc -l
# 预期23
```
- [ ] **步骤 3确认 .gitignore 仍生效(避免入库重复)**
```bash
cd /c/Users/刘焱/Desktop/gitlink-cl
git check-ignore .claude/skills/gitlink-compliance
# 预期:输出 `.claude/skills/gitlink-compliance`
git status --short
# 预期:无 .claude/skills 相关条目
```
- [ ] **步骤 4重新验证同任务 3 步骤 2-4**
在新会话重跑 `/doctor` + skill 列表 + 端到端。预期全通过。
- [ ] **步骤 5记录退路决策**
无需 commit`.claude/skills/` 仍被忽略)。在规格文档或 PR 说明注明「因 junction 未被 Claude Code 识别,改用真实复制」。
---
## 自检
**1. 规格覆盖度:**
- §1 目标 → 任务 1-3
- §2 现状 → 前置已就绪声明
- §3 兼容性结论 → 任务 3 验证 + 任务 4 退路
- §4 方案(逐 skill junction / gitignore / 命令桥接)→ 任务 1 / 任务 2 / 任务 3 步骤 4
- §5 数据流、§6 验证 → 任务 3
- §7 错误处理与退路 → 任务 4
- §8 范围外 → 计划未涉及全局安装/settings.json
✅ 全覆盖,无遗漏。
**2. 占位符扫描:** 无 TODO/待定/「类似任务N」每步含完整命令与预期输出。✅
**3. 类型/路径一致性:** `.claude/skills/`、`skills/`、`gitlink-cli`、`liuyan688`、23 个 skill 名——跨任务一致。✅

View File

@ -0,0 +1,127 @@
# Shortcut 命令实现报告
## 总体设计模式
三个 Shortcut 组(`wiki`、`snippet`、`hook-runner`)虽然功能不同,但整体架构遵循一致的设计模式:
1. **命令注册**:每个 Shortcut 组通过 `Shortcuts()` 函数返回 `[]*common.Shortcut`,在 `shortcuts/register.go` 中统一挂载到 cobra 根命令
2. **上下文注入**:通过 `RuntimeContext` 提供 API 客户端、owner/repo 解析、输出格式化等基础设施
3. **owner/repo 解析**:每个命令先调用 `ctx.ResolveOwnerRepo()` 从 flags 或 git remote 自动解析
4. **数据访问**:读操作用公开方式(无需认证),写操作用 Token 认证
5. **输出格式**:统一支持 `json` / `table` 格式,通过 `ctx.Output()` / `ctx.OutputData()` 输出
6. **错误处理**:参数校验置前(必填 flag 检查API 错误直接传播
> **注意**:以下所有演示命令假设在 `gitlink-cli` 仓库目录下运行。`--owner` 和 `--repo` 参数会自动从 Git remote 解析,无需手动传入。
---
## 1. Wiki 管理(`wiki`
### 实现思路
GitLink 的 Wiki 本质是一个**独立的 Git 仓库**`https://gitlink.org.cn/{owner}/{repo}.wiki.git`),每个页面是一个 `.md` 文件,侧边栏由 `_Sidebar.md` 控制。
| 操作 | 方式 | 认证 |
|------|------|------|
| 读list/view | `git clone` 到临时目录,读取文件 | ❌ 公开仓库,无需认证 |
| 写create/update/delete | `git clone` → 修改文件 → `git commit/push` | ✅ Personal Access Token |
删除时额外删除 `_Sidebar.md`,让 GitLink 网页端自动从文件列表重建侧边栏,防止残留引用。
### 遇到的问题
| 问题 | 原因 | 解决方案 |
|------|------|---------|
| 修改 `_Sidebar.md` 内容导致网页渲染崩溃 | `_Sidebar.md` 的编码/格式与 GitLink 网页端的预期不一致 | 不修改内容,直接删除文件,让 GitLink 自动重建 |
| `git add _Sidebar.md` 文件不存在时报错 | `_Sidebar.md` 尚未被网页端生成时不存在 | 用 `git add -A` 替代,自动识别所有变更 |
### 演示指令
```powershell
# 列出 Wiki 页面Git 克隆 → 读取目录 → 输出)
./gitlink-cli.exe wiki +list --format table
# 查看 Wiki 页面内容Git 克隆 → 读取文件内容 + Git log
./gitlink-cli.exe wiki +view --page-name "Wiki测试" --format json
# 创建 Wiki 页面Git 克隆 → 写 .md 文件 → git add/commit/push
./gitlink-cli.exe wiki +create --page-name "demo" --title "Demo" --content "Hello World" --message "创建Wiki页面"
# 更新 Wiki 页面Git 克隆 → 修改文件 → git add/commit/push
./gitlink-cli.exe wiki +update --page-name "demo" --title "Updated" --content "New content"
# 删除 Wiki 页面Git 克隆 → 删文件+删_Sidebar.md → git add -A/commit/push
./gitlink-cli.exe wiki +delete --page-name "demo"
```
---
## 2. 代码片段(`snippet`
### 实现思路
代码片段存放在项目仓库的 `snippets/` 目录下,每个片段是一个文件,读操作用 Git 克隆,写操作用文件 API。
| 操作 | 方式 | 说明 |
|------|------|------|
| 列出片段 | `git clone` → 读取 `snippets/` 目录 | 读操作无需认证 |
| 查看片段 | `git clone` → 读取指定文件内容 | 读操作无需认证 |
| 创建片段 | `POST /{owner}/{repo}/create_file` API | 写操作需 Token |
| 删除片段 | `git hash-object` 获取 SHA → `DELETE /delete_file` API | 先获取文件 SHA 再删除 |
创建时自动用代码块语法包裹内容(支持 `--language` 指定语言)。
### 演示指令
```powershell
# 创建代码片段POST 文件 API → 写入 snippets/ 目录)
./gitlink-cli.exe snippet +create --name "hello.py" --content 'print("Hello World!")' --language python --message "添加Python示例"
# 列出代码片段Git 克隆 → 读取 snippets/ 目录 → 输出)
./gitlink-cli.exe snippet +list --format table
# 查看代码片段Git 克隆 → 读取指定文件内容 → 输出)
./gitlink-cli.exe snippet +view --name "hello.py"
# 删除代码片段Git 获取 SHA → DELETE 文件 API
./gitlink-cli.exe snippet +delete --name "hello.py"
```
---
## 3. Webhook 投递监控(`webhook`
> 以下功能已合并到 `webhook` 命令组中,`hook-runner` 已删除。
### 实现思路
Webhook 每次触发事件push、Issue 操作、PR 操作等GitLink 会向配置的 URL 发送 HTTP 请求,这个过程称为"投递"。通过 Webhook 历史推送列表 API 获取投递记录。
| 命令 | API 路径 | 说明 |
|------|---------|------|
| `webhook +tasks` | `GET /v1/{owner}/{repo}/webhooks/{id}/hooktasks` | 查看投递历史(原有命令,保持不变) |
| `webhook +failed` | 从投递列表中过滤失败项 | 仅查看投递失败的记录 |
| `webhook +task-view` | 从投递列表中按 ID 筛选 | 查看某次投递的请求体、响应状态等 |
### 演示指令
```powershell
# 查看投递历史(原有命令不变)
./gitlink-cli.exe webhook +tasks --id 51102
# 查看投递失败的记录
./gitlink-cli.exe webhook +failed --id 51102
# 查看某次投递的详细内容
./gitlink-cli.exe webhook +task-view --id 51102 --task-id 4775684
```
---
## 测试
```powershell
# 运行全部 Shortcut 测试
cd E:/gitlink-cli/gitlink-cli
go test ./shortcuts/... -count=1
```

View File

@ -0,0 +1,86 @@
# 项目级 Skill 集成设计 — gitlink-cl
**日期**: 2026-06-17
**状态**: 设计待审查
**范围**: 仅 `gitlink-cl` 项目内
## 1. 背景与目标
让 Claude Code 能在 `gitlink-cl` 项目目录内发现并调用 `skills/` 下的 23 个 gitlink skill。范围**仅限本项目**,不污染全局 `~/.claude/skills/`
**成功标准**: 在 `gitlink-cl` 目录开新 Claude Code 会话后,23 个 `gitlink-*` skill 出现在可用 skill 列表,并能通过自然语言触发、执行底层 `gitlink-cli` 命令。
## 2. 现状评估
| 项 | 状态 |
|---|---|
| `gitlink-cli` 命令 | ✅ 全局可用(@gitlink-ai/cli@0.1.18,在 PATH) |
| 认证 | ✅ 已登录(`liuyan688`) |
| skill 源 | ✅ `skills/` 下 23 个,frontmatter 合规(见 §3) |
| Claude Code 发现 | ❌ 无项目级 `.claude/skills/`,全局也未装 → Claude Code 看不见 |
## 3. Claude Code 兼容性预检(关键)
基于 Claude Code 官方文档 + frontmatter 实测。
### 3.1 frontmatter 合规(实测,全过)
- 23 个 SKILL.md 均含 `name` + `description`
- 目录名与 frontmatter `name` 完全一致(23/23)——Claude Code 以**目录名**作为命令名,这是关键合规点
- `description` 长度均 < 1536 字符上限
- 非标准字段(`version`、`metadata.requires.bins`、`metadata.cliHelp`):官方文档**未承诺**,但按 Agent Skills 开放标准 + YAML 解析惯例,推断为**静默忽略、不阻塞加载**。注意:Claude Code **不会消费** `metadata.requires.bins`(不自动做依赖检查)——当前 skill 正文直接调 `gitlink-cli`,已满足运行需求。
### 3.2 加载机制(官方文档明确)
- Claude Code 扫描 `<project>/.claude/skills/<name>/SKILL.md`(项目级),与用户级**合并生效**(同名时 personal 覆盖 project)
- 启动时扫描 + 运行中 live change detection 双层
- **会话启动后才新建顶层 `.claude/skills/` 目录 → 必须重启会话**才能发现
### 3.3 Junction 穿透(文档未承诺,推断)
- junction 读取 SKILL.md(标准文件 I/O):**几乎肯定 OK**
- live change detection 的 watch 行为:**不确定**
- **结论**:不依赖运行时变更感知,保证启动扫描读到即可;采用逐 skill junction 降低单点风险(见 §4.1)。
## 4. 设计方案
### 4.1 逐 skill Junction(核心)
`.claude/skills/` 为真实目录,其下每个 skill 子目录是一个 junction,指向项目根 `skills/<同名>`:
```
.claude/skills/gitlink-compliance → skills/gitlink-compliance
.claude/skills/gitlink-newcomer-guide → skills/gitlink-newcomer-guide
... (共 23 个)
```
**为何逐 skill 而非整个 `.claude/skills` 单 junction**:Claude Code 文档未承诺 junction 的 live-watch 行为;逐 skill junction 使 `.claude/skills/` 本身是真实目录,启动扫描最稳,单点 watch 失效不影响整体(基于 §3.3 推断 + 兼容性优先)。
### 4.2 .gitignore
忽略 `.claude/skills/`(junction 区域,不应入库——junction 指向本地源,他人 clone 后无效)。
### 4.3 命令桥接
复用全局 `gitlink-cli`(已登录)。无需额外桥接。
## 5. 数据流
`cd gitlink-cl` → 启动 Claude Code → 扫描 `.claude/skills/*/SKILL.md`(穿透 junction 读源)→ 注册 23 个 skill → 用户自然语言/slash 触发 → AI 按 SKILL.md 调 `gitlink-cli ...`
## 6. 验证方案
实现后,在 `gitlink-cl` 目录开**新** Claude Code 会话(必须新会话,见 §3.2):
1. 问 "What skills are available?" / 查 skill 列表 → 确认 23 个 `gitlink-*` 出现
2. `/doctor` → 确认无 skill 加载错误、无 description 预算溢出
3. 端到端:触发一个只读 skill(如 `gitlink-newcomer-guide``issue +list` 步骤)→ 确认 `gitlink-cli` 命令链通
## 7. 错误处理与退路
| 故障 | 处理 |
|---|---|
| junction 建立失败(已存在/路径错) | 清理已存在项,重试 |
| Claude Code 不识别 junction(/doctor 报错或 skill 不出现) | **退路:真实复制** `skills/*``.claude/skills/`(牺牲单一来源,换 100% 兼容) |
| frontmatter 非标准字段导致加载失败(极小概率) | 移除 `version`/`metadata` 字段或迁入正文 |
| skill 不出现 | 确认是新会话(非运行中新建);确认 `.claude/skills/` 真实存在 |
## 8. 范围外(YAGNI)
- 全局安装(`~/.claude/skills/`)
- 修改 skill 源内容
- settings.json 额外配置(除非退路需要)
- skill 的 hooks/依赖检查自动化(SKILL.md 正文已含直接调用)

View File

@ -1,289 +0,0 @@
# 子任务三 & 子任务四 — 工作交接文档
> 最后更新2026-06-30
> 提交记录:`378d8f1` — 46 files changed, 5493 insertions
> Issue[#19](https://gitlink.org.cn/z2_cc/gitlink-cli/issues/19) / [#20](https://gitlink.org.cn/z2_cc/gitlink-cli/issues/20)
---
## 一、总体架构
```
e:/gitlink-cli/gitlink-cli/
├── skills/
│ ├── gitlink-community-ops/ # 子任务三 - 场景A
│ ├── gitlink-quality-gate/ # 子任务三 - 场景B
│ ├── gitlink-research-insight/ # 子任务四 - 模块C
│ ├── gitlink-research-hotspot/ # 子任务四 - 模块D
│ └── gitlink-shared/scripts/ # 共享工具
│ ├── detect-cli.sh # CLI 版本自动检测
│ └── md-to-html.js # Markdown→HTML 转换器
├── doc/
│ ├── sub-task3-scenario-a/ # 场景A 架构图+报告
│ ├── sub-task3-scenario-b/ # 场景B 架构图+报告
│ ├── sub-task4-module-c/ # 模块C 架构图+报告
│ └── sub-task4-module-d/ # 模块D 架构图+报告
├── .devops/
│ ├── 构建流水线.yml # 原有(修改)
│ ├── 社区运营流水线.yml # 新增
│ └── 代码质量门禁流水线.yml # 新增
└── CLAUDE.md # 修改(新增 skill 映射)
```
---
## 二、子任务三:端到端自动化工作流
### 场景A社区运营自动化
**三阶段流水线:** Issue 分拣 → 社区周报 → Release Notes
| 文件 | 作用 |
|------|------|
| `skills/gitlink-community-ops/SKILL.md` | Skill 定义,引用 issue-triage/project-health/release-auto |
| `examples/community-ops-workflow.md` | 端到端工作流示例 |
| `scripts/01-issue-triage.sh` | Phase 1采集 Issue → 关键词权重分析 → 建议标签 |
| `scripts/02-weekly-health-report.sh` | Phase 2采集 Issue/PR/Commit/Milestone → 生成周报 |
| `scripts/03-auto-release-notes.sh` | Phase 3获取提交历史 → 分类 → 生成 Release Notes |
| `scripts/community-ops-full.sh` | 全流程编排(依次调用三阶段) |
| `scripts/health-analyze.js` | 周报数据分析引擎(计算关闭率/评分/改进建议) |
| `scripts/release-analyze.js` | Release Notes 分析引擎(按 Conventional Commits 分类) |
**运行方式:**
```bash
cd e:/gitlink-cli/gitlink-cli
DRY_RUN=true bash skills/gitlink-community-ops/scripts/community-ops-full.sh z2_cc gitlink-cli
```
### 场景B代码质量看门人
**四阶段门禁:** PR 采集 → 深度审查 → CI 检查 → 质量评分决策
| 文件 | 作用 |
|------|------|
| `skills/gitlink-quality-gate/SKILL.md` | Skill 定义 |
| `examples/quality-gate-workflow.md` | 工作流示例 |
| `scripts/01-collect-prs.sh` | Phase 1列出待审 PR |
| `scripts/02-deep-review.sh` | Phase 2获取 PR 详情/文件/diff/评审历史 |
| `scripts/03-ci-check.sh` | Phase 3检查 CI 构建状态 |
| `scripts/04-quality-gate-decision.sh` | Phase 4计算评分 → 自动合并/给修改建议 |
| `scripts/quality-gate-full.sh` | 全流程编排(遍历所有待审 PR |
**评分模型:**
```
质量总分 = CodeReview×40% + CI状态×30% + 设计一致性×30%
门槛≥70 分且 CI 通过 → 自动合并
```
**运行方式:**
```bash
DRY_RUN=true bash skills/gitlink-quality-gate/scripts/quality-gate-full.sh z2_cc gitlink-cli
```
---
## 三、子任务四:应用 GitLink 辅助科研
### 模块C科研项目洞悉
**流程:** 8 维数据采集 → 4 维度评分 → 结构化报告
| 文件 | 作用 |
|------|------|
| `skills/gitlink-research-insight/SKILL.md` | Skill 定义 |
| `examples/research-insight-workflow.md` | 工作流示例 |
| `scripts/01-collect-repo-data.sh` | 采集 repo/commit/issue/pr/collaborator/topics/languages |
| `scripts/02-analyze-contributions.sh` | 调用 analyze.js 计算评分 |
| `scripts/analyze.js` | **数据分析引擎**:读取 JSON → 计算成熟度/文档/贡献/社区评分 → 生成报告 |
| `scripts/research-insight-full.sh` | 全流程编排 |
**评分维度:**
- 成熟度25%):年龄 + Star + Fork + 更新频率
- 文档质量20%README + License + CI
- 贡献模式30%):贡献者数 + 提交频率
- 社区健康度25%Issue 关闭率 + PR 合并率
**运行方式:**
```bash
bash skills/gitlink-research-insight/scripts/research-insight-full.sh z2_cc gitlink-cli
```
### 模块D热点追踪与知识图谱
**流程:** 多关键词搜索 → 数据丰富 → 知识图谱 → 趋势报告
| 文件 | 作用 |
|------|------|
| `skills/gitlink-research-hotspot/SKILL.md` | Skill 定义 |
| `examples/hotspot-workflow.md` | 工作流示例 |
| `scripts/01-search-repos.sh` | 多关键词搜索 + 去重 + 数据丰富 |
| `scripts/02-build-knowledge-graph.sh` | 调用 hotspot-analyze.js + kg-to-html.js |
| `scripts/hotspot-analyze.js` | **数据分析引擎**:提取实体关系,生成知识图谱和趋势报告 |
| `scripts/kg-to-html.js` | **交互式可视化**:生成可缩放/拖拽/高亮的 HTML 图谱 |
| `scripts/hotspot-tracker-full.sh` | 全流程编排 |
**运行方式:**
```bash
bash skills/gitlink-research-hotspot/scripts/hotspot-tracker-full.sh "machine learning" "深度学习" "自然语言处理"
```
---
## 四、共享工具
| 文件 | 作用 |
|------|------|
| `skills/gitlink-shared/scripts/detect-cli.sh` | **CLI 版本检测**:优先使用本地编译版本(支持 commit +list 等完整命令),回退系统 PATH 版本 |
| `skills/gitlink-shared/scripts/md-to-html.js` | **报告可视化**:将任意 Markdown 报告转为带评分环、表格着色、响应式布局的 HTML 页面 |
---
## 五、报告文档
| 文档路径 | 内容 |
|----------|------|
| `doc/sub-task3-scenario-a/架构图` | Mermaid 社区运营流程 |
| `doc/sub-task3-scenario-a/新需求构思报告` | 需求背景、详述、技术方案、风险评估 |
| `doc/sub-task3-scenario-a/变更影响分析及测试报告` | 变更范围、测试计划、风险、结论 |
| `doc/sub-task3-scenario-b/架构图` | Mermaid 质量门禁流程 + 评分模型 |
| `doc/sub-task3-scenario-b/新需求构思报告` | 同上 |
| `doc/sub-task3-scenario-b/变更影响分析及测试报告` | 同上 |
| `doc/sub-task4-module-c/架构图` | 科研洞察四层架构 |
| `doc/sub-task4-module-c/research-insight-report` | 洞察报告模板 |
| `doc/sub-task4-module-d/架构图` | 热点追踪三层架构 |
| `doc/sub-task4-module-d/hotspot-trend-report` | 趋势报告模板 |
| `doc/sub-task4-module-d/knowledge-graph` | 知识图谱说明 |
---
## 六、DevOps 流水线
| 文件 | 触发 | 功能 |
|------|------|------|
| `.devops/构建流水线.yml` | Push 触发 | Go 编译验证 |
| `.devops/社区运营流水线.yml` | 定时触发 | SSH 执行 community-ops-full.sh |
| `.devops/代码质量门禁流水线.yml` | PR 事件 | SSH 执行 quality-gate-full.sh |
> ⚠️ 需要到 GitLink 仓库开启 DevOps 引擎并配置 SSH 密钥才能运行
---
## 七、常见问题
### Q1如何让 commit +list 等命令可用?
当前系统 PATH 的 npm 版 CLI 不包含全部命令。脚本已自动检测本地编译版本,只需编译即可:
```bash
cd e:/gitlink-cli/gitlink-cli && go build -o gitlink-cli.exe .
```
### Q2脚本默认会修改数据吗
**不会。** 所有写操作issue +update / pr +merge / release +create默认受 `DRY_RUN=true` 保护。
需要实际执行时:
```bash
DRY_RUN=false bash scripts/xxx.sh <owner> <repo>
```
### Q3输出文件在哪
所有脚本的输出保存在各自 `scripts/_output/` 目录下,包含 JSON 数据、Markdown 报告和 HTML 可视化。
`.gitignore` 已忽略 `_output/` 目录。
### Q4如何查看可视化报告
```bash
# 科研洞察报告
explorer "skills/gitlink-research-insight/scripts/_output/research-insight-report.html"
# 社区周报
explorer "skills/gitlink-community-ops/scripts/_output/weekly-health-report.html"
# Release Notes
explorer "skills/gitlink-community-ops/scripts/_output/release-notes-v0.1.0.html"
# 知识图谱(交互式)
explorer "skills/gitlink-research-hotspot/scripts/_output/knowledge-graph-machine learning.html"
# 热点趋势报告
explorer "skills/gitlink-research-hotspot/scripts/_output/hotspot-trend-report-machine learning.html"
```
---
## 八、文件清单46 个文件)
### 新增文件44 个)
```
skills/gitlink-community-ops/
├── SKILL.md
├── examples/community-ops-workflow.md
└── scripts/
├── 01-issue-triage.sh
├── 02-weekly-health-report.sh
├── 03-auto-release-notes.sh
├── community-ops-full.sh
├── health-analyze.js
└── release-analyze.js
skills/gitlink-quality-gate/
├── SKILL.md
├── examples/quality-gate-workflow.md
└── scripts/
├── 01-collect-prs.sh
├── 02-deep-review.sh
├── 03-ci-check.sh
├── 04-quality-gate-decision.sh
└── quality-gate-full.sh
skills/gitlink-research-insight/
├── SKILL.md
├── examples/research-insight-workflow.md
└── scripts/
├── 01-collect-repo-data.sh
├── 02-analyze-contributions.sh
├── analyze.js
└── research-insight-full.sh
skills/gitlink-research-hotspot/
├── SKILL.md
├── examples/hotspot-workflow.md
└── scripts/
├── 01-search-repos.sh
├── 02-build-knowledge-graph.sh
├── hotspot-analyze.js
├── hotspot-tracker-full.sh
└── kg-to-html.js
skills/gitlink-shared/scripts/
├── detect-cli.sh
└── md-to-html.js
doc/
├── sub-task3-scenario-a/
│ ├── architecture-diagram.md
│ ├── 新需求构思报告.md
│ └── 变更影响分析及测试报告.md
├── sub-task3-scenario-b/
│ ├── architecture-diagram.md
│ ├── 新需求构思报告.md
│ └── 变更影响分析及测试报告.md
├── sub-task4-module-c/
│ ├── architecture-diagram.md
│ └── research-insight-report.md
├── sub-task4-module-d/
│ ├── architecture-diagram.md
│ ├── hotspot-trend-report.md
│ └── knowledge-graph.md
└── sub-task34-交接文档.md ← 本文件
.devops/
├── 社区运营流水线.yml
└── 代码质量门禁流水线.yml
```
### 修改文件2 个)
```
.gitignore — 添加 _output/ .cli-bin/ *.json 忽略规则
CLAUDE.md — 添加 4 个新 skill 映射
```
---
*如有疑问,查看 Issue #19(子任务三)和 #20(子任务四)*

View File

@ -1,154 +0,0 @@
# 工作日志 — 子任务三 & 子任务四
> 项目GitLink CLI 课程实践(《软件演化与运维》)
> 周期2026-06-29 ~ 2026-06-30
> 提交记录:`378d8f1` → `b0d46b4`
---
## 2026-06-29
### 上午:需求理解与方案设计
| 时间段 | 工作内容 |
|--------|----------|
| 09:00-09:30 | 阅读课程实践任务文档0613了解子任务三/四要求 |
| 09:30-09:50 | 探索 gitlink-cli 项目现有结构和资产CLI 命令、Skills、DevOps |
| 09:50-10:30 | 设计总体方案,确认四个模块的技术路线 |
| 10:30-11:00 | 用户确认方案:子任务三两个场景、子任务四两个模块,先设计后实现 |
**决策记录:**
- 子任务三选「社区运营自动化」+「代码质量看门人」两个场景
- 子任务四选「科研项目洞悉」+「热点追踪与知识图谱」两个模块
- 使用 Bash 脚本 + JS 分析引擎的模式,保证可复现性
- 所有写操作默认 DRY_RUN=true
### 上午Phase 1-2 — Skill 定义和工作流示例
| 时间段 | 工作内容 | 文件数 |
|--------|----------|--------|
| 11:00-11:20 | 创建目录结构20 个目录) | — |
| 11:20-11:40 | 编写 4 个 SKILL.md 定义文件 | 4 |
| 11:40-12:00 | 编写 4 个工作流示例文档 | 4 |
### 下午Phase 3 — 可复现脚本开发
| 时间段 | 工作内容 | 文件数 |
|--------|----------|--------|
| 13:00-14:00 | 社区运营 4 个脚本01-issue-triage / 02-weekly / 03-release / full | 4 |
| 14:00-14:40 | 质量门禁 5 个脚本01-PR采集 / 02-审查 / 03-CI检查 / 04-决策 / full | 5 |
| 14:40-15:10 | 科研洞察 3 个脚本01-数据采集 / 02-分析 / full | 3 |
| 15:10-15:30 | 热点追踪 3 个脚本01-搜索 / 02-图谱 / full | 3 |
### 下午Phase 4-5 — 架构图和报告文档
| 时间段 | 工作内容 | 文件数 |
|--------|----------|--------|
| 15:30-15:50 | 4 个 Mermaid 架构图 | 4 |
| 15:50-16:30 | 子任务三 4 份报告(新需求构思+变更测试 × 2场景 | 4 |
| 16:30-17:00 | 子任务四 4 份报告(洞察报告/趋势报告/知识图谱说明) | 4 |
### 下午Phase 6 — 配置更新
| 时间段 | 工作内容 |
|--------|----------|
| 17:00-17:15 | 更新 CLAUDE.md4 个新 skill 映射) |
| 17:15-17:25 | 创建 2 条 DevOps 流水线 + 更新 .gitignore |
| 17:25-17:30 | 拷贝 SKILL.md 到 .claude/skills/ |
### 第一次测试与修复
| 时间 | 问题 | 修复 |
|------|------|------|
| 17:30 | 周报变量未展开 | heredoc `'EOF'``EOF` |
| 17:30 | `commit +list` / `collaborator +list` 不可用 | 发现是系统 PATH 用了 npm 旧版 CLI |
| 17:35 | 科研分析只输出模板 | 创建 `analyze.js` 独立 JS 分析引擎 |
| 17:40 | node 参数太长 | 改用 JS 直接读文件 |
| 17:50 | search 去重失败 | 修复 MSYS 路径问题 + JSON 结构解析 |
| 17:55 | 知识图谱 `[object Object]` | 修复 topic/language 字段为对象类型 |
**问题根因汇总:**
1. 系统 `gitlink-cli` 是 npm 安装的旧版本421 字节的 JS wrapper缺少 `commit`、`collaborator` 等命令
2. MSYS2 路径 `/e/xxx` 传给 node 时变成了 `E:\e\xxx` — 需要用 `process.argv` 传参或绝对路径
3. GitLink API 返回的 `topics``language` 字段是 `{id, name}` 对象而不是字符串
---
## 2026-06-30
### 上午:第二次测试与修复
| 时间 | 问题 | 修复 |
|------|------|------|
| 08:00 | 科研洞察描述为空 | 从 issue.project.description 获取 |
| 08:05 | 热点搜索仍是 0 条 | 创建 `hotspot-analyze.js` + 修复 node 路径 |
| 08:10 | CLI 检测失效alias 在脚本中无效) | 创建 `detect-cli.sh`,用 wrapper + PATH 覆盖 |
| 08:15 | 周报/Release Notes 还是模板 | 创建 `health-analyze.js` + `release-analyze.js` |
| 08:20 | Release Notes 文件/行数为 0 | fallback 路径缺 `git log --stat`,补充 + 中文正则 |
| 08:30 | 知识图谱关系太简单 | 重写 `kg-to-html.js`:缩放/拖拽/高亮/侧栏/导出 |
| 08:35 | 报告只有 Markdown 不便展示 | 创建 `md-to-html.js` 通用转换器 |
### 最终验证
| 模块 | 命令 | 结果 |
|------|------|------|
| 科研洞察 | `research-insight-full.sh z2_cc gitlink-cli` | ✅ 16 贡献者、15 Issue、4.8/10 分 |
| 热点追踪 | `hotspot-tracker-full.sh "machine learning" "深度学习"` | ✅ 33 仓库、19 主题标签、11 语言 |
| 社区运营 | `community-ops-full.sh z2_cc gitlink-cli` | ✅ 三阶段完整输出 |
| 质量门禁 | `quality-gate-full.sh z2_cc gitlink-cli` | ✅ 脚本就绪(当前无 PR |
### 代码提交与 Issue
| 时间 | 操作 |
|------|------|
| 09:00 | commit #146 文件5493 行 |
| 09:05 | git push 到 `z2_cc/gitlink-cli` |
| 09:10 | 创建 Issue #19(子任务三)和 #20(子任务四) |
| 09:15 | 补充交接文档并提交 |
---
## 2026-06-30 下午:文档整理与技术债务优化
### 文档结构清理
| 时间 | 操作 |
|------|------|
| 10:00 | 删除分散的 4 份报告scenario-a/b 各 2 份)|
| 10:05 | 创建统一《新需求构思报告》(覆盖子任务一至四)|
| 10:10 | 创建统一《变更影响分析及测试报告》(含完整测试结果)|
| 10:20 | 删除多余的 architecture-diagram、demo 等 9 个文件 |
| 10:25 | 精简 doc/ 目录从 17 个文件降至 8 个 |
### 技术债务优化
| 时间 | 问题 | 修复 |
|------|------|------|
| 10:30 | Release Notes 依赖 git log | `release-analyze.js` 新增 API JSON 输入支持 |
| 10:35 | 非 git 目录 Release Notes 为空 | `03-auto-release-notes.sh` 后备使用 `commit +list --format json` |
| 10:40 | 缺少 CLI 安装指引 | 新建 `scripts/setup-local-cli.sh` 一键编译脚本 |
---
## 统计汇总
| 维度 | 数据 |
|------|------|
| 总工作时长 | 约 10 小时 |
| 交付文件数 | 47 个(含交接文档) |
| 代码行数 | ~5,800 行 |
| 修复迭代次数 | 14 次 |
| 最终验证通过率 | 100% |
| Git 提交 | 6 次(`378d8f1` `b0d46b4` `7b43711` `393a090` `c0c7580` `f44471d` `92f65a9` `74f6aea` |
| GitLab Issue | 2 个(#19, #20 |
---
## 技术债务 / 待改进
| 项目 | 状态 | 说明 |
|------|------|------|
| CLI 版本一致化 | ✅ 已优化 | 新增 `scripts/setup-local-cli.sh` 一键编译+设置 |
| Git Log 依赖 | ✅ 已优化 | `release-analyze.js` 支持 API JSON 后备,无需 git 仓库 |
| HTML 可视化 | ⏳ 可接受 | `md-to-html.js` 对当前报告已够用 |
| 测试覆盖 | ⏳ 待补充 | 已做端到端验证,缺自动化单元测试 |

Binary file not shown.

Binary file not shown.

View File

@ -1,92 +0,0 @@
# 项目汇报演示脚本
> 配合 `doc/汇报PPT.pptx` 使用
---
## 演示流程(总时长约 10 分钟)
### 1. 开场 + 背景1 分钟)
**讲述:** "大家好,我们团队完成了 GitLink 智能化能力提升项目。gitlink-cli 是 GitLink 的命令行工具我们围绕它做了四大块工作CLI 扩展、AI Agent Skills、端到端工作流、科研辅助。"
### 2. 子任务一CLI 能力1 分钟)
**讲述:** "我们新增了 23 个 Shortcut 命令组、181+ 个子命令。关键新增包括 Webhook 投递监控、Wiki 管理、代码片段管理、REPL 交互模式。同时实现了 4 个平台的包管理npm/brew/scoop/choco。"
### 3. 子任务二Skills1 分钟)
**讲述:** "我们开发了 11 个 Claude Code Skills涵盖 Issue 自动分拣、代码深度审查、项目健康度报告、自动 Release Notes、合规检查等场景。全部在 Claude Code 端到端验证通过。"
### 4. 子任务三社区运营自动化2 分钟)— ⭐ 现场演示
**操作:**
```bash
cd e:/gitlink-cli/gitlink-cli
DRY_RUN=true bash skills/gitlink-community-ops/scripts/community-ops-full.sh z2_cc gitlink-cli
```
**讲述:** "这条命令一键执行三阶段流水线Issue 自动分拣 → 社区周报生成 → Release Notes 发布。默认 dry-run 模式,不会修改实际数据。"
**展示输出重点:**
- Phase 1Issue 列表和分类建议
- Phase 2生成的周报文件 `_output/weekly-health-report.md`
- Phase 3生成的 Release Notes
**展示 HTML 报告:**
```bash
explorer "skills/gitlink-community-ops/scripts/_output/weekly-health-report.html"
```
### 5. 子任务四科研洞察2 分钟)— ⭐ 现场演示
**操作:**
```bash
bash skills/gitlink-research-insight/scripts/research-insight-full.sh z2_cc gitlink-cli
```
**讲述:** "科研洞察模块采集仓库的 8 维数据包括仓库信息、主题标签、语言分布、贡献者、提交历史、Issue、PR、协作者然后从成熟度、文档质量、贡献模式、社区健康度四个维度评分。"
**展示输出:**
```bash
cat skills/gitlink-research-insight/scripts/_output/research-insight-report.md
```
**展示 HTML**
```bash
explorer "skills/gitlink-research-insight/scripts/_output/research-insight-report.html"
```
### 6. 子任务四热点追踪与知识图谱2 分钟)— ⭐ 现场演示
**操作:**
```bash
bash skills/gitlink-research-hotspot/scripts/hotspot-tracker-full.sh "machine learning" "深度学习"
```
**讲述:** "热点追踪模块通过多关键词搜索 GitLink 平台,发现相关仓库并自动构建知识图谱。"
**展示交互式 HTML 图谱:**
```bash
explorer "skills/gitlink-research-hotspot/scripts/_output/knowledge-graph-machine learning.html"
```
**讲述:** "图谱支持缩放、拖拽、点击高亮和 SVG 导出。"
### 7. 总结1 分钟)
**讲述:** "项目共交付 47 个文件、约 5,800 行代码。刘焱负责 CLI 底层架构,赵昌负责命令实现和 Skills 开发,曾蔚然负责 DevOps 流水线和审查 Skills。演示完毕谢谢"
---
## 演示环境检查清单
- [ ] `go build -o gitlink-cli.exe .`(确保 CLI 已最新编译)
- [ ] `gitlink-cli auth status`(确保已登录)
- [ ] 网络通畅(需要访问 GitLink API
- [ ] 预留 5 分钟提前运行采集脚本(热点搜索耗时较长)
## 备用方案
- 如果热点搜索耗时太长,可预先运行并将结果保存,演示时直接打开 HTML
- 如果网络不通,展示 GitHub 上的代码结构和已生成的 HTML 报告文件

View File

@ -1,269 +0,0 @@
# 科研辅助场景使用文档
> 子任务四 · 5 大科研辅助模块完整使用指南
> 最后更新2026-07-04
> 全程只读,可放心对任意公开仓库运行
## 目录
1. [模块 A科研项目洞悉](#模块-a科研项目洞悉)
2. [模块 B热点追踪与知识图谱](#模块-b热点追踪与知识图谱)
3. [模块 C科研合规与复现性](#模块-c科研合规与复现性)
4. [模块 D科研协作智能匹配](#模块-d科研协作智能匹配)
5. [模块 E科研进度跟踪与预警](#模块-e科研进度跟踪与预警)
6. [委托模式说明](#委托模式说明)
---
## 模块 A科研项目洞悉
### 功能
回答"这个科研项目怎么样?"——采集 8 维数据,做 4 维评分,生成 HTML 报告。
### 使用方法
```bash
# 基本用法
cd skills/gitlink-research-insight/scripts
DRY_RUN=true bash research-insight-full.sh z2_cc gitlink-cli
# 实际运行(生成报告)
bash research-insight-full.sh z2_cc gitlink-cli
```
### 8 维数据采集
| 维度 | 数据来源 | 示例 |
|------|----------|------|
| 仓库信息 | `repo +info` | name/default_branch/size |
| 主题标签 | `repo +info` → topics | gitlink/cli/tools |
| 语言分布 | `repo +info` → languages | Go 70.1%/JS 22.7%/Shell 6.7% |
| 贡献者 | `repo +contributors` | 16 人 |
| 提交记录 | `commit +list --limit 100` | 100 条 |
| Issue | `issue +list --state all` | 17 个 |
| PR | `pr +list --state all` | 2 个 |
| 协作者 | `collaborator +list` | 3 人 |
### 4 维评分模型
| 维度 | 权重 | 子维度 |
|------|------|--------|
| 成熟度 | 25% | 年龄(25%)+影响力(25%)+Fork(20%)+维护(30%) |
| 文档质量 | 20% | README+LICENSE+CI+CHANGELOG |
| 贡献模式 | 30% | 贡献者数量+质量 |
| 社区健康度 | 25% | Issue 关闭率+PR 合并率+响应速度 |
### 验证结果z2_cc/gitlink-cli
| 维度 | 评分 | 说明 |
|------|------|------|
| 成熟度 | 2.8/10 | 0 个月、0 Star、2 Fork早期阶段 |
| 文档质量 | 5.0/10 | 有 README 缺 LICENSE 和 CI |
| 贡献模式 | 6.8/10 | 16 人协作良好 |
| 社区健康度 | 4.4/10 | Issue 关闭率低 |
| **综合** | **4.8/10** | — |
### 产物
`_output/research-insight-report.html` — 交互式 HTML 报告
---
## 模块 B热点追踪与知识图谱
### 功能
回答"这个领域有哪些相关项目?"——多关键词搜索 → 实体关系提取 → 交互式知识图谱。
### 使用方法
```bash
cd skills/gitlink-research-hotspot/scripts
bash hotspot-full.sh gitlink CLI
# 参数关键词1 关键词2 ...(支持任意数量)
```
### 工作流程
1. **多关键词搜索**:搜索"gitlink"+"CLI",去重后 21 个仓库
2. **数据丰富**:采集每个仓库的 Star/Fork/语言/主题/组织
3. **实体识别**:项目 21 | 主题 4 | 技术栈 2 | 组织 4
4. **关系提取**belongs_to / topic / language / depends_on
5. **可视化**Mermaid 知识图谱 + HTML 交互式渲染
### 验证结果
搜索"gitlink"+"CLI"找到 21 个仓库,构建知识图谱:
- 4 主题java / dockerfile / batchfile / swift
- 2 技术栈Go / Java
- 4 组织Gitlink / wangtao / otto / mozilong
- 4 种关系belongs_to / topic / language / depends_on
### 产物
- `_output/knowledge-graph-gitlink.html` — 交互式知识图谱(支持缩放/拖拽/点击高亮)
- `_output/hotspot-trend-report-gitlink.html` — 热点趋势报告
---
## 模块 C科研合规与复现性
### 功能
回答"这个科研仓库别人能跑出一样结果吗?"——三维复现性证据链审查。
### 使用方法
```bash
cd skills/gitlink-research-compliance
# 按 SKILL.md 步骤执行(全程只读)
gitlink-cli repo +info --owner ifzhang --repo FairMOT --format json
gitlink-cli file +get --owner ifzhang --repo FairMOT --path LICENSE --format json
gitlink-cli file +readme --owner ifzhang --repo FairMOT --format json
gitlink-cli dataset +list --owner ifzhang --repo FairMOT --format json
gitlink-cli release +list --owner ifzhang --repo FairMOT --format json
```
### 三维复现性证据链
| 维度 | 检查项 | 命令 |
|------|--------|------|
| ① 数据可用性 | dataset +list / README 数据说明 / 是否随仓托管 | `dataset +list` / `file +readme` |
| ② 环境可复现 | requirements.txt / Dockerfile / CI / 依赖锁定 | `file +get --path requirements.txt` |
| ③ 结果可验证 | release 权重 / 测试脚本 / 指标一致性 | `release +list` |
### 委托模式
委托 `gitlink-compliance` 跑通用合规层LICENSE/依赖/版权),自研复现性证据链。两者正交不重复。
### 验证结果ifzhang/FairMOT
| 维度 | 发现 | 等级 |
|------|------|------|
| 合规 | MIT License · Copyright (c) 2020 YifuZhang | ✅ |
| 数据 | README 给下载来源,未随仓托管 | ⚠️ |
| 环境 | requirements.txt: yacs/opencv/cython/motmetrics | ✅ |
| 结果 | release 0 个,无预训练权重 | ❌ |
| 引用 | README 无 cite/BibTeX | ⚠️ |
### 产物哲学
输出**证据导向审查记录**(非分数排名)。每个发现先呈现"看到了什么"(文件内容/存在性/原文片段),让科研读者自行判断可复现性。
---
## 模块 D科研协作智能匹配
### 功能
回答"谁适合做什么任务?"——从提交历史推断角色,按角色匹配待办 Issue。
### 使用方法
```bash
cd skills/gitlink-research-matching
# 按 SKILL.md 步骤执行
gitlink-cli pr +list --owner Gitlink --repo forgeplus --format json > .probe-data/pr.json
gitlink-cli issue +list --owner Gitlink --repo forgeplus --format json > .probe-data/issue.json
gitlink-cli commit +list --owner Gitlink --repo forgeplus --limit 50 --format json > .probe-data/commit.json
```
### 4 角色推断
| 角色 | 推断信号 | 示例 |
|------|----------|------|
| 数据 | PR 标题含"data" / 分支名含"data/" / 文件路径含"data/" | 数据采集/清洗/标注 |
| 算法 | PR 标题含"model" / 分支名含"model/" / 文件路径含"model/" | 模型设计/实验 |
| 工程 | PR 标题含"fix:" / 分支名含"fix/" / 文件路径含"src/" | 框架/部署/工具链 |
| 评测 | PR 标题含"eval" / 分支名含"eval/" / 文件路径含"eval/" | 指标/对比/分析 |
### 委托模式
委托 `gitlink-research-insight` 提供贡献者画像数据自研角色匹配。insight 是数据层,本模块是分析层。
### 验证结果Gitlink/forgeplus
4246 Issue / 355 PR3 位活跃贡献者:
| 贡献者 | PR 数 | 推断角色 | 置信度 | 依据 |
|--------|-------|----------|--------|------|
| xxq250 | 12 | 工程 | 🟡 中 | 版本发布号+部署说明 |
| dtwdtw | 7 | 工程 | 🟢 高 | 全部 fix: 前缀 |
| maxjhandsome | 1 | 工程 | 🔴 低 | PR 数不足 |
**角色覆盖偏科**3 人全落"工程"角色,无数据/算法/评测。这本身也是匹配算法的正确输出。
---
## 模块 E科研进度跟踪与预警
### 功能
回答"项目卡在哪了、有什么风险?"——6 维风险信号检测 + 100 分制评分。
### 使用方法
```bash
cd skills/gitlink-research-progress
# 按 SKILL.md 步骤执行
gitlink-cli repo +info --owner Gitlink --repo gitlink-cli --format json
gitlink-cli issue +list --owner Gitlink --repo gitlink-cli --state all --format json
gitlink-cli commit +list --owner Gitlink --repo gitlink-cli --limit 50 --format json
gitlink-cli milestone +list --owner Gitlink --repo gitlink-cli --format json
```
### 6 维风险信号
| 信号 | 检测逻辑 | 风险等级 |
|------|----------|----------|
| ① 长期停滞 | 未解决 Issue 停留 >60 天 | 🔴 高 |
| ② 高优无人 | 高优先级 Issue 无人认领 | 🔴 高 |
| ③ 零回复 | 未解决且 0 评论 | 🟡 中 |
| ④ 积压恶化 | 近 30 天新增 > 关闭 | 🟡 中 |
| ⑤ 提交突变 | 提交活跃度骤降/骤升 | 🟡 中 |
| ⑥ 里程碑 DDL | 里程碑临近且未完成 | 🔴 高 |
### GitLink 数据现实(重要)
| 数据维度 | GitLink 现状 | 应对 |
|----------|-------------|------|
| 里程碑 | 几乎无人使用total_count=0 | 信号⑥设为可选 |
| Issue due_date/done_ratio | 普遍为空 | 不依赖 |
| Issue status | 中文:新增/关闭/已解决 | 按 status.name 客户端重统计 |
| Issue 时间序列 | ✅ 可靠可用 | 信号①②③④数据基础 |
| 提交时间序列 | ✅ 可靠可用(秒级时间戳) | 信号⑤数据基础 |
因此本模块**不以里程碑 DDL 为核心**,而以 Issue+提交时间序列为预警锚点。
### 委托模式
委托 `gitlink-project-health` 跑静态健康度(关闭率/活跃度评分),自研动态风险预警。两者正交。
### 验证结果Gitlink/gitlink-cli
19 Issue9 新增/10 关闭),关闭率 53%
| 信号 | 发现 | 等级 |
|------|------|------|
| ① 长期停滞 | #2(86天) #5(65天) #6(64天) + 4 个 30-60 天 | 🔴 高 |
| ③ 零回复 | #17、#18 未解决且 0 评论 | 🟡 中 |
| ⑤ 提交突变 | 近 30 天 15 条 vs 前 30 天 0 条 → 活跃上升期 | 🟢 低 |
评分62/100
---
## 委托模式说明
5 个科研模块普遍采用"委托通用 Skill + 自研科研层"模式:
| 科研模块 | 委托的通用模块 | 自研部分 | 边界 |
|----------|---------------|----------|------|
| research-compliance | compliance合规层 | 复现性证据链 | 合规管"合法",本模块管"可复现" |
| research-matching | research-insight画像 | 角色匹配 | insight 管数据,本模块管分析 |
| research-progress | project-health健康度 | 时间线风险预警 | health 管"现状",本模块管"趋势" |
设计原则:两者正交,不重复。通用 Skill 处理跨领域共性问题,科研层处理科研特有问题。
— 文档完 —

View File

@ -1,257 +0,0 @@
# 端到端工作流说明文档
> 子任务三 · 5 个端到端自动化场景
> 最后更新2026-07-07
## 一、总体架构
### 1.1 设计理念
5 个端到端场景统一采用"三阶段脚本 + JS 分析引擎 + DevOps 流水线"架构:
```
┌─────────────────────────────────────────────────────────┐
│ DevOps 流水线层 │
│ (1 条已部署 · push 触发) │
├─────────────────────────────────────────────────────────┤
│ 端到端编排层 │
│ community-ops / quality-gate / project-bootstrap / │
│ multi-repo-coordination / contributor-growth │
│ (各 *-full.sh 串联三阶段) │
├─────────────────────────────────────────────────────────┤
│ Phase 1 Phase 2 Phase 3 │
│ (01-*.sh) (02-*.sh) (03-*.sh) │
│ 数据采集 分析处理 执行/输出 │
├─────────────────────────────────────────────────────────┤
│ JS 分析引擎层 │
│ health-analyze / dashboard-gen / growth-analyze / │
│ skeleton-gen / scoring-engine │
│ (10 个 JS 引擎 · 2568 行) │
├─────────────────────────────────────────────────────────┤
│ CLI 命令层 │
│ gitlink-cli (24 命令组 · 17,005 行 Go) │
│ → GitLink API │
└─────────────────────────────────────────────────────────┘
```
### 1.2 通用设计原则
| 原则 | 说明 |
|------|------|
| 三阶段原子化 | 每阶段可单独运行,失败不影响前一阶段成果 |
| DRY_RUN 安全 | 默认 DRY_RUN=true只打印不实际执行写操作 |
| CLI 版本检测 | detect-cli.sh 自动检测 CLI 是否安装及版本兼容 |
| JSON 中间产物 | 阶段间通过 _output/*.json 传递数据,可调试可复现 |
| 优雅降级 | 离线/未认证时写空 JSON仍生成报告 |
## 二、场景一:社区运营自动化
### 2.1 架构图
```
community-ops-full.sh z2_cc gitlink-cli
├── Phase 1: Issue 自动分拣 (01-triage-issues.sh)
│ ├── gitlink-cli issue +list --state all
│ ├── 按关键词分类bug/feature/question/docs
│ └── 输出: _output/triage-report.json
├── Phase 2: 社区周报生成 (02-generate-weekly.sh)
│ ├── 采集: issues / prs / commits / contributors
│ ├── health-analyze.js 4 维评分
│ │ ├── Issue 关闭率 (30%)
│ │ ├── PR 合并率 (25%)
│ │ ├── 贡献者活跃度 (25%)
│ │ └── 响应速度 (20%)
│ └── 输出: _output/weekly-health-report.html
└── Phase 3: Release Notes (03-generate-release.sh)
├── gitlink-cli commit +list --limit 100
├── 按 Conventional Commits 分类
└── 输出: _output/release-notes-v0.1.0.html
```
### 2.2 关键数据
| 指标 | 实测值 |
|------|--------|
| Issue 总数 | 2117 打开/4 关闭) |
| 关闭率 | 19% |
| 综合评分 | 3.5/10 |
| 提交分类 | 22 新功能 / 15 Bug / 8 文档 |
| 贡献者 | 7 人 |
### 2.3 对应文件
- `skills/gitlink-community-ops/SKILL.md` — 设计规格
- `skills/gitlink-community-ops/scripts/community-ops-full.sh` — 串联脚本
- `skills/gitlink-community-ops/scripts/health-analyze.js` — 分析引擎
## 三、场景二:代码质量门禁
### 3.1 架构图
```
quality-gate-full.sh z2_cc gitlink-cli
├── Phase 1: PR 采集 (01-collect-prs.sh)
│ ├── gitlink-cli pr +list --state open
│ └── 逐个采集详情+变更文件
├── Phase 2: 深度审查 (02-deep-review.sh)
│ ├── 委托 pr-deep-review Skill
│ ├── Critical / Warning / Suggestion 三级
│ └── CodeReview 评分: 100 - Critical×20 - Warning×10 - Suggestion×3
├── Phase 3: 本地 CI 检查 (03-local-ci-check.sh)
│ ├── 本地 go build 编译验证
│ ├── 测试覆盖率
│ └── CI 评分: 全通过=100, 有失败=0一票否决
└── Phase 4: 门禁决策 (04-gate-decision.sh)
├── 质量总分 = CodeReview×40% + CI×30% + 设计一致性×30%
├── ≥70 + CI 通过 → 自动合并
└── <70 修改建议
```
### 3.2 评分模型
| 维度 | 权重 | 评分规则 |
|------|------|----------|
| CodeReview | 40% | 起始 100Critical -20 / Warning -10 / Suggestion -3 |
| CI 状态 | 30% | 全通过=100有失败=0一票否决 |
| 设计一致性 | 30% | PR 描述与代码变更匹配度 |
### 3.3 对应文件
- `skills/gitlink-quality-gate/SKILL.md`
- `skills/gitlink-quality-gate/scripts/quality-gate-full.sh`80 行)
- `skills/gitlink-quality-gate/scripts/03-local-ci-check.sh` — 本地 CI 检查
## 四、场景三:项目一键初始化
### 4.1 架构图
```
project-bootstrap-full.sh
├── Phase 1: 解析需求 + 创建仓库 (01-parse-and-create-repo.sh)
│ ├── AI 从 PROJECT_DESC 提取 name/desc/lang/license
│ ├── 输出: _output/project-spec.json
│ └── gitlink-cli repo +create
├── Phase 2: 生成项目骨架 (02-generate-skeleton.sh)
│ ├── skeleton-gen.js 按语言生成模板
│ │ ├── README.md
│ │ ├── LICENSE (MIT/Apache/GPL)
│ │ ├── .gitignore (Go/Python/JS 差异化)
│ │ └── CI 配置 (建木 YAML)
│ └── gitlink-cli file +batch 推送
└── Phase 3: Issue + 里程碑 (03-create-issues-milestones.sh)
├── gitlink-cli milestone +create v0.1.0
├── gitlink-cli label +create (good-first-issue/enhancement/bug)
└── gitlink-cli issue +create × 3
```
### 4.2 对应文件
- `skills/gitlink-project-bootstrap/SKILL.md`
- `skills/gitlink-project-bootstrap/scripts/project-bootstrap-full.sh`61 行)
- `skills/gitlink-project-bootstrap/scripts/skeleton-gen.js` — 骨架生成引擎
- `.devops/项目初始化流水线.yml`(手动触发)
## 五、场景四:多仓库协同
### 5.1 架构图
```
multi-repo-full.sh
│ REPOS="z2_cc/gitlink-cli,z2_cc/gitlink-bisync"
├── Phase 1: 统一 Issue 追踪 (01-unified-issue-tracker.sh)
│ ├── 遍历 REPOS 采集 open Issue
│ ├── 标题相似度匹配 (Jaccard >0.5)
│ └── 识别跨仓库关联 Issue
├── Phase 2: PR 看板 (02-pr-dashboard.sh)
│ ├── 采集 open/merged PR
│ ├── 识别长期未合并 PR (>30天)
│ └── dashboard-gen.js 生成看板
└── Phase 3: Release 协调 (03-release-coordination.sh)
├── 汇总各仓库最新版本号+发布日期
├── 版本对齐分析 (哪个落后)
└── 协调发布建议
```
### 5.2 对应文件
- `skills/gitlink-multi-repo-coordination/SKILL.md`
- `skills/gitlink-multi-repo-coordination/scripts/multi-repo-full.sh`70 行)
- `skills/gitlink-multi-repo-coordination/scripts/dashboard-gen.js` — 看板引擎
- `.devops/多仓库协同流水线.yml`(手动触发)
## 六、场景五:贡献者成长体系
### 6.1 架构图
```
contributor-growth-full.sh z2_cc gitlink-cli
├── Phase 1: 贡献活动追踪 (01-track-activity.sh)
│ ├── contributors-stat 代码统计
│ ├── commit 近期提交 (按 author 聚合)
│ ├── pr 已合并 (按 user 聚合)
│ └── issue 已关闭 (按 assignee 聚合)
├── Phase 2: 排行 + 段位 (02-rank-and-tier.sh)
│ ├── growth-analyze.js 计算成长分
│ │ 成长分 = commits×1 + mergedPR×5 + closedIssue×3 + (首次?+10)
│ ├── 排名排序
│ └── 段位划分: 🌱新芽(0-9) → 🌿新星(10-29) → 🌳中坚(30-79) → 🏆核心(80+)
└── Phase 3: 自动颁发徽章 (03-award-badges.sh)
├── 达段位 → 创建致谢 Issue
├── 颁发徽章评论
└── 新人发 good-first-issue 引导
```
### 6.2 成长分计算示例
| 贡献者 | commits | mergedPR | closedIssue | 首次 | 成长分 | 段位 |
|--------|---------|----------|-------------|------|--------|------|
| alice | 25 | 8 | 4 | 否 | 25+40+12=77 | 🌳 中坚 |
| bob | 6 | 2 | 1 | 否 | 6+10+3=19 | 🌿 新星 |
| carol | 3 | 1 | 0 | 是 | 3+5+0+10=18 | 🌿 新星 |
### 6.3 对应文件
- `skills/gitlink-contributor-growth/SKILL.md`
- `skills/gitlink-contributor-growth/scripts/contributor-growth-full.sh`56 行)
- `skills/gitlink-contributor-growth/scripts/growth-analyze.js` — 分析引擎
- `.devops/贡献者成长体系流水线.yml`(定时触发)
## 七、DevOps 流水线
### 7.1 已部署流水线
| 流水线 | 触发方式 | 功能 | 文件 |
|--------|----------|------|------|
| 构建流水线 | push | 拉取代码 → 编译 → 部署到 /usr/local/bin → 验证 | `.devops/构建流水线.yml` |
该流水线已在 GitLink DevOps 平台部署并成功运行push 代码时自动触发集成和部署。
### 7.2 流水线 YAML 配置(未部署)
以下 YAML 配置文件已提交到仓库,但尚未在建木平台部署:
| 流水线 | 触发方式 | 对应场景 | 文件 |
|--------|----------|----------|------|
| 项目初始化 | 手动 | 场景三 | `.devops/项目初始化流水线.yml` |
| 多仓库协同 | 手动 | 场景四 | `.devops/多仓库协同流水线.yml` |
| 贡献者成长 | 定时 | 场景五 | `.devops/贡献者成长体系流水线.yml` |
社区运营(场景一)和代码质量门禁(场景二)通过手动执行脚本运行。所有流水线配置 DRY_RUN 默认安全模式SSH 密钥用 `((work_together.ssh_key))` 密文引用。
— 文档完 —

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,361 @@
# GitLink Skills 丰富与完善 — 设计规格
- **日期**2026-06-15
- **分支**`feat/gitlink-skills-enrichment`
- **范围**:子任务二「编写和丰富 GitLink Skills」中标记为"完成"的 2 个技能
- **作者**AI Agentsuperpowers brainstorming → writing-plans 流程)
---
## 1. 背景与目标
`gitlink-cl`fork `z2_cc/gitlink-cli`upstream `Gitlink/gitlink-cli`)的 `skills/` 目录已有 23 个技能。本规格聚焦其中 **2 个** 目标技能,将其补齐到与 `gitlink-code-review` / `gitlink-insight` 同等的完整标准SKILL.md + REFERENCE.md + examples/),并满足任务交付要求:
> • 许可证合规检查:扫描仓库的许可证合规性和**敏感信息泄露风险**
> • 新人引导:为 good-first-issue **自动添加引导评论**,降低新贡献者参与门槛
### 目标
1. **`gitlink-compliance`** 补齐"敏感信息泄露风险"扫描能力(当前完全缺失),补 `examples/`,使报告与评分完整。
2. **`gitlink-newcomer-guide`** 修复命令正确性 Bug、补 `REFERENCE.md`、加入幂等去重与状态过滤,做成可重复运行的真实写操作技能。
3. 两个技能都能在 **Claude Code** 上验证通过(先静态,后真实)。
4. 同步更新 `skills/README.md` 概览表。
### 非目标YAGNI本轮不做
- 其余 4 个场景技能code-review / issue-triage / release-auto / project-health—— 本轮不动。
- 新增全新技能(如 contributor-insight / gatekeeper / milestone
- 重写已有技能的整体结构。
- 修改 `gitlink-cli` 本身的 Go 代码 / 增加新子命令(技能层用现有命令 + raw API
---
## 2. 现状评估
### 2.1 `gitlink-compliance`
| 文件 | 大小 | 现状 |
|------|------|------|
| `SKILL.md` | 8.4KB | 3 个工作流(完整合规 / 许可证兼容性 / 版权声明)+ 报告模板,**较完整** |
| `REFERENCE.md` | 5.7KB | 文件检查 API、许可证识别关键词、兼容性矩阵、检查清单**较完整** |
| `examples/` | — | **缺失** |
**关键缺口**:任务要求"敏感信息泄露风险",但当前 SKILL.md **完全没有**密钥/Token/凭据/私钥扫描章节。这是本轮最重要的新增。
**扫描方式短板**:当前全部依赖 `gitlink-cli api GET /:owner/:repo/raw/<branch>/<path>` 逐文件取内容。对"批量扫描全仓库敏感信息"不现实(仓库动辄数百上千文件,逐个 raw 请求不可行)。需要引入 `git clone` + `git grep` 批量扫描路径。
### 2.2 `gitlink-newcomer-guide`
| 文件 | 大小 | 现状 |
|------|------|------|
| `SKILL.md` | 4.2KB | 工作流 + 3 个评论模板 + 使用示例,**偏薄** |
| `examples/newcomer-guide-workflow.md` | 1.8KB | 4 步基础示例 |
| `REFERENCE.md` | — | **缺失** |
**关键缺口(含 1 个正确性 Bug**
1. 🔴 **Bug**`SKILL.md` 第 27、123 行引用 `gitlink-cli label +list`。实测 `gitlink-cli label --help``unknown command "label" for "gitlink-cli"`。**该命令不存在**,照抄会让技能直接报错。`gitlink-cli` 顶层命令只有:`api auth branch ci config issue org pr release repo search user version`。
2. ❌ 缺 `REFERENCE.md`(命令/字段/端点详细参考)。
3. ⚠️ 备注里说"添加引导评论前先检查是否已有引导评论(避免重复)",但**没给任何方法**——无幂等机制,重复运行会刷屏。
4. ⚠️ `--state open` 过滤**不准确**(官方克隆 `gitlink-onboarding` 已确认:返回列表可能含已关闭 Issue需按 `status_id` 客户端二次过滤。
### 2.3 可用的事实依据(来自探索,作为设计地基)
- `gitlink-cli issue +list` 只支持 `--state/--page/--limit`**无 `--label` 过滤**。返回 JSON 字段:`project_issues_index`(网页编号)、`subject`、`status_id`1=新增 / 2=正在解决 / 3=已解决 / 5=关闭 / 0=未知)、`tags[]`(每个含 `name`)、`assigners`、`priority`、`created_at`/`updated_at`。
- `gitlink-cli issue +comment -n <number> -b <body>``POST /v1/{owner}/{repo}/issues/{number}/journals`body 映射为 `notes`)。
- 列出 Issue 评论(用于去重):`gitlink-cli api GET /v1/:owner/:repo/issues/:number/journals --format json`(本仓 `skills/gitlink-issue/SKILL.md` 第 63 行已在用此端点)。
- good-first-issue 检测**不需要** `label` 命令——`issue +list` 的 `tags[].name` 字段已足够。
- `gitlink-cli api <METHOD> <PATH> [--query --body --header]`,认证自动注入,支持任意端点。
- 响应统一格式:`{ ok, data, meta:{page,limit,total_count} }` 或 `{ ok:false, error:{code,message,suggestion} }`
- 官方克隆 `skills/gitlink-license-compliance` 已有成熟的"敏感信息扫描"章节(正则特征库 + 风险分级 + git clone 批量扫描),作为权威蓝本参考。
- 官方克隆 `skills/gitlink-onboarding` 给出了 Issue JSON 字段与 `status_id` 过滤的精确说明,作为 newcomer-guide 的参考。
---
## 3. 设计决策
### 决策 A — compliance 敏感信息扫描方式:**混合(方案③)**
- **仓库元信息 / LICENSE / 依赖声明文件 / 指定小文件** → 用 `gitlink-cli api`(小而准,无需 clone远程可用
- **批量敏感信息扫描(遍历全仓库文件 + Git 历史)** → 用 `git clone` + `git ls-tree -r --name-only HEAD` + `git grep -nE '<pattern>'` + `git log -p`(现实可行,能扫全)。
**理由**:敏感信息扫描本质是"对大量文件做正则匹配",逐文件 `api raw` 不可行;`git grep` 是为此而生的工具,单次调用扫描整个工作树,效率与覆盖率都最佳。元信息类小数据继续用 `api`,避免无谓 clone。
**被否方案**
- ① 纯 `api raw`:扫不动真实仓库,否。
- ② 纯 `git clone`:元信息(如 `repo +info`)用 clone 反而绕远,否。
### 决策 B — newcomer-guide 去重策略:**标记串 + journal 扫描(方案①)**
- 每条引导评论末尾埋固定 HTML 注释标记:`<!-- gitlink-newcomer-guide:v1 -->`(在网页上不可见,但 API 能读到)。
- 发评论前:`gitlink-cli api GET /v1/:owner/:repo/issues/:number/journals --format json`,扫描已有 journal 的 `notes` 字段是否含该标记。
- 命中标记 → 跳过该 Issue幂等未命中 → 发评论。
**理由**:标记串让"是否已是本技能发的引导评论"判断精确、版本可演进换标记串即可重发新版引导。journal 端点已确认存在。
**被否方案**:仅比较 `comment_journals_count` 前后差值——无法区分"已有引导评论"与"有其他评论",否。
---
## 4. 详细设计 — `gitlink-compliance`
### 4.1 新增「工作流 4敏感信息扫描」
插入到 `SKILL.md` 现有"工作流 3版权声明批量检查"之后、"Raw API 参考"之前。
#### 4.1.1 高危文件类型清单(优先扫描)
```
配置文件: .env, .env.local, .env.production, .env.development
config.yaml, config.yml, config.json, application.properties
settings.py, settings.json, appsettings.json
证书/密钥: *.pem, *.key, *.p12, *.pfx, *.crt, *.cer, *.der
SSH 密钥: id_rsa, id_dsa, id_ecdsa, id_ed25519
数据库配置: database.yml, db.conf, datasource.properties, *.conn
CI/部署配置:.travis.yml, .gitlink-ci.yml, .trustie-pipeline.yml,
.github/workflows/*.yml, docker-compose.yml, Dockerfile
```
#### 4.1.2 敏感信息正则特征目录
```
AWS Access Key AKIA[0-9A-Z]{16}
GitHub Token ghp_[A-Za-z0-9]{36}
GitLink Token glpat-[A-Za-z0-9\-_]{20}
JWT eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}
私钥头 -----BEGIN (RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----
通用密钥赋值 (?i)(password|passwd|pwd|secret|token|apikey|api_key|access_key|private_key)\s*[:=]\s*['"]?[^\s'"]{8,}
数据库连接串 (mysql|postgres|postgresql|mongodb|redis)://[^:\s]+:[^@\s]+@[^\s]+
内网/私有 IP (192\.168\.|10\.\d{1,3}\.|172\.(1[6-9]|2\d|3[01])\.|127\.0\.0\.1)
Slack Token xox[baprs]-[A-Za-z0-9-]{10,}
```
#### 4.1.3 四级风险分级
| 风险等级 | 描述 | 处理建议 |
|---------|------|---------|
| 🔴 严重 | 真实密钥/Token/私钥暴露在代码中 | 立即撤销密钥;从 Git 历史清除 |
| 🟠 高 | 密码 / 数据库连接串硬编码 | 替换为环境变量;清理历史提交 |
| 🟡 中 | 内网地址 / 测试账号泄露 | 评估影响范围,按需处理 |
| 🟢 低 | 疑似敏感但可能是示例/占位数据 | 人工确认后决定是否处理 |
#### 4.1.4 混合扫描执行步骤(写进工作流)
```bash
# Step 1仓库元信息api无需 clone
gitlink-cli repo +info --owner <owner> --repo <repo> --format json
# Step 2LICENSE / 依赖声明文件api文件少且明确
gitlink-cli api GET /:owner/:repo/raw/master/LICENSE
gitlink-cli api GET /:owner/:repo/raw/master/go.mod # 按主语言选择
gitlink-cli api GET /:owner/:repo/raw/master/package.json
# Step 3批量敏感信息扫描需 clone
git clone https://www.gitlink.org.cn/<owner>/<repo>.git /tmp/<repo>-scan
cd /tmp/<repo>-scan
git ls-tree -r --name-only HEAD # 确定扫描范围
# Step 4对高危文件类型 + 全工作树做正则扫描
git grep -nE 'AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|glpat-[A-Za-z0-9\-_]{20}|-----BEGIN .*PRIVATE KEY-----' HEAD
git grep -niE '(password|passwd|pwd|secret|token|apikey|api_key)\s*[:=]' HEAD -- '*.env*' '*.yml' '*.yaml' '*.json' '*.py' '*.conf'
git grep -nE '(mysql|postgres|mongodb|redis)://[^:\s]+:[^@\s]+@' HEAD
# Step 5可选检查 Git 历史中已删除但仍残留的敏感信息
git log --all -p -S 'AKIA' -- '*.py' # 按可疑特征搜历史
```
> **降级**:若用户无本地 clone 条件、仓库极小,可仅用 Step 1-2 + 对少量高危文件逐个 `api raw` 扫描,并在报告中注明"未做全量扫描"。
#### 4.1.5 输出整合
把"敏感信息扫描结果"作为独立一节并入现有合规报告模板(`SKILL.md` 的"输出格式"小节与 `REFERENCE.md` 的"输出格式规范"都要改):
```markdown
### 🔴 敏感信息扫描
| 风险 | 文件 | 行 | 内容特征 | 建议 |
|------|------|----|---------|------|
| 🟠 高 | config/database.yml | 12 | password: prod_db_pass_123 | 改用环境变量 |
```
评分维度新增「🔒 敏感信息管控」一行(☆☆☆☆☆ / ✅⚠️❌),总分计算纳入。
### 4.2 新增 `examples/compliance-check-workflow.md`
端到端可运行示例,结构:
1. 场景说明(发布前合规自检,目标仓库 `z2_cc/gitlink-cli`
2. 前置条件(已登录、有读权限;批量扫描需可 clone
3. Step 1-6repo 信息 → LICENSE 识别 → 依赖合规 → 敏感信息扫描 → 版权头采样 → 汇总报告
4. 一份**示例报告输出**(含发现的不兼容依赖与一个假密钥命中)
5. 命令速览
> 全程只读 + 可 dry-run敏感信息扫描的 `git clone`/`git grep` 本身不写远端)。示例中用到的"命中密钥"用明显的假值(如 `AKIAIOSFODNN7EXAMPLE`),避免示例本身触发误报。
### 4.3 `REFERENCE.md` 增补
- 新增「敏感信息扫描 API 与命令」小节:高危文件类型清单、正则特征目录、风险分级表、`git grep` / `git log -S` 用法。
- 「合规检查清单」表格补一行「敏感信息 | `git grep` 批量扫描 | 无 🔴/🟠 级命中」。
- 「输出格式规范」补「敏感信息扫描结果」模板片段。
### 4.4 `SKILL.md` 其余微调
- 顶部「工作流概览」表新增一行「敏感信息 | 密钥/Token/凭据/私钥泄露 | 🔴 / 🟠」。
- `metadata.requires.bins``["gitlink-cli"]` 改为 `["gitlink-cli", "git"]`(批量扫描依赖 git并在文中注明 git 为"批量扫描时必需,基础检查可用 api 替代")。
- 「注意事项」补一条:扫描结果仅供参考,真实密钥需人工复核,勿把误报当噪音忽略。
---
## 5. 详细设计 — `gitlink-newcomer-guide`
### 5.1 修复 `label` 命令 Bug
删除所有 `gitlink-cli label +list` 引用,替换为:
- **good-first-issue 检测**:不依赖 label 命令,直接用 `issue +list --format json` 返回的 `tags[].name` 字段筛选(见 5.2)。
- **(可选)查看仓库可用标签目录**`gitlink-cli api GET /v1/:owner/:repo/labels --format json`raw API端点在静态验证阶段确认若 404 则在 REFERENCE 标注"GitLink 无独立 label 列表端点,依赖 issue.tags")。
### 5.2 good-first-issue 检测逻辑(写进 SKILL.md 工作流)
```
1. issue +list --state open --format json必要时翻页 --page 2..,按 meta.total_count
2. 客户端按 status_id 过滤:保留 1新增、2正在解决排除 3已解决、5关闭
—— 抵消 --state open 过滤不准确的已知问题
3. 按 tags[].name 匹配入门标签(大小写不敏感,正则):
/good.?first.?issue|新手|入门|help.?wanted|easy|beginner|低难度/
4. 排除已分配assigners 非空)的 Issue除非标签明确是 help wanted
5. 对每个候选 issue +view --number <index> --format json取 description / comment_journals_count
```
标签名变体在 REFERENCE 列全(`good first issue`、`good-first-issue`、`good_first_issue`、`新手任务`、`入门`、`help wanted`、`help-wanted`、`easy`、`beginner`)。
### 5.3 去重机制(决策 B
- 引导评论模板**末尾统一追加**标记:`<!-- gitlink-newcomer-guide:v1 -->`3 个模板都加)。
- 发评论前执行幂等检查:
```bash
gitlink-cli api GET /v1/:owner/:repo/issues/<number>/journals --format json
# 扫描返回 data[].notes 是否含 "gitlink-newcomer-guide:v1"
# 命中 → 跳过(输出"已引导过,跳过 #<number>"
# 未命中 → 执行 issue +comment
```
- 工作流把"去重检查"作为**发评论前的强制步骤**写进流程图与注意事项。
### 5.4 新建 `REFERENCE.md`
内容:
- 依赖命令表(`issue +list/view/comment`、`repo +info`、`api GET .../journals`),每条带 flag 与 API 映射。
- Issue JSON 关键字段表(`project_issues_index` / `status_id` 含义 / `tags[].name` / `assigners` / `comment_journals_count`)。
- 入门标签名变体表 + 匹配正则。
- `status_id` → 状态对照表1/2/3/5/0
- 幂等规则标记串格式、journal 扫描命令、版本演进说明。
- 已知坑:`--state open` 不准 → 客户端按 `status_id` 二次过滤;分页 >20 需翻页。
### 5.5 增强 `examples/newcomer-guide-workflow.md`
在现有 4 步基础上扩为:
1. 列 issue含翻页 + status_id 过滤说明)
2. 按 tags 筛 good-first-issue 候选
3. **去重检查**journal 扫描标记串)—— 新增步骤
4. 选模板bug / 功能 / 文档)+ 追加标记串
5. 发评论(写操作,先确认)
6. 批量场景:对多个候选循环执行 3-5输出"已引导 N 个 / 跳过 M 个"
### 5.6 `SKILL.md` 其余微调
- 「依赖的 Shortcuts」表删除 `label +list` 行,改为 `api GET .../journals`(去重)与 `issue +list/view/comment`
- 工作流程图加入"去重检查"节点。
- 「注意事项」补:写操作前确认用户意图;重复运行不会刷屏(幂等);不要改 good-first-issue 标签。
- 顶部加 `**CRITICAL — 所有写操作issue +comment执行前必须确认用户意图**`(与 issue 技能一致)。
---
## 6. 横切:`skills/README.md` 更新
当前 README 概览表(核心/辅助 Skills 两张表)**未收录** `gitlink-compliance``gitlink-newcomer-guide`。补两行:
| Skill | 说明 | 常用命令 |
|-------|------|----------|
| **gitlink-compliance** | 许可证 / 依赖合规 / 敏感信息扫描 | `repo +info`, `api GET .../raw`, `git grep` |
| **gitlink-newcomer-guide** | 为 good-first-issue 自动添加引导评论 | `issue +list/view/comment`, `api GET .../journals` |
(放在"辅助 Skills"表,或在"核心"表后新增"合规与社区"小节——实现时择一,倾向新增小节以体现场景价值。)
---
## 7. 验证计划(先静态,后真实)
### 7.1 静态验证(本轮立即做,无需凭据)
针对**每个**技能文件:
1. **Frontmatter 合法**`name` / `version` / `description` / `metadata.requires` 齐全且 YAML 可解析。
2. **命令存在性**:技能中每条 `gitlink-cli <cmd> [args]``<cmd>` 实测存在(逐一 `--help` 校验)。**重点回归**`gitlink-newcomer-guide` 中不再出现 `label``gitlink-compliance` 新增的 `git` 命令在 PATH 中可用。
3. **flag 合法性**example / SKILL 里的 flag`-n/-b/--number/--body/--format/--state/--page/--limit`)与各子命令 `--help` 一致。
4. **只读命令实跑**:用真实仓库 `z2_cc/gitlink-cli` 跑通只读链路(`repo +info`、`issue +list`、`api GET .../raw`、`api GET .../journals`),确认 JSON 可解析、字段名与文档一致。
5. **写操作 dry-run / 展示**`issue +comment` 用构造好的 body 仅展示命令、不实际发送(无凭据阶段);敏感信息扫描的 `git clone` + `git grep` 在本地对 `gitlink-cl` 自身实跑,确认正则能命中示例假密钥。
6. **链接与交叉引用**SKILL.md ↔ REFERENCE.md ↔ examples 的相对链接可达。
### 7.2 真实验证(用户给凭据 + 测试仓库后做)
7. **compliance**:在测试仓库植入假密钥(如 `AKIAIOSFODNN7EXAMPLE`、`ghp_`+36 位、`password: real_secret_xxx`),实跑完整扫描,确认 🔴/🟠 级命中并生成报告;再清掉假密钥复跑确认无命中。
8. **newcomer-guide**:在测试仓库开一个带 `good first issue` 标签的开放 Issue实发一条引导评论确认标记串写入**立即复跑**技能,确认第二次识别到标记串、跳过、不重复发。再开一个不带入门标签的 Issue确认被正确排除。
### 7.3 Claude Code 平台验证
- 两个 SKILL.md 的 `description` 能被 Claude Code 正确识别为可触发技能(语义清晰、含触发词)。
- 在 Claude Code 中模拟一次"帮我检查这个仓库的合规性 / 给 good-first-issue 加引导"的请求,确认技能被加载、流程可走通(静态部分)。
---
## 8. 边界与错误处理
| 场景 | 处理 |
|------|------|
| 仓库无 LICENSE | compliance 报 🔴 必须修复,给推荐许可证(按语言/社区惯例) |
| 依赖许可证无法确定 | 标"需人工确认",不计入不兼容数 |
| 无本地 clone 条件 | compliance 降级为 api + 高危文件逐个扫,报告注明"未全量扫描" |
| `git grep` 命中示例/测试数据 | 标 🟢 低风险,建议加注释说明是示例 |
| 仓库无任何入门标签 | newcomer-guide 输出"未发现 good-first-issue建议维护者先标记",列出未分配的开放 Issue 供参考 |
| Issue 已被认领assigners 非空) | 跳过,除非标签是 help wanted |
| journal GET 端点 404 / 字段不符 | 静态/真实验证阶段确认;若端点不可用,降级为"仅比较 comment_journals_count 是否为 0"并在 REFERENCE 注明 |
| 写操作issue +comment | 一律先确认用户意图;批量场景逐条或汇总确认 |
---
## 9. 文件清单(创建 / 修改)
### 创建3 个)
- `skills/gitlink-compliance/examples/compliance-check-workflow.md`
- `skills/gitlink-newcomer-guide/REFERENCE.md`
- spec 本身,已建)`docs/superpowers/specs/2026-06-15-gitlink-skills-enrichment-design.md`
### 修改5 个)
- `skills/gitlink-compliance/SKILL.md`+工作流 4 敏感信息扫描、+报告整合、+requires.git、概览表
- `skills/gitlink-compliance/REFERENCE.md`+敏感信息章节、+检查清单行、+输出片段)
- `skills/gitlink-newcomer-guide/SKILL.md`(修 label Bug、+status_id 过滤、+去重、+标记串、工作流图)
- `skills/gitlink-newcomer-guide/examples/newcomer-guide-workflow.md`+去重步骤、+批量场景)
- `skills/README.md`(概览表补 2 行 / 新增小节)
---
## 10. 未决项(实现阶段确认)→ 真实验证结果2026-06-16
1. **label 列表端点** `GET /v1/:owner/:repo/labels` —— **实测不可用**(返回 GitLink 首页 HTML非 JSON。已在 REFERENCE 标注"无独立端点,标签信息只来自 `issue +list``tags[]``issue +create --label <id>` 的 ID 只能从网页后台获取"。good-first-issue 检测不依赖它。✅ 已闭环。
2. **journal GET 返回结构** —— **实测**:响应为 `data.journals[]`(非 `data[]`);评论 journal 含 `notes`(正文),操作 journal状态/描述变更)含 `operate_content`、无 `notes`。已在 REFERENCE 修正去重逻辑为"遍历 `data.journals[]`,仅扫描评论 journal 的 `notes`"。✅ 已闭环。
**真实验证额外发现(已回填文档):**
3. **`issue +list` 确实返回 `tags[]` 字段**(未打标签的仓库为空数组,但字段存在)→ good-first-issue 检测机制成立。✅
4. **Windows Git BashMSYS路径坑**`gitlink-cli api GET /v1/...` 的参数会被 MSYS 转为 Windows 路径(`/v1/...`→`D:/Git/v1/...`),请求落到首页返回 HTML`MSYS_NO_PATHCONV=1` 或改用 PowerShell/cmd。已在两个技能的 REFERENCE 已知坑中标注。⚠️(这是 gitlink-cli 在 Windows/MSYS 下的通用问题,建议作为独立 issue 反馈给上游。)
**未执行的端到端写验证**(需专用测试仓库):在真实仓库植入假密钥实跑扫描、发真实引导评论+复跑去重——底层机制(正则经本地 fixture 验证、journals 端点经实测可达)已验证,但完整写流程未在真实仓库跑通。
---
## 11. 后续
本规格经用户审查通过后,调用 `writing-plans` 技能产出分步实现计划(按"compliance → newcomer-guide → README → 静态验证"顺序,每步可独立验收),再进入实现。

View File

@ -1,6 +0,0 @@
{
"dependencies": {
"docx": "^9.7.1",
"pptxgenjs": "^4.0.1"
}
}

View File

@ -1,59 +0,0 @@
#!/bin/bash
# ================================================================
# gitlink-cli 本地编译安装脚本
# 功能:编译本地源码并替换 PATH 中的旧版本
# 使用bash scripts/setup-local-cli.sh
# ================================================================
set -e
echo "============================================"
echo " gitlink-cli 本地编译安装"
echo "============================================"
cd "$(dirname "$0")/.."
# 1. 检查 Go 环境
if ! command -v go &> /dev/null; then
echo "[ERROR] 未找到 Go请先安装 Go 1.21+"
exit 1
fi
echo "[INFO] Go 版本: $(go version)"
# 2. 编译
echo "[INFO] 编译 gitlink-cli..."
go build -o gitlink-cli.exe . 2>&1
echo "[INFO] 编译完成: $(ls -lh gitlink-cli.exe | awk '{print $5}')"
# 3. 验证编译版本
echo "[INFO] 验证命令完整性..."
if ./gitlink-cli.exe commit --help > /dev/null 2>&1; then
echo "[INFO] ✅ commit +list 可用"
else
echo "[WARN] commit 命令不可用,请检查代码"
fi
if ./gitlink-cli.exe collaborator --help > /dev/null 2>&1; then
echo "[INFO] ✅ collaborator +list 可用"
else
echo "[WARN] collaborator 命令不可用"
fi
# 4. 提供 PATH 设置说明
echo ""
echo "============================================"
echo " 安装完成"
echo "============================================"
echo ""
echo "本地编译版本: $(pwd)/gitlink-cli.exe"
echo ""
echo "方式一:设置别名(推荐,仅当前终端有效)"
echo " alias gitlink-cli='$(pwd)/gitlink-cli.exe'"
echo ""
echo "方式二:添加到 PATH永久有效需管理员权限"
echo " export PATH=\"$(pwd):\$PATH\""
echo " 或将上面这行添加到 ~/.bashrc 或 ~/.bash_profile"
echo ""
echo "方式三:直接使用 detect-cli.sh已在子任务三/四脚本中集成)"
echo " source skills/gitlink-shared/scripts/detect-cli.sh"
echo ""
echo "验证:"
echo " gitlink-cli commit +list --owner z2_cc --repo gitlink-cli --limit 3 --format json"

View File

@ -69,7 +69,7 @@ and --page and --limit for pagination.`,
if u := ctx.Arg("until"); u != "" {
q.Set("until", u)
}
env, err := ctx.CallAPIWithQuery("GET", fmt.Sprintf("/v1%s/actions/runs", ctx.RepoPath()), q)
env, err := ctx.CallAPIWithQuery("GET", ctx.RepoPath()+"/builds", q)
if err != nil {
return err
}
@ -365,7 +365,6 @@ Prompts for confirmation before stopping the build.`,
Flags: []common.Flag{
{Name: "page", Short: "p", Usage: "Page number", Default: "1"},
{Name: "limit", Short: "l", Usage: "Items per page", Default: "20"},
{Name: "name", Short: "n", Usage: "Pipeline name (optional)"},
},
Run: func(ctx *common.RuntimeContext) error {
if err := ctx.ResolveOwnerRepo(); err != nil {
@ -374,9 +373,6 @@ Prompts for confirmation before stopping the build.`,
q := url.Values{}
q.Set("page", ctx.Arg("page"))
q.Set("limit", ctx.Arg("limit"))
if n := ctx.Arg("name"); n != "" {
q.Set("name", n)
}
env, err := ctx.CallAPIWithQuery("GET", fmt.Sprintf("/v1%s/pipelines/run_results", ctx.RepoPath()), q)
if err != nil {
return err

View File

@ -108,29 +108,6 @@ skills/
│ └── ci-workflow.md # CI 工作流
├── gitlink-pm/ # 项目管理
│ └── SKILL.md # PM 操作指南
├── gitlink-duplicate-detector/ # 重复 Issue 检测
│ ├── SKILL.md # 重复检测与关联收敛指南
│ └── examples/
│ └── duplicate-detection-workflow.md # 端到端工作流与验证记录
├── gitlink-pr-deep-review/ # PR 深度审查
│ ├── SKILL.md # 编排 code-review + 设计/一致性推理
│ └── examples/
│ └── pr-deep-review-workflow.md # 端到端工作流与验证记录
├── gitlink-project-bootstrap/ # 项目一键初始化(子任务五)
│ ├── SKILL.md # 创建仓库 → README/LICENSE/CI → 初始 Issue/里程碑
│ ├── examples/
│ │ └── bootstrap-workflow.md # 端到端工作流与验证记录
│ └── scripts/ # 三阶段 + 全流程串联 + 骨架生成引擎
├── gitlink-multi-repo-coordination/ # 多仓库协同(子任务五)
│ ├── SKILL.md # 跨仓库 Issue 追踪 / PR 看板 / Release 协调
│ ├── examples/
│ │ └── multi-repo-workflow.md # 端到端工作流与验证记录
│ └── scripts/ # 三阶段 + 全流程串联 + 看板聚合引擎
├── gitlink-contributor-growth/ # 贡献者成长体系(子任务五)
│ ├── SKILL.md # 贡献追踪 → 排行/段位 → 自动颁发徽章
│ ├── examples/
│ │ └── contributor-growth-workflow.md # 端到端工作流与验证记录
│ └── scripts/ # 三阶段 + 全流程串联 + 成长分析引擎
└── gitlink-workflow/ # AI 自动化工作流
└── SKILL.md # 工作流模板Issue 分类、PR Review、Release Notes
```
@ -161,17 +138,12 @@ skills/
| **gitlink-pm** | 项目管理 | 通过 Raw API 访问 |
| **gitlink-workflow** | AI 工作流 | Issue 分类、PR Review、Release Notes |
### 端到端自动化流水线 Skills子任务三 / 五)
### 合规与社区 Skills
多阶段串联、可直接复现的完整解决方案,每个 Skill 都配有 `scripts/*-full.sh` 全流程脚本与 `.devops/*流水线.yml` GitLink DevOps 流水线,默认 `DRY_RUN=true`
| Skill | 场景 | 全流程脚本 |
|-------|------|-----------|
| **gitlink-community-ops** | 社区运营Issue 分拣 → 周报 → Release Notes | `community-ops-full.sh` |
| **gitlink-quality-gate** | 代码质量看门人PR 审查 → CI → 门禁决策 → 合并 | `quality-gate-full.sh` |
| **gitlink-project-bootstrap** | 项目一键初始化:创建仓库 → README/LICENSE/CI → 初始 Issue/里程碑 | `project-bootstrap-full.sh` |
| **gitlink-multi-repo-coordination** | 多仓库协同:跨仓库 Issue 追踪 / PR 看板 / Release 协调(`REPOS` 环境变量) | `multi-repo-full.sh` |
| **gitlink-contributor-growth** | 贡献者成长:活动追踪 → 排行/段位 → 自动颁发徽章 | `contributor-growth-full.sh` |
| Skill | 说明 | 常用命令 |
|-------|------|----------|
| **gitlink-compliance** | 许可证 / 依赖合规 / 敏感信息扫描 | `repo +info`、`api GET .../raw`、`git grep` |
| **gitlink-newcomer-guide** | 为 good-first-issue 自动添加引导评论 | `issue +list/view/comment`、`api GET .../journals` |
---
@ -336,11 +308,6 @@ AI 代理可以:
- ✅ 自动分类 Issue
- ✅ 自动生成 Release Notes
- ✅ 自动执行代码审查
- ✅ 自动检测并收敛重复 Issue[gitlink-duplicate-detector](gitlink-duplicate-detector/SKILL.md)
- ✅ PR 深度审查:实现质量 + 设计/需求一致性 + 跨模块影响([gitlink-pr-deep-review](gitlink-pr-deep-review/SKILL.md)
- ✅ 项目一键初始化:输入描述即可创建仓库 + README/LICENSE/CI + 初始 Issue/里程碑([gitlink-project-bootstrap](gitlink-project-bootstrap/SKILL.md)
- ✅ 多仓库协同:跨仓库统一 Issue 追踪 / PR 状态看板 / Release 协调发布([gitlink-multi-repo-coordination](gitlink-multi-repo-coordination/SKILL.md)
- ✅ 贡献者成长体系:追踪活动 → 生成排行/段位 → 自动颁发徽章([gitlink-contributor-growth](gitlink-contributor-growth/SKILL.md)
---

View File

@ -50,34 +50,23 @@ gitlink-cli pr +files --id <pull_request_id> --format json
| `files[].isDeleted` | boolean | 是否删除文件 |
| `files[].isRenamed` | boolean | 是否重命名 |
### 获取 PR Diff`pr +version-diff`,替代已移除的 `pr +diff`
`pr +diff` 已移除(与 `file` 冗余)。先取补丁集版本,再看版本差异:
### 获取 PR Diff
```bash
# 1) 取 patchset version_id
gitlink-cli pr +versions --id <pull_request_id> --format json
# 2) 看该版本的逐行 diff
gitlink-cli pr +version-diff --id <pull_request_id> --version-id <vid> [--file <path>] --format json
gitlink-cli pr +diff --id <pull_request_id> --format json
```
**`pr +versions` 返回字段:**
**返回字段说明:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `data.versions[].id` | int | **patchset 版本 IDversion-diff 用这个)** |
**`pr +version-diff` 返回字段:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `data.file_nums` | int | 文件总数 |
| `data.files[].name` | string | 文件名 |
| `data.files[].addition` / `deletion` | int | 该文件增/删行数 |
| `data.files[].sections[].lines[].content` | string | 行内容(含 `@@ ...` hunk 头) |
| `data.files[].sections[].lines[].type` | int | **2=新增, 3=删除, 4=hunk 头(`@@`);据此筛出变更行** |
> ⚠️ `--file <path>` 过滤不稳定,建议整份取后客户端按 `files[].name` 筛。需读文件全文用 `file +get --ref <head分支> --path <文件>`
| `files_count` | int | 文件总数 |
| `total_addition` | int | 总新增行数 |
| `total_deletion` | int | 总删除行数 |
| `files[].sections[].lines[].leftIdx` | int | 原文件行号 |
| `files[].sections[].lines[].rightIdx` | int | 新文件行号 |
| `files[].sections[].lines[].type` | int | 1=未变, 2=新增, 3=删除, 4=统计信息 |
| `files[].sections[].lines[].content` | string | 行内容 |
---
@ -111,53 +100,6 @@ gitlink-cli pr +list --state <open|merged|closed> --format json
---
## 评审与评论命令(代码审查写入)
### `pr +review` — 提交评审(首选)
```bash
gitlink-cli pr +review --id <pr_id> --status <common|approved|rejected> --content "<报告>" [--commit <sha>] [--dry-run] --format json
```
| 参数 | 说明 |
|------|------|
| `-i, --id` | PR 编号 |
| `-s, --status` | **评审状态:`common`(普通评论)/ `approved`(批准)/ `rejected`(拒绝,即 Request changes**,默认 `common` |
| `-c, --content` | 评审内容Markdown放整体审查报告 |
| `-m, --commit` | 可选,挂到具体 commit SHA |
| `--dry-run` | **预览不提交(审查必用)** |
> 状态映射:报告含 Critical → `rejected`;仅 Warning/Suggestion → `common`;无问题 → `approved`。**不要用 GitHub 风格的 `event:"COMMENT"`**GitLink 用 `--status`
### `pr +create-comment` — 行内评审评论
```bash
gitlink-cli pr +create-comment --id <pr_id> --path <文件路径> --line <行号> --body "<意见>" --format json
```
| 参数 | 说明 |
|------|------|
| `-i, --id` | PR 编号 |
| `-p, --path` | 文件路径 |
| `-l, --line` | **文件中的行号**(非 diff 补丁位置;注意 import/头注释偏移) |
| `-b, --body` | 评论内容 |
> 行号不确定时**不要发**——并入 `pr +review --content` 总报告,或改用 `pr +comment`
### `pr +comment` — 普通评论(不绑行)
```bash
gitlink-cli pr +comment --id <pr_id> --body "<评论>" --format json
```
> 以 journal 形式挂在 PR 下,不绑定文件行。是行内评论失败时的安全 fallback。
### `pr +reviews` — 列出已有评审(复审时用)
```bash
gitlink-cli pr +reviews --id <pr_id> [--status <common|approved|rejected>] --format json
```
## Issue 相关 API
### 获取 Issue 列表

View File

@ -1,7 +1,7 @@
---
name: gitlink-code-review
version: 1.2.0
description: "当用户需要对 GitLink 上的 Pull Request 做代码审查时触发:获取 PR 变更/Diff、按严重程度输出结构化 Review 意见、并(经确认后)把评审评论提交到 PR。适用于收到 PR Review 请求、需要批量审查 PR、为 PR 自动生成审查报告等场景。"
version: 1.0.0
description: "智能代码审查:获取 PR 变更、分析代码质量、自动生成 Review 评论与摘要报告。当用户需要审查 Pull Request、检查代码质量或生成审查报告时触发。"
metadata:
requires:
bins: ["gitlink-cli"]
@ -11,201 +11,311 @@ metadata:
# gitlink-code-review智能代码审查
**CRITICAL — 开始前必须先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md),其中包含认证、权限处理和 API 注意事项。**
**CRITICAL — 所有写入/删除操作前,务必先确认用户意图;提交 Review 会通知 PR 相关人必须先出报告→用户确认→dry-run→再提交。**
**CRITICAL — 所有写入/删除操作前,务必先确认用户意图。**
**CRITICAL — GitLink 操作只能用 `gitlink-cli`。禁止用 `gh`GitHub CLI操作 GitLink 资源。`gh` 仅适用于 GitHub 平台。**
## 核心原则
1. **用 Shortcut不用 Raw API**:提交评审用 `pr +review`,行内评论用 `pr +create-comment`,普通评论用 `pr +comment`。不要用 GitHub 风格的 Raw API`event:"COMMENT"` / `position` 等字段 GitLink 不支持)。
2. **建议优先,确认后提交**:先把结构化审查报告交给用户确认,**禁止未经确认直接提交 Review/评论**。尤其禁止用 `--yes` 绕过确认,除非用户明确说「直接提交/不用确认」。
3. **严重程度分级驱动结论**:有 Critical → 评审状态用 `rejected`Request changes仅 Suggestion/Positive → `common`;无问题 → `approved`
4. **安全红线零容忍**硬编码密钥、SQL/命令注入、XSS、路径遍历、不安全反序列化必须标 Critical。
> **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解认证和全局参数。
## 工作流概览
| 阶段 | 操作 | 命令 |
|------|------|------|
| ① 获取上下文 | PR 详情 / 变更文件 / Diff | `pr +view` / `pr +files` / `pr +diff` |
| ② 逐文件分析 | 按语言检查项审查 | AI 分析) |
| ③ 出审查报告 | 按严重程度分级,**等用户确认** | (无写入) |
| ④ dry-run 预览 | 用户确认后,预览评审 | `pr +review --dry-run` |
| ⑤ 提交评审 | 用户再次确认后提交 | `pr +review`(去 `--dry-run` |
| ⑥ 行内评论(可选) | 针对具体行追加 | `pr +create-comment --path --line` |
本 Skill 提供一套完整的 AI 驱动代码审查工作流,覆盖从获取 PR 变更到生成审查报告的全过程。不需要额外的 CLI Shortcuts——现有 `gitlink-cli` 命令 + AI Agent 的分析能力即可完成。
| 阶段 | 操作 | AI Agent 角色 |
|------|------|--------------|
| ① 获取上下文 | 拉取 PR 详情、变更文件、Diff | 执行 CLI 命令采集数据 |
| ② 分析代码 | 检查每个文件的变更 | 逐文件审查,标记问题 |
| ③ 结构化反馈 | 按严重程度分级输出审查意见 | 生成分级 Review 评论 |
| ④ 提交评论 | 发表 Review 到 PR | 通过 API 提交 |
| ⑤ 生成报告 | 输出审查摘要 | 生成 Markdown 摘要 |
---
## 详细工作流
### Step 1获取 PR 上下文
### 工作流 1PR 代码审查
**场景**:收到 PR Review 请求后,进行完整代码审查。
#### Step 1获取 PR 上下文
```bash
# PR 详情
# 获取 PR 详情
gitlink-cli pr +view --id <pr_id> --format json
# 变更文件列表(含增删行数、是否新建)
# 获取变更文件列表
gitlink-cli pr +files --id <pr_id> --format json
# Diff 内容先取补丁集版本再看版本差异pr +diff 已移除)
gitlink-cli pr +versions --id <pr_id> --format json # 拿 version_id
gitlink-cli pr +version-diff --id <pr_id> --version-id <vid> --format json # 逐行 diff
# 获取 Diff 内容(含变更行号和代码上下文)
gitlink-cli pr +diff --id <pr_id> --format json
```
> `--id` 是 PR 编号web URL 中的编号。Diff 在 `files[].sections[].lines[]``type`2=新增、3=删除、4=hunk 头(`@@ ...`);按文件分组逐文件分析,大型 PR 分段处理。
>
> ⚠️ **实测2026-06-21**`pr +diff` 已被移除(与 `file` 冗余),由 `pr +version-diff` 替代。`--file <path>` 过滤不稳定,建议整份取 diff 后客户端按文件名筛。需要读某文件全文时用 `file +get --ref <head分支> --path <文件>`
#### Step 2逐文件分析
### Step 2逐文件分析
对每个变更文件,根据文件类型执行针对性检查:
对每个变更文件,按语言执行针对性检查:
**Python 文件检查项:**
- 语法与导入:未使用的 import、循环导入、wildcard import
- 代码规范PEP 8 风格偏离、过长行(>88 chars、命名规范
- 安全硬编码密钥、SQL 注入风险、`eval()`/`exec()` 使用
- 性能不必要的循环、缺少缓存、N+1 查询
- 错误处理:裸 `except`、吞异常、缺少 finally
**Python**:未用/循环 importPEP8 偏离与过长行硬编码密钥、SQL 注入、`eval()`/`exec()`;裸 `except`、吞异常N+1 查询。
**JS/TS**`innerHTML` 直赋、`eval()``any` 滥用;未处理 Promise废弃 API。
**Go**:未检查的 error return、panic 滥用goroutine 泄漏、缺 sync未关闭 file/conn导出标识符缺注释。
**通用**:硬编码配置/密钥/URL边界条件缺失圈复杂度过高魔法数字DRY 违反;注释过时;测试覆盖不足。
**JavaScript/TypeScript 文件检查项:**
- 安全:`innerHTML` 直接赋值、`eval()` 使用
- 类型安全:`any` 滥用、缺失类型定义
- 性能:不必要的 re-render、大对象深拷贝
- 异步:未处理的 Promise、缺少 error boundary
- 依赖:已废弃 API 使用
### Step 3出审查报告建议不写入
**Go 文件检查项:**
- 错误处理:未检查的 error return、panic 滥用
- 并发goroutine 泄漏、缺少 sync 保护
- 资源管理:未关闭的 file/conn、defer 使用
- 命名:导出标识符缺少注释、变量 shadowing
按严重程度分级输出,**此阶段不执行任何写入**
**通用检查项:**
- 硬编码的配置值、密钥、URL
- 缺少或错误的边界条件检查
- 过于复杂的函数(圈复杂度高)
- 魔法数字(未命名的常量)
- 重复代码DRY 违反)
- 缺少或过时的注释
- 测试覆盖不足
#### Step 3生成结构化审查结果
按以下 Severity 分级输出:
```markdown
## PR #<id> 代码审查报告
### 🔴 Critical必须修改
- <问题><文件>:<行号>
- <问题描述><文件>:<行号>
> <修改建议>
### 🟡 Warning建议修改 / 🔵 Suggestion可选优化 / ✅ Positive值得肯定
- ...
### 🟡 Warning建议修改
- <问题描述><文件>:<行号>
> <修改建议>
### 总体结论
<评审状态建议rejected / common / approved是否阻塞合并>
### 🔵 Suggestion可选优化
- <问题描述><文件>:<行号>
> <修改建议>
### ✅ Positive值得肯定
- <做得好的地方>
```
**等待用户确认**:用户没说「确认/提交」前停在 Step 3。**禁止用 `--yes` 自行推进。**
### Step 4dry-run 预览(用户确认报告后)
根据报告的严重程度选择评审状态dry-run 预览(不实际提交):
| 报告含 Critical | 评审状态 | 含义 |
|-----------------|----------|------|
| 是 | `rejected` | Request changes阻塞合并 |
| 否,仅 Warning/Suggestion | `common` | 普通评审评论 |
| 无问题 | `approved` | 批准合并 |
#### Step 4提交 Review 评论
```bash
gitlink-cli pr +review --id <pr_id> \
--status <common|approved|rejected> \
--content "<把审查报告 Markdown 作为 content>" \
--dry-run --format json
# 方式 1提交整体 Review
gitlink-cli api POST /:owner/:repo/pulls/:id/reviews --body '{
"body": "## 审查结果\n\n### 🔴 Critical\n...\n\n### 🟡 Warning\n...\n\n总体评价...",
"event": "COMMENT"
}'
# 方式 2在特定行添加内联评论逐条提交
gitlink-cli api POST /:owner/:repo/pulls/:id/reviews --body '{
"body": "这里存在安全风险:用户输入未经转义直接拼接到 SQL 查询中,存在注入风险。建议使用参数化查询。",
"event": "COMMENT",
"commit_id": "<commit_sha>",
"path": "src/query.py",
"position": 42
}'
```
> `--content` 放整体审查报告Markdown。`--commit <sha>` 可选,把评审挂到具体 commit。核对 dry-run 输出无误。
> **注意:** `event` 参数支持 `COMMENT`(普通评论)和 `APPROVE`(批准)。对于需要修改的问题,使用 `COMMENT`
### Step 5提交评审用户确认 dry-run 后)
#### Step 5生成审查摘要
去掉 `--dry-run` 正式提交:
审查完成后,输出 Markdown 摘要供用户查阅
```bash
gitlink-cli pr +review --id <pr_id> \
--status <common|approved|rejected> \
--content "<审查报告>" \
--format json
```
```markdown
## 📋 审查摘要 — PR #<id> <title>
### Step 6行内评论可选针对具体行
| 指标 | 数据 |
|------|------|
| 审查文件数 | <n> |
| 变更行数 | +<add> / -<del> |
| Critical 问题 | <n> |
| Warning | <n> |
| Suggestion | <n> |
需要把某条意见精准挂在某一行时,用 `pr +create-comment`
### 主要发现
1. **[Critical]** <最严重的问题>
2. **[Warning]** <次要问题>
3. **[Suggestion]** <优化建议>
```bash
gitlink-cli pr +create-comment --id <pr_id> \
--path <文件路径> --line <行号> \
--body "<针对该行的意见>" --format json
```
### 总体评价
<整体评估代码质量审查通过建议>
> ⚠️ `--line` 是**文件中的行号**。Diff 输出给的可能是补丁内位置,需换算为文件真实行号(注意文件头部 import/license 偏移)。**若行号不确定,不要盲目发**——把该意见并入 Step 5 的 `--content` 总报告,或改用 `pr +comment`(普通评论,不挂行)。
>
> ⚠️ **实测2026-06-21**`pr +create-comment --line` 会返回 `ok:true`,但返回的 `line_code``null`**评论未真正锚定到该行**(仅挂在文件级)。因此优先用 `pr +review --content` 提交总报告;行内评论不可靠时改用 `pr +comment`
```bash
# 普通评论(挂在 PR 下,不绑定行;行号不确定时的安全 fallback
gitlink-cli pr +comment --id <pr_id> --body "<评论>" --format json
---
*由 gitlink-code-review Skill 自动生成*
```
---
## 评审状态与严重程度的映射
### 工作流 2仓库代码健康度扫描
| 报告内容 | `--status` | 合并建议 |
|---------|-----------|---------|
| 含任何 Critical | `rejected` | 阻塞,修复后复审 |
| 仅 Warning/Suggestion | `common` | 可合并,建议跟进 |
| 全部 Positive / 无问题 | `approved` | 可合并 |
## 安全红线(必须标 Critical
- 硬编码的密钥 / Token / 密码 / 数据库连接串
- SQL / NoSQL 注入(用户输入直接拼接进查询)
- 命令注入shell 命令拼接用户输入)
- 路径遍历(用户输入直接用于文件路径)
- XSS未转义的用户输入直接渲染`innerHTML`
- 不安全的反序列化
## 代码审查最佳实践
1. **先大局后细节**:先理解 PR 目的与整体变更范围,再逐文件审查。
2. **关注行为而非风格**:风格问题交给 linter/formatter。
3. **提供可操作的建议**:不只指出问题,给出具体修改方案。
4. **肯定好的代码**:清晰命名、完善测试、良好设计给予正面反馈。
5. **控制评论量**:最严重的 35 个问题比 20 个小问题更有价值。
## 命令速查
**场景**:对仓库整体代码质量进行评估,不依赖 PR。
```bash
# 获取上下文
gitlink-cli pr +view --id <pr_id> --format json
gitlink-cli pr +files --id <pr_id> --format json
gitlink-cli pr +versions --id <pr_id> --format json # 拿 version_id
gitlink-cli pr +version-diff --id <pr_id> --version-id <vid> --format json # 逐行 diff替代已移除的 pr +diff
# 1. 获取仓库信息
gitlink-cli repo +info --owner <owner> --repo <repo> --format json
# 提交评审(首选)
gitlink-cli pr +review --id <pr_id> --status <common|approved|rejected> --content "<报告>" [--commit <sha>] [--dry-run]
# 2. 获取仓库文件列表(遍历关键目录)
gitlink-cli api GET /:owner/:repo/sub_entries --query 'filepath=src&ref=master'
gitlink-cli api GET /:owner/:repo/sub_entries --query 'filepath=tests&ref=master'
# 行内评论(绑定文件+行;行号不确定时勿用)
gitlink-cli pr +create-comment --id <pr_id> --path <path> --line <n> --body "<意见>"
# 3. 获取关键文件内容
gitlink-cli api GET /:owner/:repo/raw/master/README.md
gitlink-cli api GET /:owner/:repo/raw/master/.gitignore
gitlink-cli api GET /:owner/:repo/raw/master/.eslintrc.js # 或类似配置
gitlink-cli api GET /:owner/:repo/raw/master/package.json # 或 go.mod, Cargo.toml
# 普通评论(不绑行;安全 fallback
gitlink-cli pr +comment --id <pr_id> --body "<评论>"
# 查看已有评审(复审时用)
gitlink-cli pr +reviews --id <pr_id> --format json
# 4. 获取语言统计和贡献者
gitlink-cli api GET /:owner/:repo/languages
gitlink-cli api GET /:owner/:repo/contributors
```
**健康度检查清单:**
| 检查项 | 标准 | 评分依据 |
|--------|------|----------|
| 文档完整性 | 有 README、CONTRIBUTING、CHANGELOG | 文件是否存在、内容质量 |
| 许可证 | 有 LICENSE 文件 | 是否存在、是否合规 |
| CI 配置 | 有 CI 配置(.github/workflows, Jenkinsfile 等) | 文件是否存在 |
| 代码规范 | 有 linter 配置 | eslint/prettier/ruff/pylint 等 |
| 测试覆盖 | 有 test 目录或测试文件 | 测试文件比例 |
| 依赖管理 | 依赖文件完整且无已知漏洞 | package-lock/go.sum/poetry.lock |
| Issue 健康度 | Issue 有分类标签、响应及时 | 通过 Issue 列表分析 |
**输出格式:**
```markdown
## 🏥 仓库健康度报告 — <owner>/<repo>
### 总体评分:<⭐x/5>
| 维度 | 状态 | 评分 | 建议 |
|------|:----:|:----:|------|
| 📖 文档 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> |
| 📜 许可证 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> |
| 🔧 CI/CD | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> |
| 🎨 代码规范 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> |
| 🧪 测试覆盖 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> |
| 📦 依赖安全 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> |
| 🐛 Issue 管理 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> |
### 关键发现
1. <最需要改进的问题>
2. <次要问题>
3. <做得好的方面>
### 改进路线图
- **紧急(本周):** ...
- **短期(本月):** ...
- **长期(本季度):** ...
```
---
### 工作流 3批量 Issue Triage + 自动分配
**场景**:对新 Issue 进行自动分类、标签分配和责任人推荐。
```bash
# 1. 获取未标记的 Issue
gitlink-cli issue +list --state open --format json
# 2. 逐个分析 Issue 内容
gitlink-cli issue +view --id <issue_id> --format json
# 3. 根据内容智能分类
# 分析标题和描述后,通过 Raw API 打标签
gitlink-cli api POST /:owner/:repo/issues/:id --body '{
"issue_tag_ids": [<tag_id>],
"done_ratio": 0,
"subject": "<原始标题>",
"description": "<原始描述>"
}'
```
**分类规则参考:**
| Issue 关键词 | 推荐标签 | 优先级 |
|-------------|----------|:------:|
| bug, 错误, 失败, crash, 崩溃 | bug | 🔴 High |
| feature, 新增, 建议, 希望 | enhancement | 🔵 Low |
| 安全, 漏洞, 权限, 泄露 | security | 🔴 High |
| 性能, 慢, 卡顿, 优化 | performance | 🟡 Medium |
| 文档, README, 注释 | documentation | 🔵 Low |
| question, 如何, 怎么, 请问 | question | 🟡 Medium |
| 测试, test, 覆盖率 | testing | 🔵 Low |
---
## Raw API 参考
评审相关操作**优先用上述 Shortcut**。Shortcut 未覆盖时才用 Raw API且字段需符合 GitLink**不是** GitHub 的 `event:"COMMENT"`/`position`
代码审查相关的 GitLink API 端点
```bash
# 列出已有评审
gitlink-cli api GET /:owner/:repo/pulls/:id/reviews --format json
# 获取 PR 详情
gitlink-cli api GET /:owner/:repo/pulls/:id --format json
# 获取 PR 变更文件列表
gitlink-cli api GET /:owner/:repo/pulls/:id/files --format json
# 获取 PR Diff
gitlink-cli api GET /:owner/:repo/pulls/:id/diff --format json
# 提交 PR Review
gitlink-cli api POST /:owner/:repo/pulls/:id/reviews --body '{"body":"...","event":"COMMENT"}'
# 获取仓库文件列表
gitlink-cli api GET /:owner/:repo/sub_entries --query 'filepath=<path>&ref=<branch>'
# 获取仓库语言统计
gitlink-cli api GET /:owner/:repo/languages --format json
# 获取贡献者列表
gitlink-cli api GET /:owner/:repo/contributors --format json
# 获取仓库动态
gitlink-cli api GET /:owner/:repo/activity --format json
```
> 字段说明详见 [`REFERENCE.md`](REFERENCE.md)。
## 代码审查最佳实践
## 红线与常见错误
### 审查原则
- ❌ **用 GitHub 风格 Raw API 提交评审**`event:"COMMENT"`、`position`、`commit_id`+`path`——GitLink 用 `pr +review --status``pr +create-comment --path --line`
- ❌ **未经用户确认就提交 Review/评论**——必须 报告→确认→dry-run→提交。
- ❌ **用 `--yes` 绕过确认门**——除非用户明确要求「直接提交」。
- ❌ **行号不确定却发 `+create-comment --line`**——会挂错行或被拒;改并入总报告或用 `+comment`
- ❌ **有 Critical 却用 `--status common/approved`**——Critical 必须配 `rejected`
- ❌ **用 `gh` 操作 GitLink**——只用 `gitlink-cli`
- 所有命令加 `--format json` 便于解析;输出为 `{ok, data, meta}` envelope。
1. **先大局后细节**:先理解 PR 的目的和整体变更范围,再逐文件审查
2. **关注行为,而非风格**自动化工具linter/formatter能处理的风格问题优先交给工具
3. **提供可操作的建议**:不只是指出问题,要给出具体的修改方案
4. **肯定好的代码**:发现好的设计、清晰的命名、完善的测试时给予正面反馈
5. **控制评论量**:避免信息过载——最严重的 3-5 个问题比 20 个小问题更有价值
### 安全红线
以下问题必须标记为 **Critical**,不得忽略:
- 硬编码的密钥 / Token / 密码
- SQL / NoSQL 注入漏洞
- 命令注入shell 命令拼接)
- 路径遍历(用户输入直接用于文件路径)
- 不安全的反序列化
- XSS未转义的用户输入直接渲染
### 输出规范
- 始终使用 `--format json` 获取结构化数据
- 审查报告输出为 **Markdown 格式**,便于直接粘贴到 PR 评论
- 涉及文件/行号时使用精准引用,方便定位
- 批量操作前使用 `--dry-run` 预检
## 注意事项
- Review/评论提交后会通知 PR 所有相关人,内容请专业、可操作。
- 大型 PR 的 diff 可能非常大,按文件分段处理,避免一次性塞满上下文。
- `pr +diff` / `+files` 接口有频率限制,避免短时间内重复请求。
- 对 draft PR提示用户先标记为 Ready for Review 再审查。
- 审查范围限于 PR 本身代码审查仓库整体健康度、Issue 分拣等场景见各自专用 Skill不在本 Skill 范围。
- PR Review 提交后会通知所有关注该 PR 的参与者,评论内容请保持专业
- `pr +diff` 输出可能很大(大型 PRAgent 应分段处理
- API 的 PR files 和 diff 接口有频率限制,避免短时间内重复请求
- 对于 draft PR草稿应提示用户先将其标记为 Ready for Review

View File

@ -113,50 +113,17 @@ gitlink-cli pr +diff --id 42 --format json
- 有类型注解,代码可读性好
```
### Step 5dry-run 预览(用户确认报告后)
报告含 2 个 Critical评审状态取 `rejected`Request changes。先 dry-run 预览,**不实际提交**
### Step 5提交 Review
```bash
gitlink-cli pr +review --id 42 \
--status rejected \
--content "## PR #42 代码审查报告
### 🔴 Critical
1. **JWT Secret 硬编码** — src/config.py:15。建议 os.getenv(\"JWT_SECRET\")。
2. **SQL 注入风险** — src/auth/login.py:42。建议参数化查询。
### 🟡 Warning
1. **密码明文存储** — 建议使用 bcrypt 哈希处理。
### 总体评价
代码整体结构清晰,测试覆盖良好。建议修复 Critical 问题后合并。" \
--dry-run --format json
# 提交整体 Review 评论
gitlink-cli api POST /Gitlink/forgeplus/pulls/42/reviews --body '{
"body": "## PR #42 代码审查报告\n\n### 🔴 Critical\n\n1. **JWT Secret 硬编码**`src/config.py:15`\n JWT_SECRET 硬编码在源码中。建议使用 `os.getenv(\"JWT_SECRET\")`。\n\n2. **SQL 注入风险**`src/auth/login.py:42`\n 直接拼接用户输入到 SQL 查询。建议使用参数化查询。\n\n### 🟡 Warning\n\n1. **密码明文存储** — 建议使用 bcrypt 哈希处理。\n\n### 总体评价\n\n代码整体结构清晰测试覆盖良好。建议修复 Critical 问题后合并。",
"event": "COMMENT"
}'
```
→ 核对预览无误,请用户二次确认。
### Step 6提交评审用户确认 dry-run 后)
去掉 `--dry-run` 正式提交:
```bash
gitlink-cli pr +review --id 42 --status rejected --content "<同上审查报告>" --format json
```
### Step 7行内评论可选针对具体行
把 Critical 意见精准挂到对应行(行号取文件真实行号,注意 import/头注释偏移;不确定则并入上面的总报告):
```bash
gitlink-cli pr +create-comment --id 42 --path src/config.py --line 15 \
--body "Critical: JWT_SECRET 硬编码,存在泄露风险。改用 os.getenv(\"JWT_SECRET\")。" --format json
gitlink-cli pr +create-comment --id 42 --path src/auth/login.py --line 42 \
--body "Critical: SQL 注入风险,用户输入直接拼接。改用参数化查询。" --format json
```
### Step 8输出审查摘要
### Step 6输出审查摘要
```markdown
## 📋 审查摘要 — PR #42 feat: add user authentication module
@ -192,12 +159,6 @@ gitlink-cli pr +files --id <id> --format json
# 获取 Diff
gitlink-cli pr +diff --id <id> --format json
# 提交评审首选Critical→rejected / 仅建议→common / 无问题→approved
gitlink-cli pr +review --id <id> --status <common|approved|rejected> --content "<审查报告>" [--dry-run]
# 行内评论(绑定文件+行;行号不确定时勿用,改用 +comment 或并入 --content
gitlink-cli pr +create-comment --id <id> --path <path> --line <n> --body "<意见>"
# 普通评论(不绑行)
gitlink-cli pr +comment --id <id> --body "<评论>"
# 提交 Review
gitlink-cli api POST /:owner/:repo/pulls/:id/reviews --body '{"body":"...","event":"COMMENT"}'
```

View File

@ -1,202 +0,0 @@
---
name: gitlink-community-ops
version: 1.0.0
description: "社区运营自动化Issue 自动分拣 → 周报生成 → Release Notes 发布。串联 issue-triage、project-health、release-auto 三阶段,实现社区运营全自动化。"
metadata:
requires:
bins: ["gitlink-cli", "jq"]
cliHelp: "gitlink-cli issue --help / gitlink-cli pr --help / gitlink-cli release --help"
---
# gitlink-community-ops社区运营自动化
> **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解认证、全局参数和 API 注意事项。
>
> **CRITICAL — 所有 GitLink 操作必须使用 `gitlink-cli`,禁止使用 `gh`GitHub CLI操作 GitLink 资源。**
## 说明
本 Skill 串联 **三个已有 Skill** 形成一个完整的社区运营自动化流水线:
1. **Issue 自动分拣** — 新 Issue 自动分类、打标签、分配责任人、添加引导评论
2. **社区周报生成** — 采集 Issue/PR/Commit/Milestone 数据,生成带评分的健康度报告
3. **自动发布 Release Notes** — 分析提交历史,生成结构化 Release Notes 并创建发布
**与子任务二的区别:** 子任务二交付的是单一步骤的 Skill如只做 Issue 分拣),而本工作流将多个 Skill 串联成完整的端到端解决方案。
---
## 三阶段工作流总览
```mermaid
flowchart LR
A[新 Issue / 周期触发] --> B[Phase 1: Issue 分拣]
B --> C[Phase 2: 周报生成]
C --> D[Phase 3: Release Notes]
subgraph B[Phase 1: Issue Triage]
B1[采集未分类 Issue] --> B2[关键词权重分析]
B2 --> B3[自动打标签]
B3 --> B4[添加引导评论]
end
subgraph C[Phase 2: 周报]
C1[采集 Issue/PR/Commit/Milestone] --> C2[计算健康度评分]
C2 --> C3[生成趋势报告]
end
subgraph D[Phase 3: Release]
D1[获取最新 Tag] --> D2[分析提交历史]
D2 --> D3[语义化版本推荐]
D3 --> D4[生成 Release Notes]
D4 --> D5[创建 Release]
end
```
---
## Phase 1Issue 自动分拣
**参考 Skill** [`../gitlink-issue-triage/SKILL.md`](../gitlink-issue-triage/SKILL.md)
### 步骤
```bash
# 1. 获取所有打开的 Issue
gitlink-cli issue +list --owner <owner> --repo <repo> --state open --format json
# 2. 逐个查看 Issue 详情(提取标题和描述用于分析)
gitlink-cli issue +view --owner <owner> --repo <repo> --number <id> --format json
# 3. 关键词权重分析AI 执行)
# 参见 gitlink-issue-triage 的"关键词权重分类系统"
# 4. 获取可用标签
gitlink-cli label +list --owner <owner> --repo <repo>
# 5. 打标签dry-run 优先)
gitlink-cli issue +update --owner <owner> --repo <repo> --number <id> --labels <label_id>
# 6. 添加引导评论
gitlink-cli issue +comment --owner <owner> --repo <repo> --number <id> --body "<comment>"
```
### 关键词权重分类矩阵
| 类别 | 关键词 | 权重分 | 建议标签 |
|------|--------|--------|---------|
| Bug | bug(10)、错误(8)、失败(7)、异常(6)、crash(10)、报错(5) | ≥15 | bug |
| 功能需求 | 建议(8)、希望(7)、需要(5)、feature(8)、支持(4)、新增(5) | ≥12 | enhancement |
| 文档 | 文档(10)、README(8)、拼写(5)、缺少(4)、帮助(3) | ≥10 | documentation |
| 安全 | 漏洞(10)、安全(8)、权限(7)、泄露(8)、注入(6) | ≥12 | security |
| 性能 | 慢(8)、卡顿(7)、性能(6)、优化(5)、performance(8) | ≥10 | performance |
| 问题咨询 | 请问(5)、怎么(5)、如何(4)、help(3)、? (2) | ≥6 | question |
---
## Phase 2社区周报生成
**参考 Skill** [`../gitlink-project-health/SKILL.md`](../gitlink-project-health/SKILL.md)
### 数据采集
```bash
# Issue 数据
gitlink-cli issue +list --owner <owner> --repo <repo> --state all --format json
gitlink-cli issue +list --owner <owner> --repo <repo> --state open
gitlink-cli issue +list --owner <owner> --repo <repo> --state closed --limit 50
# PR 数据
gitlink-cli pr +list --owner <owner> --repo <repo> --state all --format json
gitlink-cli pr +list --owner <owner> --repo <repo> --state merged --limit 50
# 贡献者数据
gitlink-cli commit +list --owner <owner> --repo <repo> --limit 50
# 里程碑
gitlink-cli milestone +list --owner <owner> --repo <repo>
```
### 评分维度
| 维度 | 计算方法 | 权重 |
|------|----------|------|
| Issue 健康度 | 关闭率 + 平均响应时间 | 30% |
| PR 健康度 | 合并率 + 平均合并时间 | 30% |
| 贡献者活跃度 | 贡献者数 + 提交频率 | 25% |
| 里程碑进度 | 完成度 + 逾期风险 | 15% |
### 综合评分
```
综合得分 = Issue得分 × 30% + PR得分 × 30% + 活跃度得分 × 25% + 里程碑得分 × 15%
9-10 → 🟢 优秀 7-8 → 🟢 良好
5-6 → 🟡 一般 3-4 → 🔴 堪忧
0-2 → 🔴 危险
```
---
## Phase 3自动 Release Notes
**参考 Skill** [`../gitlink-release-auto/SKILL.md`](../gitlink-release-auto/SKILL.md)
### 步骤
```bash
# 1. 获取最新 Release 确定基线版本
gitlink-cli release +list --owner <owner> --repo <repo> --format json
# 2. 获取从上一版本到当前的提交历史
git log <last_tag>..HEAD --format="%H|%s|%an|%ad" --date=short --stat
# 3. AI 分析提交分类(按 Conventional Commits 规范)
# feat: → ✨ 新功能 fix: → 🐛 Bug 修复
# docs: → 📝 文档 refactor: → ♻️ 重构
# perf: → ⚡ 性能优化 test: → ✅ 测试
# chore: → 🔧 工程 revert: → ⏪ 回退
# 4. 语义化版本推荐
# BREAKING CHANGE → 主版本 +1
# feat → 次版本 +1
# fix/docs/refactor → 修订号 +1
# 5. 创建 Releasedry-run 模式优先)
gitlink-cli release +create --owner <owner> --repo <repo> \
--tag <new_version> --name "<new_version>" \
--body "<generated_release_notes>" --target master
```
---
## 可复现脚本
本 Skill 提供可直接执行的 Bash 脚本,位于 `scripts/` 目录:
| 脚本 | 功能 | 使用方式 |
|------|------|----------|
| `01-issue-triage.sh` | Phase 1 Issue 分拣 | `bash 01-issue-triage.sh <owner> <repo>` |
| `02-weekly-health-report.sh` | Phase 2 周报生成 | `bash 02-weekly-health-report.sh <owner> <repo>` |
| `03-auto-release-notes.sh` | Phase 3 Release Notes | `bash 03-auto-release-notes.sh <owner> <repo>` |
| `community-ops-full.sh` | 全流程串联 | `bash community-ops-full.sh <owner> <repo>` |
**所有脚本默认 dry-run 模式**(不会实际修改数据),确认无误后通过环境变量切换:
```bash
# Dry-run默认安全
DRY_RUN=true bash scripts/community-ops-full.sh z2_cc gitlink-cli
# 实际执行
DRY_RUN=false bash scripts/community-ops-full.sh z2_cc gitlink-cli
```
---
## 注意事项
1. **dry-run 优先**:所有写操作(`issue +update`、`issue +comment`、`release +create`)默认不应实际执行
2. **Token 有效**:运行前确认 `gitlink-cli auth status` 返回正常
3. **关键词准确率**AI 的分类结果建议人工复核,特别是边缘情况
4. **版本号冲突**:如果最新 tag 不是 release 版本,需人工确认基线
5. **输出文件**:所有 JSON 数据保存到 `scripts/_output/` 目录供审计

View File

@ -1,150 +0,0 @@
# 社区运营自动化工作流 — 端到端示例
**场景**:项目维护者希望自动处理社区的日常运营工作:新 Issue 自动分类、每周生成社区报告、版本发布时自动生成 Release Notes。
## 前置条件
- `gitlink-cli` 已安装并登录(`gitlink-cli auth status`
- 目标仓库已确认(示例使用 `z2_cc/gitlink-cli`
- `jq` 已安装(用于 JSON 解析)
## 工作流步骤
### Step 1Issue 自动分拣
```bash
# 1.1 获取所有打开的 Issue
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state open --format json
```
**输出示例:**
```json
{
"ok": true,
"data": [
{"number": 42, "subject": "登录页面报错500 Internal Server Error", "state": 1},
{"number": 43, "subject": "建议增加导出功能", "state": 1},
{"number": 44, "subject": "README 中缺少安装说明", "state": 1}
]
}
```
```bash
# 1.2 分析 Issue 内容并进行关键词权重评分AI 驱动)
# Issue #42: "报错"(5) + "500"(0) = 5分 → Bug → 标签: bug
# Issue #43: "建议"(8) + "增加"(5) = 13分 → 功能需求 → 标签: enhancement
# Issue #44: "文档"(10) + "缺少"(4) = 14分 → 文档 → 标签: documentation
# 1.3 获取可用标签列表
gitlink-cli label +list --owner z2_cc --repo gitlink-cli
```
```bash
# 1.4 为 Issue #42 添加标签和分类评论dry-run 模式)
DRY_RUN=true
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] 将为 Issue #42 添加标签: bug"
echo "[DRY-RUN] 将为 Issue #42 添加评论:自动分类结果"
fi
```
**Expected:** 所有未分类的 Issue 被分析并建议标签。dry-run 模式下不实际修改。
### Step 2社区周报生成
```bash
# 2.1 采集周报数据
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state all --format json
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state closed --limit 50 --format json
gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state all --format json
gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state merged --limit 50 --format json
gitlink-cli commit +list --owner z2_cc --repo gitlink-cli --limit 50
gitlink-cli milestone +list --owner z2_cc --repo gitlink-cli --format json
```
**输出示例Issue 数据):**
```json
{
"ok": true,
"data": {
"total_count": 16,
"issues": [
{"number": 1, "subject": "...", "state": 2, "created_at": "2026-05-20", "closed_at": "2026-05-21"},
{"number": 2, "subject": "...", "state": 1, "created_at": "2026-06-01"}
]
}
}
```
**AI 分析逻辑:**
```
总 Issue = 16打开 2 + 关闭 14
关闭率 = 14/16 = 87.5% → 🟢 优秀
平均响应时间 = 计算 closed_at - created_at 的平均天数
近 30 天净变化 = 新增 - 关闭
```
### Step 3自动 Release Notes
```bash
# 3.1 获取最新 Release 确定基线版本
gitlink-cli release +list --owner z2_cc --repo gitlink-cli --format json
```
**输出示例:**
```json
{
"ok": true,
"data": [
{"tag_name": "v0.2.0", "name": "v0.2.0", "created_at": "2026-06-17"}
]
}
```
```bash
# 3.2 获取提交历史
git log v0.2.0..HEAD --format="%H|%s|%an|%ad" --date=short
```
**输出示例:**
```
abc1234|feat: 新增 Webhook 投递监控|z2_cc|2026-06-20
abc1235|fix: 修复 Wiki 侧边栏残留|z2_cc|2026-06-22
abc1236|docs: 更新 CLI 帮助文档|z2_cc|2026-06-24
```
**AI 分析结果:**
```
共 3 次提交feat 1、fix 1、docs 1
涉及 5 个文件,+120/-30 行
推荐版本v0.3.0(有 feat无 breaking
```
```bash
# 3.3 创建 Releasedry-run 模式)
echo "[DRY-RUN] 将创建 Release: v0.3.0"
echo "[DRY-RUN] Release Notes 已生成到 _output/release-notes-v0.3.0.md"
```
## 完整命令速览
```bash
# Phase 1: Issue Triage
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state open --format json
gitlink-cli label +list --owner z2_cc --repo gitlink-cli
# Phase 2: Weekly Report
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state all --format json
gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state all --format json
gitlink-cli commit +list --owner z2_cc --repo gitlink-cli --limit 50
# Phase 3: Release Notes
gitlink-cli release +list --owner z2_cc --repo gitlink-cli --format json
git log <last_tag>..HEAD --format="%H|%s|%an|%ad" --date=short
```
## 注意事项
- 所有写操作默认 dry-run确认后通过 `DRY_RUN=false` 实际执行
- 确保在仓库目录下运行(或显式指定 `--owner``--repo`
- 周报的数据范围建议明确(如"最近 7 天"

View File

@ -1,140 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 1: Issue 自动分拣
# 功能:采集未分类 Issue → 关键词权重分析 → 打标签 → 加评论
# 使用bash 01-issue-triage.sh <owner> <repo>
# 环境变量DRY_RUN=true|false (默认 true)
# ================================================================
set -e
# 使用本地编译的 gitlink-cli支持完整命令
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LOCAL_CLI="$(cd "$SCRIPT_DIR/../../.." && pwd)/gitlink-cli.exe"
if [ -f "$LOCAL_CLI" ]; then
CLI="$LOCAL_CLI"
else
CLI="gitlink-cli"
fi
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 1: Issue 自动分拣 ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[ DRY_RUN: $DRY_RUN ]"
echo "[========================================]"
# Step 1: 获取所有打开的 Issue
echo "[INFO] 获取所有打开的 Issue..."
ISSUES=$($CLI issue +list --owner "$OWNER" --repo "$REPO" --state open --format json 2>&1) || {
echo "[ERROR] 获取 Issue 列表失败: $ISSUES"
exit 1
}
echo "$ISSUES" > "$OUTPUT_DIR/issues-open.json"
TOTAL=$(echo "$ISSUES" | node -e "
let s='';
process.stdin.on('data',d=>s+=d).on('end',()=>{
const d=JSON.parse(s).data||[];
const items=Array.isArray(d)?d:(d.issues||[]);
process.stdout.write(String(items.length));
});
" 2>/dev/null || echo "0")
echo "[INFO] 发现 $TOTAL 个待处理的 Issue"
if [ "$TOTAL" -eq 0 ]; then
echo "[INFO] 没有待处理的 Issue跳过"
exit 0
fi
# Step 2: 获取可用标签
echo "[INFO] 获取可用标签列表..."
LABELS=$($CLI label +list --owner "$OWNER" --repo "$REPO" --format json 2>&1) || {
echo "[WARN] 获取标签列表失败"
LABELS='{"data":[]}'
}
echo "$LABELS" > "$OUTPUT_DIR/labels.json"
# Step 3: 逐 Issue 分析
echo "[INFO] 开始分析每个 Issue..."
for i in $(seq 0 $((TOTAL - 1))); do
ISSUE_DATA=$(echo "$ISSUES" | node -e "
let s='';
process.stdin.on('data',d=>s+=d).on('end',()=>{
const d=JSON.parse(s).data||[];
const items=Array.isArray(d)?d:(d.issues||[]);
process.stdout.write(JSON.stringify(items[$i]));
});
")
NUMBER=$(echo "$ISSUE_DATA" | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{const d=JSON.parse(s);process.stdout.write(String(d.number||d.id||''))})")
SUBJECT=$(echo "$ISSUE_DATA" | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{const d=JSON.parse(s);process.stdout.write(String(d.subject||d.title||''))})")
if [ -z "$NUMBER" ]; then
echo "[WARN] Issue #$i: 无法解析编号,跳过"
continue
fi
echo ""
echo "[INFO] --- Issue #$NUMBER: $SUBJECT ---"
# 获取 Issue 详情
DETAIL=$($CLI issue +view --owner "$OWNER" --repo "$REPO" --number "$NUMBER" --format json 2>&1) || {
echo "[WARN] 获取 Issue #$NUMBER 详情失败,使用标题分析"
DETAIL="{\"data\":{\"subject\":\"$SUBJECT\",\"description\":\"\"}}"
}
echo "$DETAIL" > "$OUTPUT_DIR/issue-$NUMBER-detail.json"
# ---- Step 4: 关键词权重分析(自动分类) ----
CATEGORY="needs-triage"
LABEL_ID=""
LABEL_NAME=""
COMMENT_TEXT=""
# 简单关键词匹配
case "$SUBJECT" in
*[Bb]ug*|*错误*|*失败*|*异常*|*crash*|*报错*)
CATEGORY="bug"; LABEL_ID="325573"; LABEL_NAME="缺陷"
COMMENT_TEXT="AI 自动分类结果:🐛 Bug缺陷"
;;
*建议*|*希望*|*feature*|*新增*|*支持*|*Shortcut*|*命令*|*兼容*|*封装*|*API*|*子任务*|*Webhook*|*Wiki*|*Snippet*)
CATEGORY="enhancement"; LABEL_ID="325574"; LABEL_NAME="功能"
COMMENT_TEXT="AI 自动分类结果:✨ 功能需求"
;;
*文档*|*README*|*拼写*|*帮助*|*doc*|*说明*)
CATEGORY="documentation"; LABEL_ID="325580"; LABEL_NAME="文档"
COMMENT_TEXT="AI 自动分类结果:📝 文档"
;;
*demo*|*测试*|*test*)
CATEGORY="test"; LABEL_ID="325581"; LABEL_NAME="测试"
COMMENT_TEXT="AI 自动分类结果:🧪 测试"
;;
esac
echo "[INFO] 分类结果: $CATEGORY (标签: $LABEL_NAME)"
# ---- Step 5: 打标签 + 加评论 ----
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] 将为 Issue #$NUMBER 添加标签: $LABEL_NAME ($LABEL_ID)"
echo "[DRY-RUN] 将添加引导评论: $COMMENT_TEXT"
else
echo "[INFO] 为 Issue #$NUMBER 打标签和添加评论..."
if [ -n "$LABEL_ID" ]; then
$CLI issue +batch-update --owner "$OWNER" --repo "$REPO" --numbers "$NUMBER" --label "$LABEL_ID" 2>&1 || echo "[WARN] 打标签失败"
fi
if [ -n "$COMMENT_TEXT" ]; then
$CLI issue +comment --owner "$OWNER" --repo "$REPO" --number "$NUMBER" --body "$COMMENT_TEXT" 2>&1 || echo "[WARN] 添加评论失败"
fi
echo "[INFO] Issue #$NUMBER 处理完成"
fi
done
echo ""
echo "[========================================]"
echo "[ Phase 1 完成 ]"
echo "[ Issue 数据保存至: $OUTPUT_DIR/ ]"
echo "[========================================]"

View File

@ -1,49 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 2: 社区周报生成
# 功能:采集 Issue/PR/Commit/Milestone 数据 → 计算健康度评分 → 生成报告
# 使用bash 02-weekly-health-report.sh <owner> <repo>
# ================================================================
set -e
# 自动检测并使用本地编译的 gitlink-cli
source "$(cd "$(dirname "$0")" && pwd)/../../gitlink-shared/scripts/detect-cli.sh"
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 2: 社区周报生成 ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[========================================]"
# ---- Step 1: 采集 Issue 数据 ----
echo "[INFO] 采集 Issue 数据..."
gitlink-cli issue +list --owner "$OWNER" --repo "$REPO" --state all --format json > "$OUTPUT_DIR/issues-all.json" 2>&1 || echo "[WARN] 采集 Issue all 失败"
gitlink-cli issue +list --owner "$OWNER" --repo "$REPO" --state open --format json > "$OUTPUT_DIR/issues-open.json" 2>&1 || echo "[WARN] 采集 Issue open 失败"
gitlink-cli issue +list --owner "$OWNER" --repo "$REPO" --state closed --limit 50 --format json > "$OUTPUT_DIR/issues-closed.json" 2>&1 || echo "[WARN] 采集 Issue closed 失败"
# ---- Step 2: 采集 PR 数据 ----
echo "[INFO] 采集 PR 数据..."
gitlink-cli pr +list --owner "$OWNER" --repo "$REPO" --state all --format json > "$OUTPUT_DIR/prs-all.json" 2>&1 || echo "[WARN] 采集 PR all 失败"
gitlink-cli pr +list --owner "$OWNER" --repo "$REPO" --state open --format json > "$OUTPUT_DIR/prs-open.json" 2>&1 || echo "[WARN] 采集 PR open 失败"
gitlink-cli pr +list --owner "$OWNER" --repo "$REPO" --state merged --limit 50 --format json > "$OUTPUT_DIR/prs-merged.json" 2>&1 || echo "[WARN] 采集 PR merged 失败"
# ---- Step 3: 采集贡献者数据 ----
echo "[INFO] 采集贡献者数据..."
gitlink-cli commit +list --owner "$OWNER" --repo "$REPO" --limit 50 --format json > "$OUTPUT_DIR/commits-50.json" 2>&1 || gitlink-cli repo +contributors --owner "$OWNER" --repo "$REPO" --format json > "$OUTPUT_DIR/contributors.json" 2>&1 || echo "[WARN] 采集贡献者数据失败"
gitlink-cli milestone +list --owner "$OWNER" --repo "$REPO" --format json > "$OUTPUT_DIR/milestones.json" 2>&1 || echo "[WARN] 采集 milestone 失败"
gitlink-cli repo +info --owner "$OWNER" --repo "$REPO" --format json > "$OUTPUT_DIR/repo-info.json" 2>&1 || echo "[WARN] 采集 repo info 失败"
# ---- Step 4: 数据分析 ----
echo "[INFO] 运行数据分析引擎..."
node "$SCRIPT_DIR/health-analyze.js" "$OUTPUT_DIR"
echo ""
echo "[========================================]"
echo "[ Phase 2 完成 ]"
echo "[ 数据保存至: $OUTPUT_DIR/ ]"
echo "[========================================]"

View File

@ -1,91 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 3: 自动 Release Notes
# 功能:获取最新 tag → 分析 commit → 推荐版本号 → 生成 Release Notes
# 使用bash 03-auto-release-notes.sh <owner> <repo>
# 环境变量DRY_RUN=true|false (默认 true)
# ================================================================
set -e
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 3: 自动 Release Notes ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[ DRY_RUN: $DRY_RUN ]"
echo "[========================================]"
# ---- Step 1: 获取最新 Release ----
echo "[INFO] 获取最新 Release..."
RELEASE_DATA=$(gitlink-cli release +list --owner "$OWNER" --repo "$REPO" --format json 2>&1) || {
echo "[WARN] 获取 Release 列表失败: $RELEASE_DATA"
echo "[INFO] 使用默认基线 v0.0.0"
LAST_TAG="v0.0.0"
}
echo "$RELEASE_DATA" > "$OUTPUT_DIR/releases.json"
# 提取最新 tag
LAST_TAG=$(echo "$RELEASE_DATA" | node -e "
let s='';
process.stdin.on('data',d=>s+=d).on('end',()=>{
try {
const d=JSON.parse(s).data||[];
const items=Array.isArray(d)?d:(d.releases||d);
if(items.length>0) process.stdout.write(String(items[0].tag_name||'v0.0.0'));
else process.stdout.write('v0.0.0');
} catch(e) { process.stdout.write('v0.0.0'); }
});
" 2>/dev/null || echo "v0.0.0")
echo "[INFO] 最新 tag: $LAST_TAG"
# ---- Step 2: 获取提交历史 ----
echo "[INFO] 获取提交历史 (基线: $LAST_TAG)..."
# 尝试从 git 获取(需要在 repo 目录下)
if git rev-parse --git-dir > /dev/null 2>&1; then
echo "[INFO] 在 git 仓库中,尝试获取 tags..."
git fetch --tags 2>&1 | tail -3 || true
# 检查 tag 是否存在
if git rev-parse -q --verify "$LAST_TAG" > /dev/null 2>&1; then
echo "[INFO] 找到本地 tag: $LAST_TAG"
git log "$LAST_TAG"..HEAD --format="%H|%s|%an|%ad" --date=short > "$OUTPUT_DIR/commits-since-$LAST_TAG.log" 2>&1
git log "$LAST_TAG"..HEAD --stat --oneline > "$OUTPUT_DIR/stats-since-$LAST_TAG.log" 2>&1
echo "[INFO] 提交历史已保存"
else
echo "[WARN] 本地未找到 tag '$LAST_TAG',尝试从远程获取..."
# 尝试从 remote 获取指定 tag
git fetch origin tag "$LAST_TAG" 2>&1 | tail -3 || true
if git rev-parse -q --verify "$LAST_TAG" > /dev/null 2>&1; then
git log "$LAST_TAG"..HEAD --format="%H|%s|%an|%ad" --date=short > "$OUTPUT_DIR/commits-since-$LAST_TAG.log" 2>&1
git log "$LAST_TAG"..HEAD --stat --oneline > "$OUTPUT_DIR/stats-since-$LAST_TAG.log" 2>&1
else
echo "[WARN] 远程也无此 tag获取全部提交历史"
git log --all --format="%H|%s|%an|%ad" --date=short -100 > "$OUTPUT_DIR/commits-since-$LAST_TAG.log" 2>&1
git log --all --oneline --stat -100 > "$OUTPUT_DIR/stats-since-$LAST_TAG.log" 2>&1
echo "[INFO] 已获取最近 100 条提交(未按 tag 过滤)"
fi
fi
else
echo "[WARN] 不在 git 仓库中,通过 CLI 获取提交历史..."
source "$SCRIPT_DIR/../../gitlink-shared/scripts/detect-cli.sh" 2>/dev/null || true
gitlink-cli commit +list --owner "$OWNER" --repo "$REPO" --limit 100 --format json > "$OUTPUT_DIR/commits-api.json" 2>&1 || {
echo "[ERROR] 通过 API 获取提交历史也失败"
echo "[INFO] Release Notes 生成跳过"
touch "$OUTPUT_DIR/commits-api.json"
}
fi
# ---- Step 3: 运行 Release 分析引擎 ----
echo "[INFO] 运行 Release Notes 分析引擎..."
node "$SCRIPT_DIR/release-analyze.js" "$OUTPUT_DIR" "$LAST_TAG"
echo ""
echo "[========================================]"
echo "[ Phase 3 完成 ]"
echo "[========================================]"

View File

@ -1,338 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>release-notes-v0.1.0</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif;
background: #f1f5f9;
color: #1e293b;
line-height: 1.7;
}
.page {
max-width: 900px;
margin: 0 auto;
padding: 0 20px 60px;
}
.header-card {
background: linear-gradient(135deg, #1e293b, #334155);
color: white;
border-radius: 16px;
padding: 32px 40px;
margin: 24px 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 20px;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
}
.header-card h1 {
font-size: 22px;
font-weight: 600;
line-height: 1.3;
}
.header-card .meta {
font-size: 13px;
color: #94a3b8;
margin-top: 6px;
}
.card {
background: white;
border-radius: 12px;
padding: 24px 28px;
margin-bottom: 16px;
box-shadow: 0 1px 4px rgba(0,0,0,0.04);
border: 1px solid #e2e8f0;
}
.card h2 {
font-size: 16px;
font-weight: 600;
color: #0f172a;
margin-bottom: 14px;
padding-bottom: 8px;
border-bottom: 2px solid #f1f5f9;
display: flex;
align-items: center;
gap: 8px;
}
.card h3 {
font-size: 14px;
font-weight: 600;
color: #334155;
margin: 16px 0 8px;
}
.card h4 {
font-size: 13px;
font-weight: 600;
color: #475569;
margin: 12px 0 6px;
}
.card p {
font-size: 14px;
color: #475569;
margin-bottom: 8px;
}
.card p:last-child { margin-bottom: 0; }
.card code {
background: #f1f5f9;
padding: 1px 6px;
border-radius: 4px;
font-size: 13px;
font-family: 'Cascadia Code', 'Fira Code', monospace;
color: #0f172a;
}
.card strong {
color: #0f172a;
}
.score-section {
text-align: center;
padding: 8px 0;
}
.score-ring {
display: inline-block;
}
.score-label {
font-size: 18px;
font-weight: 600;
margin-top: 4px;
}
.table-wrap {
overflow-x: auto;
margin: 10px 0;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
th {
background: #f8fafc;
font-weight: 600;
text-align: left;
padding: 10px 12px;
border-bottom: 2px solid #e2e8f0;
color: #475569;
white-space: nowrap;
}
td {
padding: 9px 12px;
border-bottom: 1px solid #f1f5f9;
color: #334155;
}
tr:last-child td { border-bottom: none; }
tr:hover td { background: #f8fafc; }
.cell-ok { color: #16a34a; font-weight: 500; }
.cell-fail { color: #dc2626; }
.cell-green { color: #16a34a; }
.cell-yellow { color: #ca8a04; }
.cell-red { color: #dc2626; }
.cell-warn { color: #ea580c; }
ol {
padding-left: 20px;
margin: 8px 0;
}
ol li {
font-size: 14px;
color: #475569;
padding: 4px 0;
list-style-position: outside;
}
li::marker {
font-weight: 600;
color: #3b82f6;
}
.code-block {
background: #0f172a;
color: #e2e8f0;
padding: 16px 20px;
border-radius: 8px;
font-size: 13px;
overflow-x: auto;
margin: 12px 0;
line-height: 1.5;
font-family: 'Cascadia Code', 'Fira Code', monospace;
}
.footer {
text-align: center;
padding: 24px;
color: #94a3b8;
font-size: 12px;
}
@media (max-width: 640px) {
.page { padding: 0 12px 40px; }
.header-card { padding: 20px; flex-direction: column; text-align: center; }
.header-card h1 { font-size: 18px; }
.card { padding: 16px; }
}
@media print {
body { background: white; }
.header-card { break-inside: avoid; }
.card { break-inside: avoid; box-shadow: none; border: 1px solid #e2e8f0; }
}
</style>
</head>
<body>
<div class="page">
<div class="header-card">
<div>
<h1>release-notes-v0.1.0</h1>
<div class="meta">生成时间2026/6/30 10:49:09</div>
</div>
</div>
<div class="card report-content">
<h2>v0.1.0 (2026-06-30)</h2>
<h3>📊 版本概览</h3>
<ol><li>基于上一版本v0.0.0</li>
<li>包含 <strong>100</strong> 次提交</li>
<li>涉及 <strong>252</strong> 个文件</li>
<li>新增 <strong>22410</strong> 行 / 删除 <strong>5510</strong></li>
<li>贡献者:<strong>7</strong></li>
<p></ol></p>
<h3>✨ 新功能22</h3>
<ol><li>feat: PPT 添加 HTML 报告超链接跳转(@赵昌)</li>
<li>feat: 整合 Demo 终端输出到 PPT@赵昌)</li>
<li>feat: PPT 添加备注稿和演示跳转按钮(@赵昌)</li>
<li>feat: 综合演示网页 + 增强 PPT17页@赵昌)</li>
<li>feat: 汇报 PPT 和演示脚本(@赵昌)</li>
<li>feat: 子任务三 & 子任务四 — 端到端工作流与科研辅助模块(@赵昌)</li>
<li>feat(skills): 完善 issue-triage 与 code-review Skill补充 gitlink-shared 已知坑(@s2_cc</li>
<li>feat(skills): 新增 gitlink-pr-deep-review PR 深度审查 Skill@z2_cc</li>
<li>feat(skills): 新增 gitlink-duplicate-detector 重复 Issue 检测 Skill@kaka</li>
<li>feat(compliance-skill): 新增敏感信息扫描工作流与报告整合(@刘焱)</li>
<li>feat(output): 单对象详情渲染为可读的层级表格,不再回退 JSON@刘焱)</li>
<li>feat(interactive): 默认使用 table 格式输出,提升可读性(@刘焱)</li>
<li>feat(interactive): add scrollable viewport for long command output@刘焱)</li>
<li>feat(output): improve table readability — truncate values, limit columns, summarize nested maps@刘焱)</li>
<li>feat(output): render nested list data as table instead of falling back to JSON@刘焱)</li>
<li>feat(interactive): add REPL with command palette, form, and cobra entry@刘焱)</li>
<li>feat(interactive): add command executor with stdout capture and flag parsing@刘焱)</li>
<li>feat(shortcuts): export GetAllShortcuts and GetDescriptions for interactive mode@刘焱)</li>
<li>feat: add three new skills - issue triage, project health, newcomer guide@赵昌)</li>
<li>feat: add wiki and snippet skills, update webhook skill with new commands@赵昌)</li>
<li>feat: task-view supports both numeric ID and UUID lookup@赵昌)</li>
<li>feat: add webhook +failed and +task-view commands@赵昌)</li>
<p></ol></p>
<p><strong>占比:</strong> 22%</p>
<h3>🐛 Bug 修复15</h3>
<ol><li>fix: 修正成员信息并去除学校水印(@赵昌)</li>
<li>fix: 优化技术债务(@赵昌)</li>
<li>fix(newcomer-skill): 修复 label 命令 Bug加入状态过滤与幂等去重@刘焱)</li>
<li>fix(compliance-skill): 修复 DB 连接串正则与跨文件一致性C1/I1/I2/I3/I4/M2@刘焱)</li>
<li>fix(collaborator): 修复 change-role/batch-role 请求体(@刘焱)</li>
<li>fix(branch): 修复保护分支接口路径与列表输出(@刘焱)</li>
<li>fix(output): 表头取所有行字段并集并固定核心列顺序(@刘焱)</li>
<li>fix(interactive): 命令面板选中带可选参数的命令也弹出表单(@刘焱)</li>
<li>fix(file): 移除 +tree 无效的 --recursive flag@刘焱)</li>
<li>fix(file): 修复文件管理命令的端点和参数问题(@刘焱)</li>
<li>fix(output): 本地构造的 map slice 也渲染为表格,不再显示 [N items]@刘焱)</li>
<li>fix(tag): tag +view 改用列表过滤GitLink 无单标签 API 端点(@刘焱)</li>
<li>fix(interactive): initialize RuntimeContext via NewRuntimeContext to prevent nil-Client panic@刘焱)</li>
<li>fix(interactive): trigger command palette immediately on '/' keypress@刘焱)</li>
<li>fix(interactive): correct Esc behavior and direct-exec for optional flags@刘焱)</li>
<p></ol></p>
<p><strong>占比:</strong> 15%</p>
<h3>📝 文档51</h3>
<ol><li>docs: 三份报告统一转为 Word 格式(@赵昌)</li>
<li>docs: 更新报告覆盖全部成员贡献(@赵昌)</li>
<li>docs: 更新工作日志(文档清理 & 技术债务优化)(@赵昌)</li>
<li>docs: 更新工作日志技术债务状态(@赵昌)</li>
<li>docs: 统一新需求构思报告和变更影响分析及测试报告(@赵昌)</li>
<li>docs: 添加子任务三/四工作日志(@赵昌)</li>
<li>docs: 添加子任务三/四交接文档(@赵昌)</li>
<li>docs: enrich demo page with detailed AI analysis and scoring@赵昌)</li>
<li>docs: update demo page with AI analysis outputs and scoring@赵昌)</li>
<li>docs(demo): 演示页新增许可证合规检查与新人引导交互流程(@刘焱)</li>
<li>docs: add interactive demo page for skills showcase@赵昌)</li>
<li>docs: add release notes workflow example@赵昌)</li>
<li>docs(plans): 项目级 Skill 集成实现计划(@刘焱)</li>
<li>docs(specs): 项目级 Skill 集成设计Claude Code 兼容)(@刘焱)</li>
<li>docs(skills): 真实验证回填(@刘焱)</li>
<li>docs(skills-readme): 概览表补 compliance 与 newcomer-guide@刘焱)</li>
<li>docs(newcomer-skill): 示例加入去重检查与批量场景(@刘焱)</li>
<li>docs(newcomer-skill): 新增 REFERENCE命令/字段/标签变体/幂等规则)(@刘焱)</li>
<li>docs(compliance-skill): 新增端到端合规检查示例(@刘焱)</li>
<li>docs(compliance-skill): REFERENCE 增补敏感信息扫描章节(@刘焱)</li>
<li>docs(plans): GitLink Skills 丰富与完善实现计划(@刘焱)</li>
<li>docs(specs): GitLink Skills 丰富与完善设计规格(@刘焱)</li>
<li>docs: add comprehensive Chinese comments and mark bug fixes (P1-P4)@s2_cc</li>
<li>docs(repo): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(pr): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(issue): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(attachment): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(dataset): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(template): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(ci): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(search): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(org): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(util): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(sshkey): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(label): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(commit): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(file): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(milestone): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(release): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(collaborator): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(tag): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(branch): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(wiki): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(user): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(snippet): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(webhook): 子命令描述和注释中文化(@刘焱)</li>
<li>docs(shortcuts): 给每个命令组添加中文注释和中文描述(@刘焱)</li>
<li>docs: add interactive REPL implementation plan@刘焱)</li>
<li>docs: add interactive REPL command palette design spec@刘焱)</li>
<li>docs: add workflow examples for issue-triage, project-health, newcomer-guide@赵昌)</li>
<li>docs: update report - remove hook-runner, update webhook section@赵昌)</li>
<p></ol></p>
<p><strong>占比:</strong> 51%</p>
<h3>✅ 测试1</h3>
<ol><li>test(interactive): smoke-test all registered commands execute without panic@刘焱)</li>
<p></ol></p>
<p><strong>占比:</strong> 1%</p>
<h3>🔧 工程配置3</h3>
<ol><li>chore: 删除多余的 demo 文件(@赵昌)</li>
<li>chore: 清理多余的场景文档目录(@赵昌)</li>
<li>chore: add bubbletea, bubbles, huh dependencies@刘焱)</li>
<p></ol></p>
<p><strong>占比:</strong> 3%</p>
<h3>📦 其他变更8</h3>
<ol><li>refine: 优化演示页面布局和结果展示(@赵昌)</li>
<li>Merge remote-tracking branch 'origin/master'@s2_cc</li>
<li>Merge branch 'z2cc'@s2_cc</li>
<li>enhance: enrich skill outputs with data analysis and scoring logic@赵昌)</li>
<li>remove probe@刘焱)</li>
<li>probe@liuyan688</li>
<li>添加Python示例@wqer</li>
<li>merge: integrate hook-runner into webhook commands@赵昌)</li>
<p></ol></p>
<p><strong>占比:</strong> 8%</p>
<h3>📈 统计汇总</h3>
<div class="table-wrap"><table><thead><tr><th>类别</th><th>数量</th><th>占比</th></tr></thead><tbody><tr><td>✨ 新功能</td><td>22</td><td>22%</td></tr><tr><td>🐛 Bug 修复</td><td>15</td><td>15%</td></tr><tr><td>📝 文档</td><td>51</td><td>51%</td></tr><tr><td>♻️ 代码重构</td><td>0</td><td>0%</td></tr><tr><td>⚡ 性能优化</td><td>0</td><td>0%</td></tr><tr><td class="cell-ok">✅ 测试</td><td>1</td><td>1%</td></tr><tr><td>🔧 工程配置</td><td>3</td><td>3%</td></tr><tr><td>⏪ 回退</td><td>0</td><td>0%</td></tr><tr><td>📦 其他变更</td><td>8</td><td>8%</td></tr></tbody></table></div>
<p>---</p>
<p>*自动生成时间2026-06-30 02:49:09*</p>
</div>
<div class="footer">
Powered by gitlink-cli · 数据来源于 GitLink 平台
</div>
</div>
</body>
</html>

View File

@ -1,240 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>社区健康度周报</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif;
background: #f1f5f9;
color: #1e293b;
line-height: 1.7;
}
.page {
max-width: 900px;
margin: 0 auto;
padding: 0 20px 60px;
}
.header-card {
background: linear-gradient(135deg, #1e293b, #334155);
color: white;
border-radius: 16px;
padding: 32px 40px;
margin: 24px 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 20px;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
}
.header-card h1 {
font-size: 22px;
font-weight: 600;
line-height: 1.3;
}
.header-card .meta {
font-size: 13px;
color: #94a3b8;
margin-top: 6px;
}
.card {
background: white;
border-radius: 12px;
padding: 24px 28px;
margin-bottom: 16px;
box-shadow: 0 1px 4px rgba(0,0,0,0.04);
border: 1px solid #e2e8f0;
}
.card h2 {
font-size: 16px;
font-weight: 600;
color: #0f172a;
margin-bottom: 14px;
padding-bottom: 8px;
border-bottom: 2px solid #f1f5f9;
display: flex;
align-items: center;
gap: 8px;
}
.card h3 {
font-size: 14px;
font-weight: 600;
color: #334155;
margin: 16px 0 8px;
}
.card h4 {
font-size: 13px;
font-weight: 600;
color: #475569;
margin: 12px 0 6px;
}
.card p {
font-size: 14px;
color: #475569;
margin-bottom: 8px;
}
.card p:last-child { margin-bottom: 0; }
.card code {
background: #f1f5f9;
padding: 1px 6px;
border-radius: 4px;
font-size: 13px;
font-family: 'Cascadia Code', 'Fira Code', monospace;
color: #0f172a;
}
.card strong {
color: #0f172a;
}
.score-section {
text-align: center;
padding: 8px 0;
}
.score-ring {
display: inline-block;
}
.score-label {
font-size: 18px;
font-weight: 600;
margin-top: 4px;
}
.table-wrap {
overflow-x: auto;
margin: 10px 0;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
th {
background: #f8fafc;
font-weight: 600;
text-align: left;
padding: 10px 12px;
border-bottom: 2px solid #e2e8f0;
color: #475569;
white-space: nowrap;
}
td {
padding: 9px 12px;
border-bottom: 1px solid #f1f5f9;
color: #334155;
}
tr:last-child td { border-bottom: none; }
tr:hover td { background: #f8fafc; }
.cell-ok { color: #16a34a; font-weight: 500; }
.cell-fail { color: #dc2626; }
.cell-green { color: #16a34a; }
.cell-yellow { color: #ca8a04; }
.cell-red { color: #dc2626; }
.cell-warn { color: #ea580c; }
ol {
padding-left: 20px;
margin: 8px 0;
}
ol li {
font-size: 14px;
color: #475569;
padding: 4px 0;
list-style-position: outside;
}
li::marker {
font-weight: 600;
color: #3b82f6;
}
.code-block {
background: #0f172a;
color: #e2e8f0;
padding: 16px 20px;
border-radius: 8px;
font-size: 13px;
overflow-x: auto;
margin: 12px 0;
line-height: 1.5;
font-family: 'Cascadia Code', 'Fira Code', monospace;
}
.footer {
text-align: center;
padding: 24px;
color: #94a3b8;
font-size: 12px;
}
@media (max-width: 640px) {
.page { padding: 0 12px 40px; }
.header-card { padding: 20px; flex-direction: column; text-align: center; }
.header-card h1 { font-size: 18px; }
.card { padding: 16px; }
}
@media print {
body { background: white; }
.header-card { break-inside: avoid; }
.card { break-inside: avoid; box-shadow: none; border: 1px solid #e2e8f0; }
}
</style>
</head>
<body>
<div class="page">
<div class="header-card">
<div>
<h1>社区健康度周报</h1>
<div class="meta">生成时间2026/6/30 10:49:09</div>
</div>
<div class="score-section">
<div class="score-ring">
<svg viewBox="0 0 120 120" width="140" height="140">
<circle cx="60" cy="60" r="52" fill="none" stroke="#e2e8f0" stroke-width="8"/>
<circle cx="60" cy="60" r="52" fill="none" stroke="#ef4444" stroke-width="8"
stroke-dasharray="326.7256359733385" stroke-dashoffset="212.37166338267005"
transform="rotate(-90, 60, 60)" stroke-linecap="round"
style="transition: stroke-dashoffset 1.5s ease-in-out;"/>
<text x="60" y="50" text-anchor="middle" font-size="32" font-weight="700" fill="#1e293b">3.5</text>
<text x="60" y="72" text-anchor="middle" font-size="13" fill="#64748b">/ 10</text>
</svg>
</div>
<div class="score-label">🔴 堪忧</div>
</div>
</div>
<div class="card report-content">
<h1>📊 社区健康度周报</h1>
<p><strong>报告日期:</strong> 2026-06-30</p>
<p><strong>项目:</strong> z2_cc/gitlink-cli</p>
<p><strong>综合评分:</strong> 3.5/10 🔴 堪忧</p>
<h2>一、本周概览</h2>
<div class="table-wrap"><table><thead><tr><th>指标</th><th>数据</th><th>状态</th></tr></thead><tbody><tr><td>Issue 总数</td><td>21</td><td></td></tr><tr><td>打开中</td><td>17</td><td class="cell-red">🔴</td></tr><tr><td>已关闭</td><td>4</td><td class="cell-red">🔴</td></tr><tr><td>关闭率</td><td>19%</td><td class="cell-red">🔴 偏低</td></tr><tr><td>PR 总数</td><td>2</td><td></td></tr><tr><td>打开中</td><td>0</td><td></td></tr><tr><td>已合并</td><td>0</td><td class="cell-red">🔴</td></tr><tr><td>合并率</td><td>0%</td><td class="cell-red">🔴 偏低</td></tr><tr><td>贡献者数</td><td>1 人</td><td class="cell-red">🔴</td></tr><tr><td>平均响应时间</td><td>21.5 天</td><td class="cell-yellow">🟡 正常</td></tr></tbody></table></div>
<h2>二、Issue 分析评分3/10</h2>
<ol><li>总 Issue 数21打开 17 / 关闭 4</li>
<li>关闭率19% ⚠️ 偏低</li>
<li>平均响应时间21.5 天</li>
<li><strong>分析:</strong> Issue 关闭率偏低,建议定期进行 Issue 清理和回复。</li>
<p></ol></p>
<h2>三、PR 分析评分3/10</h2>
<ol><li>总 PR 数2打开 0 / 合并 0</li>
<li>合并率0% ⚠️ 偏低</li>
<li><strong>分析:</strong> PR 合并率偏低,建议加快代码审查和合并速度。</li>
<p></ol></p>
<h2>四、贡献者活跃度评分3/10</h2>
<ol><li>近 50 次提交贡献者1 人</li>
<li><strong>分析:</strong> 单人维护 🔴</li>
<p></ol></p>
<h2>五、改进建议</h2>
<ol><li data-index="1">Issue 关闭率偏低,建议定期清理积压 Issue</li>
<li data-index="2">PR 合并率偏低,建议加快 PR 处理速度</li>
<li data-index="3">贡献者较少,建议标记 good-first-issue 吸引新贡献者</li>
<p></ol></p>
<p>---</p>
<p>*数据采集时间2026-06-30 02:49:08*</p>
<p>*AI 生成,建议人工复核*</p>
</div>
<div class="footer">
Powered by gitlink-cli · 数据来源于 GitLink 平台
</div>
</div>
</body>
</html>

View File

@ -1,56 +0,0 @@
#!/bin/bash
# ================================================================
# 社区运营自动化 — 全流程串联脚本
# 功能:依次执行 Issue 分拣 → 周报生成 → Release Notes
# 使用bash community-ops-full.sh <owner> <repo>
# 环境变量DRY_RUN=true|false (默认 true)
# ================================================================
set -e
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "============================================"
echo " 社区运营自动化"
echo " Target: $OWNER/$REPO"
echo " DRY_RUN: $DRY_RUN"
echo " 开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================"
echo ""
# Phase 1
echo "▸ Phase 1/3: Issue 自动分拣"
bash "$SCRIPT_DIR/01-issue-triage.sh" "$OWNER" "$REPO"
echo ""
# Phase 2
echo "▸ Phase 2/3: 社区周报生成"
bash "$SCRIPT_DIR/02-weekly-health-report.sh" "$OWNER" "$REPO"
echo ""
# Phase 3
echo "▸ Phase 3/3: 自动 Release Notes"
bash "$SCRIPT_DIR/03-auto-release-notes.sh" "$OWNER" "$REPO"
echo ""
# 生成 HTML 可视化报告
echo "▸ 生成 HTML 可视化报告..."
SHARED_SCRIPT="$SCRIPT_DIR/../../gitlink-shared/scripts/md-to-html.js"
if [ -f "$OUTPUT_DIR/weekly-health-report.md" ]; then
node "$SHARED_SCRIPT" "$OUTPUT_DIR/weekly-health-report.md" 2>/dev/null || true
fi
for rn in "$OUTPUT_DIR"/release-notes-*.md; do
[ -f "$rn" ] && node "$SHARED_SCRIPT" "$rn" 2>/dev/null || true
done
echo ""
echo "============================================"
echo " 全流程完成"
echo " 结束时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo " 📄 Markdown: $OUTPUT_DIR/"
echo " 🌐 HTML: 已生成"
echo "============================================"

View File

@ -1,120 +0,0 @@
const fs = require('fs');
const path = require('path');
const dir = process.argv[2] || '_output';
function readJSON(name) {
try { return JSON.parse(fs.readFileSync(path.join(dir, name), 'utf8')); }
catch(e) { return {data: {}}; }
}
// ==== 读取数据 ====
const repoInfo = readJSON('repo-info.json').data || {};
const issuesAll = readJSON('issues-all.json').data || {};
const issuesOpen = readJSON('issues-open.json').data || {};
const issuesClosed = readJSON('issues-closed.json').data || {};
const prsAll = readJSON('prs-all.json').data || {};
const prsMerged = readJSON('prs-merged.json').data || {};
const milestones = readJSON('milestones.json').data || {};
// ==== Issue 分析 ====
const issueList = issuesAll.issues || [];
const openCount = issuesOpen.issues ? issuesOpen.issues.length : (issuesAll.opened_count || 0);
const closedCount = issuesAll.closed_count || 0;
const totalIssues = openCount + closedCount || issueList.length || 0;
const closeRate = totalIssues > 0 ? Math.round(closedCount / totalIssues * 100) : 0;
// 响应时间:计算 closed list 中 created_at 到现在的平均天数
let totalResponseDays = 0;
let responseCount = 0;
(issuesClosed.issues || []).forEach(i => {
if (i.created_at) {
const created = new Date(i.created_at.replace(' ', 'T'));
if (!isNaN(created.getTime())) {
totalResponseDays += (Date.now() - created.getTime()) / (24 * 60 * 60 * 1000);
responseCount++;
}
}
});
const avgResponseDays = responseCount > 0 ? Math.round(totalResponseDays / responseCount * 10) / 10 : 0;
const closeRateScore = closeRate > 80 ? 10 : closeRate > 50 ? 7 : closeRate > 30 ? 5 : 3;
const responseScore = avgResponseDays < 2 ? 10 : avgResponseDays < 7 ? 7 : 3;
// ==== PR 分析 ====
const prList = prsAll.pulls || [];
let prOpen = 0, prMergedCount = 0;
prList.forEach(p => {
const s = (p.status || '').toLowerCase();
if (s === 'open' || s === 'opened') prOpen++;
else if (s === 'merged') prMergedCount++;
});
const totalPRs = repoInfo.pull_requests_count || prList.length || 0;
const mergeRate = totalPRs > 0 ? Math.round(prMergedCount / totalPRs * 100) : 0;
const mergeRateScore = mergeRate > 70 ? 10 : mergeRate > 40 ? 7 : 3;
// ==== 贡献者活跃度 ====
const contribCount = repoInfo.contributor_users_count || 0;
const contribScore = contribCount >= 5 ? 10 : contribCount >= 2 ? 7 : 3;
// ==== 综合评分 ====
const healthScore = Math.round((closeRateScore * 0.30 + mergeRateScore * 0.30 + contribScore * 0.25 + 6 * 0.15) * 10) / 10;
const healthLevel = healthScore >= 9 ? '🟢 优秀' : healthScore >= 7 ? '🟢 良好' : healthScore >= 5 ? '🟡 一般' : '🔴 堪忧';
// ==== 改进建议 ====
const suggestions = [];
if (closeRate < 50) suggestions.push('Issue 关闭率偏低,建议定期清理积压 Issue');
if (mergeRate < 50 && totalPRs > 0) suggestions.push('PR 合并率偏低,建议加快 PR 处理速度');
if (contribCount < 3) suggestions.push('贡献者较少,建议标记 good-first-issue 吸引新贡献者');
if (suggestions.length === 0) suggestions.push('项目状态良好,继续保持');
const now = new Date();
const dateStr = now.toISOString().slice(0, 10);
const timeStr = now.toISOString().slice(0, 19).replace('T', ' ');
// ==== 生成周报 ====
const report = `# 📊 社区健康度周报
**报告日期** ${dateStr}
**项目** z2_cc/gitlink-cli
**综合评分** ${healthScore}/10 ${healthLevel}
## 本周概览
| 指标 | 数据 | 状态 |
|------|------|------|
| Issue 总数 | ${totalIssues} | |
| 打开中 | ${openCount} | ${openCount > 10 ? '🔴' : openCount > 5 ? '🟡' : '🟢'} |
| 已关闭 | ${closedCount} | ${closeRate > 50 ? '🟢' : '🔴'} |
| 关闭率 | ${closeRate}% | ${closeRateScore >= 7 ? '🟢 良好' : closeRateScore >= 5 ? '🟡 一般' : '🔴 偏低'} |
| PR 总数 | ${totalPRs} | |
| 打开中 | ${prOpen} | |
| 已合并 | ${prMergedCount} | ${mergeRate > 50 ? '🟢' : '🔴'} |
| 合并率 | ${mergeRate}% | ${mergeRateScore >= 7 ? '🟢 良好' : '🔴 偏低'} |
| 贡献者数 | ${contribCount} | ${contribScore >= 7 ? '🟢' : '🔴'} |
| 平均响应时间 | ${avgResponseDays} | ${responseScore >= 7 ? '🟢 及时' : '🟡 正常'} |
## Issue 分析评分${closeRateScore}/10
- Issue ${totalIssues}打开 ${openCount} / 关闭 ${closedCount}
- 关闭率${closeRate}%${closeRate > 50 ? ' ✅ 良好' : ' ⚠️ 偏低'}
- 平均响应时间${avgResponseDays}
- **分析** ${closeRate > 50 ? '社区 Issue 处理效率良好。' : 'Issue 关闭率偏低,建议定期进行 Issue 清理和回复。'}
## PR 分析评分${mergeRateScore}/10
- PR ${totalPRs}打开 ${prOpen} / 合并 ${prMergedCount}
- 合并率${mergeRate}%${mergeRate > 50 ? ' ✅ 良好' : ' ⚠️ 偏低'}
- **分析** ${mergeRate > 50 ? 'PR 合并效率良好,团队协作顺畅。' : 'PR 合并率偏低,建议加快代码审查和合并速度。'}
## 贡献者活跃度评分${contribScore}/10
- 50 次提交贡献者${contribCount}
- **分析** ${contribCount >= 5 ? '团队协作活跃 🟢' : contribCount >= 2 ? '少量贡献者 🟡' : '单人维护 🔴'}
## 改进建议
${suggestions.map((s, i) => `${i + 1}. ${s}`).join('\n')}
---
*数据采集时间${timeStr}*
*AI 生成建议人工复核*
`;
fs.writeFileSync(path.join(dir, 'weekly-health-report.md'), report, 'utf8');
console.log('周报已生成');

View File

@ -1,121 +0,0 @@
const fs = require('fs');
const path = require('path');
const dir = process.argv[2] || '_output';
const lastTag = process.argv[3] || 'v0.0.0';
// 读提交日志(优先 git log后备 API JSON
const logFile = path.join(dir, `commits-since-${lastTag}.log`);
const statsFile = path.join(dir, `stats-since-${lastTag}.log`);
const apiFile = path.join(dir, 'commits-api.json');
let commits = [];
if (fs.existsSync(logFile)) {
const content = fs.readFileSync(logFile, 'utf8');
commits = content.trim().split('\n').filter(Boolean).map(line => {
const parts = line.split('|');
return { sha: parts[0] || '', msg: parts[1] || '', author: parts[2] || '', date: parts[3] || '' };
});
console.log('✓ 从 git log 读取 ' + commits.length + ' 条提交');
} else if (fs.existsSync(apiFile)) {
try {
const raw = JSON.parse(fs.readFileSync(apiFile, 'utf8'));
const list = raw.data && raw.data.commits ? raw.data.commits : (raw.data || []);
commits = list.map(c => ({
sha: c.sha || '',
msg: (c.commit_message || '').replace(/\n.*$/, '').trim(),
author: (c.author && c.author.login) || (c.committer && c.committer.login) || '',
date: c.commit_time ? new Date(c.commit_time * 1000).toISOString().slice(0, 10) : ''
}));
console.log('✓ 从 API 读取 ' + commits.length + ' 条提交');
} catch(e) {
console.log('⚠ API 数据解析失败: ' + e.message);
}
}
// 按 Conventional Commits 分类
const categories = { feat: [], fix: [], docs: [], refactor: [], perf: [], test: [], chore: [], revert: [], other: [] };
const typeLabels = {
feat: '✨ 新功能', fix: '🐛 Bug 修复', docs: '📝 文档',
refactor: '♻️ 代码重构', perf: '⚡ 性能优化', test: '✅ 测试',
chore: '🔧 工程配置', revert: '⏪ 回退', other: '📦 其他变更'
};
commits.forEach(c => {
const m = c.msg.match(/^(\w+)(\([^)]+\))?:/);
const type = m ? m[1] : 'other';
if (categories[type]) categories[type].push(c);
else categories.other.push(c);
});
const totalCommits = commits.length;
const authors = new Set(commits.map(c => c.author).filter(Boolean));
const contributorCount = authors.size;
// 统计各类型数量
const counts = {};
Object.keys(categories).forEach(k => counts[k] = categories[k].length);
const classifiedTotal = Object.values(counts).reduce((a, b) => a + b, 0);
// 统计文件变更(兼容中英文 Git 输出)
let totalFiles = 0, additions = 0, deletions = 0;
if (fs.existsSync(statsFile)) {
const stats = fs.readFileSync(statsFile, 'utf8');
const lines = stats.split('\n');
lines.forEach(line => {
// 匹配 "X file(s) changed" 或 "X 个文件已更改"
const fm = line.match(/(\d+)\s*(file|个文件)/i);
if (fm) totalFiles += parseInt(fm[1]) || 0;
// 匹配 "Y insertion" 或 "Y 行插入"
const am = line.match(/(\d+)\s*(insertion|行插入)/i);
if (am) additions += parseInt(am[1]) || 0;
// 匹配 "Z deletion" 或 "Z 行删除"
const dm = line.match(/(\d+)\s*(deletion|行删除)/i);
if (dm) deletions += parseInt(dm[1]) || 0;
});
}
// 语义化版本推荐
const hasBreaking = commits.some(c => c.msg.includes('BREAKING CHANGE') || c.msg.includes('!'));
const hasFeat = counts.feat > 0;
const oldVer = lastTag.match(/v?(\d+)\.(\d+)\.(\d+)/);
let newVer = 'v0.1.0';
if (oldVer) {
const [_, major, minor, patch] = oldVer.map(Number);
if (hasBreaking) newVer = `v${major + 1}.0.0`;
else if (hasFeat) newVer = `v${major}.${minor + 1}.0`;
else newVer = `v${major}.${minor}.${patch + 1}`;
}
// 生成 Release Notes
const sections = ['feat', 'fix', 'docs', 'refactor', 'perf', 'test', 'chore', 'revert', 'other']
.filter(t => counts[t] > 0)
.map(t => {
const items = categories[t].map(c => `- ${c.msg}@${c.author || 'unknown'}`).join('\n');
const pct = totalCommits > 0 ? Math.round(counts[t] / totalCommits * 100) : 0;
return `### ${typeLabels[t]}${counts[t]}\n\n${items}\n\n**占比:** ${pct}%`;
}).join('\n\n');
const notes = `## ${newVer} (${new Date().toISOString().slice(0, 10)})
### 📊 版本概览
- 基于上一版本${lastTag}
- 包含 **${totalCommits}** 次提交
- 涉及 **${totalFiles || '—'}** 个文件
- 新增 **${additions || '—'}** / 删除 **${deletions || '—'}**
- 贡献者**${contributorCount}**
${totalCommits > 0 ? sections : '(暂无提交记录,请确认 tag 名称正确)'}
### 📈 统计汇总
| 类别 | 数量 | 占比 |
|------|------|------|
${Object.entries(typeLabels).map(([k, label]) => `| ${label} | ${counts[k]} | ${totalCommits > 0 ? Math.round(counts[k] / totalCommits * 100) : 0}% |`).join('\n')}
---
*自动生成时间${new Date().toISOString().slice(0, 19).replace('T', ' ')}*
`;
fs.writeFileSync(path.join(dir, `release-notes-${newVer}.md`), notes, 'utf8');
console.log('Release Notes 已生成: ' + path.join(dir, `release-notes-${newVer}.md`));
console.log(`版本推荐: ${lastTag}${newVer}${hasBreaking ? 'BREAKING': hasFeat ? '有新功能': '修复'}`);

View File

@ -52,6 +52,56 @@ gitlink-cli api GET /:owner/:repo/contributors --format json
---
## 敏感信息扫描
### 高危文件类型
| 类别 | 文件 |
|------|------|
| 配置文件 | `.env*`、`config.yaml/yml/json`、`settings.py`、`application.properties` |
| 证书/密钥 | `*.pem`、`*.key`、`*.p12`、`*.pfx`、`*.crt`、`*.cer` |
| SSH 密钥 | `id_rsa`、`id_ed25519`、`id_ecdsa`、`id_dsa` |
| 数据库配置 | `database.yml`、`db.conf`、`datasource.properties` |
| CI/部署 | `.gitlink-ci.yml`、`.trustie-pipeline.yml`、`.github/workflows/*.yml`、`docker-compose.yml` |
### 敏感信息特征正则
| 类型 | 正则 |
|------|------|
| AWS Access Key | `AKIA[0-9A-Z]{16}` |
| GitHub Token | `ghp_[A-Za-z0-9]{36}` |
| GitLab/Gitea Token (glpat-) | `glpat-[A-Za-z0-9\-_]{20}` |
| JWT | `eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}` |
| 私钥头 | `-----BEGIN (RSA \|EC \|DSA \|OPENSSH \|PGP )?PRIVATE KEY-----` |
| 通用密钥赋值 | `(?i)(password\|passwd\|pwd\|secret\|token\|apikey\|api_key\|access_key\|private_key)\s*[:=]\s*['"]?[^[:space:]'"]{8,}` |
| 数据库连接串 | `(mysql\|postgres\|postgresql\|mongodb\|redis)://[^:[:space:]]+:[^@[:space:]]+@[^[:space:]]+` |
| 内网/私有 IP | `(192\.168\.\|10\.\d{1,3}\.\|172\.(1[6-9]\|2\d\|3[01])\.\|127\.0\.0\.1)` |
| Slack Token | `xox[baprs]-[A-Za-z0-9-]{10,}` |
### 扫描命令git
```bash
# 克隆后批量扫描工作树
git clone https://www.gitlink.org.cn/<owner>/<repo>.git /tmp/<repo>-scan
cd /tmp/<repo>-scan
git grep -nE 'AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|glpat-[A-Za-z0-9\-_]{20}|-----BEGIN .*PRIVATE KEY-----' HEAD
git grep -niE '(password|passwd|pwd|secret|token|apikey|api_key)\s*[:=]' HEAD -- '*.env*' '*.yml' '*.yaml' '*.json' '*.py' '*.conf'
# 历史残留(已删除但仍存在)
git log --all -p -S 'AKIA' --oneline | head
```
### 风险分级
| 等级 | 描述 | 处理建议 |
|------|------|---------|
| 🔴 严重 | 真实密钥/Token/私钥暴露 | 立即撤销密钥;从 Git 历史清除 |
| 🟠 高 | 密码 / 数据库连接串硬编码 | 替换为环境变量;清理历史提交 |
| 🟡 中 | 内网地址 / 测试账号泄露 | 评估影响范围,按需处理 |
| 🟢 低 | 疑似敏感但可能是示例/占位 | 人工确认后决定是否处理 |
---
## 常见许可证识别
通过读取 LICENSE 文件内容,关键字匹配识别许可证类型:
@ -110,6 +160,7 @@ gitlink-cli api GET /:owner/:repo/contributors --format json
| CI 配置 | 检查 `.trustie-pipeline.yml` / `.github/workflows` 等 | 存在即通过 |
| 源文件版权头 | 采样检查源码文件前 5 行 | 50% 以上文件有版权声明 |
| 依赖配置文件 | 检查 package.json / go.mod / Cargo.toml 等 | 存在即通过 |
| 敏感信息 | `git clone` + `git grep` 批量扫描 | 无 🔴/🟠 级命中 |
---
@ -135,6 +186,11 @@ gitlink-cli api GET /:owner/:repo/contributors --format json
| # | 建议 | 说明 |
|---|------|------|
### 🔴 敏感信息扫描
| 风险 | 文件 | 行 | 内容特征 | 建议 |
|------|------|----|---------|------|
| 🟠 高 | config/database.yml | 12 | password: prod_db_pass_123 | 改用环境变量 ${DB_PASSWORD} |
### 📊 合规评分
| 维度 | 状态 | 评分 |
|------|:----:|:----:|
@ -143,6 +199,7 @@ gitlink-cli api GET /:owner/:repo/contributors --format json
| 📦 依赖合规 | ✅/⚠️/❌ | ☆☆☆☆☆ |
| 🔒 安全策略 | ✅/⚠️/❌ | ☆☆☆☆☆ |
| 📖 项目文档 | ✅/⚠️/❌ | ☆☆☆☆☆ |
| 🔒 敏感信息管控 | ✅/⚠️/❌ | ☆☆☆☆☆ |
**总体合规评分:<分数>/100**
```
@ -158,3 +215,5 @@ gitlink-cli api GET /:owner/:repo/contributors --format json
5. MulanPSL-2.0 是中国广泛使用的开源许可证,在 GitLink 平台上常见
6. 版权声明检查为采样性质100% 覆盖需专业扫描工具
7. RAW API 返回的某些文件可能包含完整内容(`replace_content` 字段)
8. 敏感信息扫描结果仅供参考,建议发布前用 gitleaks/trufflehog 等专业工具二次确认
9. **Windows Git BashMSYS路径坑**`gitlink-cli api GET /:owner/:repo/raw/...` 等 raw `api` 调用,其 `/...` 参数在 MSYS 下会被自动转换为 Windows 路径(如 `D:/Git/...`),导致请求落到 GitLink 首页返回 HTML 而非文件内容。解决:命令前加 `MSYS_NO_PATHCONV=1`,或改用 PowerShell/cmd 执行。批量扫描走 `git clone` + `git grep` 路径不受此影响。

View File

@ -4,7 +4,7 @@ version: 1.0.0
description: "开源合规检查:扫描仓库许可证、版权声明、依赖合规性,生成合规报告与修复建议。当用户需要检查项目合规状态、许可证兼容性或准备开源发布时触发。"
metadata:
requires:
bins: ["gitlink-cli"]
bins: ["gitlink-cli", "git"]
cliHelp: "gitlink-cli repo --help"
---
@ -28,6 +28,7 @@ metadata:
| 依赖合规 | 第三方依赖许可证兼容性 | 🔴 |
| 安全策略 | SECURITY.md、安全披露流程 | 🟡 |
| 贡献者协议 | CLA / DCO 要求 | 🔵 |
| 敏感信息扫描 | 密钥/Token/凭据/私钥泄露 | 🔴 / 🟠 |
---
@ -206,6 +207,88 @@ gitlink-cli api GET /:owner/:repo/raw/master/src/main.py
---
## 工作流 4敏感信息扫描
**场景**发布前检查仓库是否泄露密钥、Token、密码、私钥等敏感信息。这是合规检查的关键一环——一旦真实凭据进入 Git 历史,撤销和清理成本极高。
### 扫描策略(混合)
- **小数据 / 远程无 clone**:用 `gitlink-cli api` 取仓库元信息、LICENSE、依赖声明文件、个别高危文件。
- **批量扫描全仓库**:用 `git clone` + `git grep` / `git log -S`。逐文件 `api raw` 对真实仓库不现实,`git grep` 单次扫描整个工作树。
### 高危文件类型(优先扫描)
| 类别 | 文件 |
|------|------|
| 配置文件 | `.env`、`.env.local`、`.env.production`、`config.yaml/yml/json`、`settings.py`、`application.properties` |
| 证书/密钥 | `*.pem`、`*.key`、`*.p12`、`*.pfx`、`*.crt`、`*.cer` |
| SSH 密钥 | `id_rsa`、`id_ed25519`、`id_ecdsa`、`id_dsa` |
| 数据库配置 | `database.yml`、`db.conf`、`datasource.properties` |
| CI/部署 | `.gitlink-ci.yml`、`.trustie-pipeline.yml`、`.github/workflows/*.yml`、`docker-compose.yml` |
### 敏感信息特征(正则)
| 类型 | 正则 |
|------|------|
| AWS Access Key | `AKIA[0-9A-Z]{16}` |
| GitHub Token | `ghp_[A-Za-z0-9]{36}` |
| GitLab/Gitea Token (glpat-) | `glpat-[A-Za-z0-9\-_]{20}` |
| JWT | `eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}` |
| 私钥头 | `-----BEGIN (RSA \|EC \|DSA \|OPENSSH \|PGP )?PRIVATE KEY-----` |
| 通用密钥赋值 | `(?i)(password\|passwd\|pwd\|secret\|token\|apikey\|api_key\|access_key\|private_key)\s*[:=]\s*['"]?[^[:space:]'"]{8,}` |
| 数据库连接串 | `(mysql\|postgres\|postgresql\|mongodb\|redis)://[^:[:space:]]+:[^@[:space:]]+@[^[:space:]]+` |
| 内网/私有 IP | `(192\.168\.\|10\.\d{1,3}\.\|172\.(1[6-9]\|2\d\|3[01])\.\|127\.0\.0\.1)` |
| Slack Token | `xox[baprs]-[A-Za-z0-9-]{10,}` |
### 风险分级
| 等级 | 描述 | 处理建议 |
|------|------|---------|
| 🔴 严重 | 真实密钥/Token/私钥暴露 | 立即撤销密钥;从 Git 历史清除 |
| 🟠 高 | 密码 / 数据库连接串硬编码 | 替换为环境变量;清理历史提交 |
| 🟡 中 | 内网地址 / 测试账号泄露 | 评估影响范围,按需处理 |
| 🟢 低 | 疑似敏感但可能是示例/占位 | 人工确认后决定是否处理 |
### 执行步骤
```bash
# 1. 仓库元信息api无需 clone
gitlink-cli repo +info --owner <owner> --repo <repo> --format json
# 2. LICENSE / 依赖声明文件api文件少且明确
gitlink-cli api GET /:owner/:repo/raw/master/LICENSE
gitlink-cli api GET /:owner/:repo/raw/master/go.mod # 按主语言选择
# 3. 批量敏感信息扫描(需 clone
git clone https://www.gitlink.org.cn/<owner>/<repo>.git /tmp/<repo>-scan
cd /tmp/<repo>-scan
git ls-tree -r --name-only HEAD # 确定扫描范围
# 4. 对高危特征做正则扫描(多模式分别跑,便于归类)
git grep -nE 'AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|glpat-[A-Za-z0-9\-_]{20}|-----BEGIN .*PRIVATE KEY-----' HEAD
git grep -niE '(password|passwd|pwd|secret|token|apikey|api_key)\s*[:=]' HEAD -- '*.env*' '*.yml' '*.yaml' '*.json' '*.py' '*.conf'
git grep -nE '(mysql|postgres|mongodb|redis)://[^:[:space:]]+:[^@[:space:]]+@' HEAD
# 5可选检查 Git 历史中已删除但仍残留的敏感信息
git log --all -p -S 'AKIA' --oneline | head
```
> **降级**:若用户无本地 clone 条件、仓库极小,可仅用 Step 1-2 + 对少量高危文件逐个 `api raw` 扫描,并在报告中注明"未做全量扫描"。
### 输出(并入合规报告)
在合规报告的"可选优化"之后、"合规评分"之前,新增一节:
```markdown
### 🔴 敏感信息扫描
| 风险 | 文件 | 行 | 内容特征 | 建议 |
|------|------|----|---------|------|
| 🟠 高 | config/database.yml | 12 | password: prod_db_pass_123 | 改用环境变量 ${DB_PASSWORD} |
```
并在"合规评分"维度表新增一行 `| 🔒 敏感信息管控 | ✅ / ⚠️ / ❌ | ☆☆☆☆☆ |`,纳入总分计算。
## Raw API 参考
```bash
@ -229,3 +312,4 @@ gitlink-cli api GET /:owner/:repo/contributors --format json
- 不同语言的依赖管理文件格式不同,需要根据项目主语言选择对应的依赖文件分析
- 版权声明检查是采样性的100% 覆盖需要运行专门的扫描工具
- MulanPSL-2木兰许可证是 GitLink 平台上常用的许可证,需注意其与 GPL 的兼容性
- 敏感信息扫描结果仅供参考,真实密钥需人工复核;正则可能漏报或误报,发布前建议结合 gitleaks/trufflehog 等专业工具二次确认

View File

@ -0,0 +1,112 @@
# 开源合规检查完整工作流示例
**场景**`z2_cc/gitlink-cli` 准备发版前,做一次完整合规自检(许可证 + 依赖 + 敏感信息 + 版权头),产出结构化报告。
## 前置条件
- `gitlink-cli` 已安装并登录(`gitlink-cli auth status` 正常)
- 对目标仓库有读权限
- 批量敏感信息扫描需要本地可 `git clone`(无 clone 条件时见"降级"
## Step 1仓库元信息
```bash
gitlink-cli repo +info --owner z2_cc --repo gitlink-cli --format json
```
提取:`full_name`、`default_branch`、`license`(若平台返回)、`private`。
## Step 2LICENSE 识别
```bash
gitlink-cli api GET /z2_cc/gitlink-cli/raw/master/LICENSE
```
按 LICENSE 关键词识别类型MIT / Apache-2.0 / MulanPSL-2 等)。
## Step 3依赖合规分析
```bash
# Go 项目
gitlink-cli api GET /z2_cc/gitlink-cli/raw/master/go.mod
```
逐依赖判断许可证,对照兼容性矩阵评估与项目主许可证的兼容性。
## Step 4敏感信息扫描批量
```bash
git clone https://www.gitlink.org.cn/z2_cc/gitlink-cli.git /tmp/gitlink-cli-scan
cd /tmp/gitlink-cli-scan
# 高危凭据特征
git grep -nE 'AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|glpat-[A-Za-z0-9\-_]{20}|-----BEGIN .*PRIVATE KEY-----' HEAD
# 配置文件中的硬编码密钥
git grep -niE '(password|passwd|pwd|secret|token|apikey|api_key)\s*[:=]' HEAD -- '*.env*' '*.yml' '*.yaml' '*.json' '*.conf'
# 数据库连接串
git grep -nE '(mysql|postgres|mongodb|redis)://[^:[:space:]]+:[^@[:space:]]+@' HEAD
# 历史残留
git log --all -p -S 'AKIA' --oneline | head
```
> **降级**:无 clone 条件时,仅对少量高危文件逐个取内容扫描:
> `gitlink-cli api GET /z2_cc/gitlink-cli/raw/master/.env` 等,并在报告注明"未做全量扫描"。
## Step 5版权声明采样
```bash
git ls-tree --name-only HEAD | head
git show HEAD:cmd/auth/login.go | head -5 # 采样源文件头部
```
## Step 6汇总报告示例输出
```markdown
## ⚖️ 合规检查报告 — z2_cc/gitlink-cli
📅 检查时间2026-06-15
📋 项目许可证MIT
### 🔴 必须修复
| # | 问题 | 文件 | 建议 |
|---|------|------|------|
### 🟡 建议修复
| # | 问题 | 文件 | 建议 |
|---|------|------|------|
| 1 | 缺少 SECURITY.md | — | 添加安全披露流程 |
### 🔴 敏感信息扫描
| 风险 | 文件 | 行 | 内容特征 | 建议 |
|------|------|----|---------|------|
| 🟢 低 | examples/demo.go | 45 | token: "example_token_for_demo" | 加注释说明是示例 |
### 📊 合规评分
| 维度 | 状态 | 评分 |
|------|:----:|:----:|
| 📜 许可证 | ✅ | ★★★★★ |
| 🏷️ 版权声明 | ⚠️ | ★★★☆☆ |
| 📦 依赖合规 | ✅ | ★★★★★ |
| 🔒 安全策略 | ⚠️ | ★★★☆☆ |
| 🔒 敏感信息管控 | ✅ | ★★★★☆ |
**总体合规评分82/100**
```
## 命令速览
```bash
gitlink-cli repo +info --owner <owner> --repo <repo> --format json
gitlink-cli api GET /:owner/:repo/raw/master/LICENSE
gitlink-cli api GET /:owner/:repo/raw/master/go.mod
git clone https://www.gitlink.org.cn/<owner>/<repo>.git /tmp/<repo>-scan
git grep -nE 'AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|glpat-[A-Za-z0-9\-_]{20}|-----BEGIN .*PRIVATE KEY-----' HEAD
```
## 注意
- 全程只读,不修改远端仓库
- 示例报告中出现的 `example_token_for_demo` 为占位假值;扫描命令中的 `AKIA[0-9A-Z]{16}` 等是正则模式而非真实凭据——均勿当作真实泄露

View File

@ -1,214 +0,0 @@
---
name: gitlink-contributor-growth
version: 1.0.0
description: "贡献者成长体系:贡献活动追踪 → 成长排行与段位 → 自动颁发徽章。串联 contributors-stat / commit / pr / issue 数据,多维加权计算成长分并自动颁奖。"
metadata:
requires:
bins: ["gitlink-cli", "jq"]
cliHelp: "gitlink-cli repo +contributors --help / gitlink-cli issue +create --help / gitlink-cli label +create --help"
---
# gitlink-contributor-growth贡献者成长体系
> **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解认证、全局参数和 API 注意事项。
>
> **CRITICAL — 所有 GitLink 操作必须使用 `gitlink-cli`,禁止使用 `gh`GitHub CLI操作 GitLink 资源。**
## 说明
本 Skill 构建一套完整的贡献者成长激励体系,将分散的 PR / Issue / Commit 数据聚合为可量化的"成长分",并按段位自动颁发徽章,形成"持续贡献 → 即时反馈"的闭环。
**三个阶段串联:**
1. **贡献活动追踪** — 采集仓库贡献者代码统计、贡献者列表、近期提交、已合并 PR、已关闭 Issue
2. **贡献排行 + 成长等级** — 多维加权计算成长分、排名、划分段位(🌱新芽 / 🌿新星 / 🌳中坚 / 🏆核心)
3. **自动颁发徽章** — 对达到段位的贡献者创建致谢 Issue 或在已有 Issue 下颁发徽章评论,给新人发 good-first-issue 引导
---
## 三阶段工作流总览
```mermaid
flowchart LR
A[周期触发 / 手动] --> B[Phase 1: 贡献追踪]
B --> C[Phase 2: 排行与段位]
C --> D[Phase 3: 颁发徽章]
subgraph B[Phase 1: 贡献追踪]
B1[contributors-stat 代码统计] --> B2[commit 近期提交]
B2 --> B3[merged PR 列表]
B3 --> B4[closed Issue 列表]
B4 --> B5[按 login 聚合指标]
end
subgraph C[Phase 2: 排行与段位]
C1[计算成长分] --> C2[排名排序]
C2 --> C3[划分成长段位]
C3 --> C4[输出排行报告]
end
subgraph D[Phase 3: 颁发徽章]
D1[识别首次贡献者] --> D2[达段位者颁奖]
D2 --> D3[good-first-issue 引导]
D3 --> D4[创建致谢 Issue / 评论]
end
```
---
## 成长分与段位模型
### 成长分计算公式
```
成长分 = commits × 1 + mergedPR × 5 + closedIssue × 3 + (首次贡献者 ? +10 : 0)
```
| 维度 | 权重 | 数据来源 | 说明 |
|------|------|----------|------|
| 提交数 (commits) | ×1 | `commit +list --limit 100` | 近期代码贡献基础分 |
| 合并 PR 数 | ×5 | `pr +list --state merged` | 协作产出,权重最高 |
| 关闭 Issue 数 | ×3 | `issue +list --state closed` | 协助社区/参与讨论 |
| 首次贡献奖励 | +10 | 对比 contributors 历史列表 | 鼓励新成员加入 |
### 成长段位
| 成长分区间 | 段位 | 徽章 | 含义 |
|-----------|------|------|------|
| 0 9 | 🌱 新芽 | — | 刚起步的新贡献者 |
| 10 29 | 🌿 新星 | 🌿 | 持续活跃的潜力成员 |
| 30 79 | 🌳 中坚 | 🌳 | 团队核心生产力 |
| ≥ 80 | 🏆 核心 | 🏆 | 不可或缺的项目骨干 |
### 段位进度条
报告中用 ASCII 进度条展示当前段位距下一段位还差多少分,例如:
```
🌿 新星 (23/29) ████████░░░ 距 🌳 中坚 还差 6 分
```
---
## Phase 1贡献活动追踪
### 步骤
```bash
# 1. 贡献者代码统计contributions / additions / deletions
gitlink-cli repo +contributors-stat --owner <owner> --repo <repo> --format json
# 2. 贡献者列表(用于识别"首次贡献者"——历史列表中是否包含当前 login
gitlink-cli repo +contributors --owner <owner> --repo <repo> --format json
# 3. 近期提交(按 author.login 聚合 commits 数)
gitlink-cli commit +list --owner <owner> --repo <repo> --limit 100 --format json
# 4. 已合并 PR按 user.login 聚合 mergedPR 数)
gitlink-cli pr +list --owner <owner> --repo <repo> --state merged --limit 100 --format json
# 5. 已关闭 Issue按 assignee 或参与者 login 聚合 closedIssue 数)
gitlink-cli issue +list --owner <owner> --repo <repo> --state closed --limit 100 --format json
```
聚合规则(按 `login`
- **commits** = commit list 中 author.login 出现次数
- **mergedPR** = merged PR 列表中 user.login 出现次数
- **closedIssue** = closed Issue 中 assignee.login或参与者出现次数
- **isFirstTime** = 当前贡献者不在 contributors 历史列表中
---
## Phase 2贡献排行与成长等级
### 计算流程
```
输入:每个贡献者的 { commits, mergedPR, closedIssue, isFirstTime }
计算:
score = commits × 1 + mergedPR × 5 + closedIssue × 3 + (isFirstTime ? 10 : 0)
排名:按 score 降序
段位映射:
score >= 80 → 🏆 核心
score >= 30 → 🌳 中坚
score >= 10 → 🌿 新星
else → 🌱 新芽
```
### 输出
- `contribution-ranking.md` — 排行榜表格(排名|贡献者|提交|合并PR|关闭Issue|成长分|段位|进度条)
- `contributor-growth-report.md` — 成长报告(含社区活跃度综合评分 /10、段位分布、新人识别、颁奖建议
---
## Phase 3自动颁发徽章
### 颁奖规则
| 触发条件 | 动作 | 命令 |
|---------|------|------|
| 新人首次贡献 | good-first-issue 引导评论 | `issue +comment` |
| 达到 🌿 新星 | 致谢 Issue + 🌿 徽章标签 | `issue +create` / `label +create` |
| 达到 🌳 中坚 | 致谢 Issue + 🌳 徽章标签 | `issue +create` |
| 达到 🏆 核心 | 致谢 Issue + 🏆 徽章标签 | `issue +create` |
### 步骤
```bash
# 1. 预先创建徽章标签dry-run 优先)
gitlink-cli label +create --owner <owner> --repo <repo> --name "🏆 核心贡献者" --color ff6b35
# 2. 为达段位者创建致谢 Issue
gitlink-cli issue +create -t "🏅 致谢 @<user> 达成 <段位> 段位" \
-b "感谢 @<user> 在本周期内的贡献:提交 X / 合并 PR Y / 关闭 Issue Z成长分 W晋升 <段位>。" \
--label <label_id>
# 3. 在已有 Issue 下颁发徽章评论(针对解决 Issue 的贡献者)
gitlink-cli issue +comment --owner <owner> --repo <repo> --number <id> \
--body "🏅 感谢 @<user> 关闭本 Issue达成 <段位> 段位!"
# 4. 给 good-first-issue 新人发引导评论
gitlink-cli issue +comment --owner <owner> --repo <repo> --number <id> \
--body "👋 欢迎新贡献者 @<user>!这是你的首次提交,可参考 good-first-issue 列表继续参与。"
```
**所有写操作默认 dry-run**,确认后通过 `DRY_RUN=false` 切换。
---
## 可复现脚本
本 Skill 提供可直接执行的 Bash 脚本,位于 `scripts/` 目录:
| 脚本 | 功能 | 使用方式 |
|------|------|----------|
| `01-track-activity.sh` | Phase 1 贡献活动追踪 | `bash 01-track-activity.sh <owner> <repo>` |
| `02-rank-and-tier.sh` | Phase 2 排行与段位 | `bash 02-rank-and-tier.sh <owner> <repo>` |
| `03-award-badges.sh` | Phase 3 颁发徽章 | `bash 03-award-badges.sh <owner> <repo>` |
| `growth-analyze.js` | 核心引擎(成长分 / 段位 / 报告) | `node growth-analyze.js <output_dir>` |
| `contributor-growth-full.sh` | 全流程串联 | `bash contributor-growth-full.sh <owner> <repo>` |
**所有脚本默认 dry-run 模式**(不会实际修改数据),确认无误后通过环境变量切换:
```bash
# Dry-run默认安全
DRY_RUN=true bash scripts/contributor-growth-full.sh z2_cc gitlink-cli
# 实际执行
DRY_RUN=false bash scripts/contributor-growth-full.sh z2_cc gitlink-cli
```
---
## 注意事项
1. **dry-run 优先**:所有写操作(`issue +create`、`issue +comment`、`label +create`)默认不实际执行
2. **Token 有效**:运行前确认 `gitlink-cli auth status` 返回正常
3. **优雅降级**API 未登录或无网络时,脚本必须用 `2>&1 || echo "[WARN]"` 兜底,保证离线也能产出报告(用空数据填充)
4. **首次贡献者识别**:依赖 contributors 历史列表与近期贡献者对比,列表为空时所有近期贡献者均视为首次
5. **避免重复颁奖**:颁奖前可检查是否已存在同名致谢 Issue标题包含 `@<user>`
6. **输出文件**:所有 JSON / MD / HTML 报告保存到 `scripts/_output/` 目录供审计

View File

@ -1,128 +0,0 @@
# 贡献者成长体系工作流 — 端到端示例
**场景**:项目维护者希望量化每位贡献者的产出,按成长分划分段位,并对达到段位的成员自动颁发徽章致谢,形成"贡献 → 反馈 → 持续激励"的闭环。
## 前置条件
- `gitlink-cli` 已安装并登录(`gitlink-cli auth status`
- 目标仓库已确认(示例使用 `z2_cc/gitlink-cli`
- `jq` 已安装(用于 JSON 解析)
## 工作流步骤
### Step 1贡献活动追踪Phase 1
```bash
# 1.1 贡献者代码统计(基线,含历史贡献者列表)
gitlink-cli repo +contributors-stat --owner z2_cc --repo gitlink-cli --format json
# 1.2 贡献者列表(识别首次贡献者的历史基线)
gitlink-cli repo +contributors --owner z2_cc --repo gitlink-cli --format json
# 1.3 近期提交(按 author.login 聚合 commits
gitlink-cli commit +list --owner z2_cc --repo gitlink-cli --limit 100 --format json
# 1.4 已合并 PR按 user.login 聚合 mergedPR
gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state merged --limit 100 --format json
# 1.5 已关闭 Issue按 assignee.login 聚合 closedIssue
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state closed --limit 100 --format json
```
**输出示例(聚合后的多维指标):**
```json
{
"contributors": [
{"login": "alice", "commits": 25, "mergedPR": 8, "closedIssue": 4, "isFirstTime": false},
{"login": "bob", "commits": 6, "mergedPR": 2, "closedIssue": 1, "isFirstTime": false},
{"login": "carol", "commits": 3, "mergedPR": 1, "closedIssue": 0, "isFirstTime": true}
]
}
```
### Step 2成长分计算与段位划分Phase 2
**成长分公式:** `commits × 1 + mergedPR × 5 + closedIssue × 3 + (首次贡献者 ? +10 : 0)`
**计算演示:**
```
alice: 25×1 + 8×5 + 4×3 + 0 = 25 + 40 + 12 + 0 = 77 → 🌳 中坚
bob: 6×1 + 2×5 + 1×3 + 0 = 6 + 10 + 3 + 0 = 19 → 🌿 新星
carol: 3×1 + 1×5 + 0×3 + 10 = 3 + 5 + 0 + 10 = 18 → 🌿 新星(含新人加成)
```
**段位划分:**
| 成长分区间 | 段位 |
|-----------|------|
| 0 9 | 🌱 新芽 |
| 10 29 | 🌿 新星 |
| 30 79 | 🌳 中坚 |
| ≥ 80 | 🏆 核心 |
**Expected 断言:**
- alice77→ 🌳 中坚 ✅
- bob19→ 🌿 新星 ✅
- carol18→ 🌿 新星 ✅(首次贡献 +10 起关键作用)
### Step 3自动颁发徽章Phase 3dry-run
```bash
# 3.1 预先创建徽章标签dry-run 模式)
DRY_RUN=true
echo "[DRY-RUN] 将创建标签: 🏆 核心贡献者 (#ff6b35)"
echo "[DRY-RUN] 将创建标签: 🌳 中坚贡献者 (#16a34a)"
echo "[DRY-RUN] 将创建标签: 🌿 新星贡献者 (#3b82f6)"
```
```bash
# 3.2 为 alice 颁发 🌳 中坚 徽章dry-run
echo "[DRY-RUN] 将为 @alice 颁发 🌳 中坚 徽章"
echo "[DRY-RUN] 将创建致谢 Issue: 🏅 致谢 @alice 达成 🌳 中坚 段位"
```
```bash
# 3.3 给首次贡献者 carol 发引导评论dry-run
echo "[DRY-RUN] 将为首次贡献者 @carol 发送 good-first-issue 引导评论"
```
**Expected** alice、bob、carol 均进入颁奖清单carol 进入新人引导清单alice 是榜首。
### Step 4实际执行确认后切换
```bash
# 切换到实际执行
DRY_RUN=false bash skills/gitlink-contributor-growth/scripts/contributor-growth-full.sh z2_cc gitlink-cli
```
实际执行将:
1. 通过 `label +create` 创建 🏆核心 / 🌳中坚 / 🌿新星 三类徽章标签
2. 通过 `issue +create` 为 alice 创建"🏅 致谢 @alice 达成 🌳 中坚 段位"致谢 Issue
3. 在合适 Issue 下通过 `issue +comment` 为 carol 发新人引导评论
## 完整命令速览
```bash
# Phase 1: 追踪
gitlink-cli repo +contributors-stat --owner z2_cc --repo gitlink-cli --format json
gitlink-cli repo +contributors --owner z2_cc --repo gitlink-cli --format json
gitlink-cli commit +list --owner z2_cc --repo gitlink-cli --limit 100 --format json
gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state merged --limit 100 --format json
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state closed --limit 100 --format json
# Phase 2: 排行(自动调 growth-analyze.js
bash scripts/02-rank-and-tier.sh z2_cc gitlink-cli
# Phase 3: 颁奖
gitlink-cli label +create --owner z2_cc --repo gitlink-cli --name "🏆 核心贡献者" --color ff6b35
gitlink-cli issue +create -t "🏅 致谢 @alice 达成 🌳 中坚 段位" -b "<贡献统计正文>"
gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number <id> --body "<引导评论>"
```
## 注意事项
- 所有写操作(`label +create` / `issue +create` / `issue +comment`)默认 dry-run
- API 未登录或无网络时,脚本优雅降级,用空数据填充,仍能产出报告
- 首次贡献者识别依赖 contributors 历史列表与近期贡献者对比
- 颁奖前可检查是否已存在同名致谢 Issue避免重复颁奖
- 输出文件位于 `scripts/_output/``contribution-ranking.md` / `.json` / `contributor-growth-report.md` 及对应 HTML

View File

@ -1,65 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 1: 贡献活动追踪
# 功能:采集 contributors-stat / commit / merged pr / closed issue
# 按贡献者 login 聚合多维指标,分别保存到 _output/
# 使用bash 01-track-activity.sh <owner> <repo>
# 环境变量DRY_RUN=true|false (默认 true本阶段只读dry-run 仅影响提示)
# ================================================================
set -e
# ---- 自动检测并使用本地编译的 gitlink-cli ----
source "$(cd "$(dirname "$0")" && pwd)/../../gitlink-shared/scripts/detect-cli.sh"
# ---- 参数解析 ----
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 1: 贡献活动追踪 ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[ DRY_RUN: $DRY_RUN ]"
echo "[========================================]"
# ---- Step 1: 贡献者代码统计 ----
echo "[INFO] 采集贡献者代码统计 (contributors-stat)..."
gitlink-cli repo +contributors-stat --owner "$OWNER" --repo "$REPO" --format json > "$OUTPUT_DIR/contributors-stat.json" 2>&1 || echo "[WARN] 采集 contributors-stat 失败(可能未登录/无网络),使用空数据"
# ---- Step 2: 贡献者列表(识别首次贡献者的基线) ----
echo "[INFO] 采集贡献者列表 (contributors)..."
gitlink-cli repo +contributors --owner "$OWNER" --repo "$REPO" --format json > "$OUTPUT_DIR/contributors.json" 2>&1 || echo "[WARN] 采集 contributors 失败,使用空数据"
# ---- Step 3: 近期提交 ----
echo "[INFO] 采集近期提交 (commit +list --limit 100)..."
gitlink-cli commit +list --owner "$OWNER" --repo "$REPO" --limit 100 --format json > "$OUTPUT_DIR/commits.json" 2>&1 || echo "[WARN] 采集 commits 失败,使用空数据"
# ---- Step 4: 已合并 PR ----
echo "[INFO] 采集已合并 PR (pr +list --state merged)..."
gitlink-cli pr +list --owner "$OWNER" --repo "$REPO" --state merged --limit 100 --format json > "$OUTPUT_DIR/prs-merged.json" 2>&1 || echo "[WARN] 采集 merged pr 失败,使用空数据"
# ---- Step 5: 已关闭 Issue ----
echo "[INFO] 采集已关闭 Issue (issue +list --state closed)..."
gitlink-cli issue +list --owner "$OWNER" --repo "$REPO" --state closed --limit 100 --format json > "$OUTPUT_DIR/issues-closed.json" 2>&1 || echo "[WARN] 采集 closed issue 失败,使用空数据"
# ---- 兜底:确保文件存在且为合法 JSON避免下游 node 解析崩溃 ----
ensure_json() {
local f="$1"
if [ ! -s "$f" ] || ! node -e "JSON.parse(require('fs').readFileSync('$f','utf8'))" 2>/dev/null; then
echo '{"data":[]}' > "$f"
fi
}
ensure_json "$OUTPUT_DIR/contributors-stat.json"
ensure_json "$OUTPUT_DIR/contributors.json"
ensure_json "$OUTPUT_DIR/commits.json"
ensure_json "$OUTPUT_DIR/prs-merged.json"
ensure_json "$OUTPUT_DIR/issues-closed.json"
echo ""
echo "[========================================]"
echo "[ Phase 1 完成 ]"
echo "[ 数据保存至: $OUTPUT_DIR/ ]"
echo "[========================================]"

View File

@ -1,39 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 2: 贡献排行与成长等级
# 功能:调用 growth-analyze.js 聚合 _output/ 下的多维数据,
# 计算成长分、排名、段位,输出 contribution-ranking.md
# 和 contributor-growth-report.md
# 使用bash 02-rank-and-tier.sh <owner> <repo>
# ================================================================
set -e
# ---- 参数解析 ----
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 2: 贡献排行与成长等级 ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[========================================]"
# ---- 检查 Phase 1 数据是否就绪 ----
if [ ! -f "$OUTPUT_DIR/contributors-stat.json" ]; then
echo "[WARN] 未发现 Phase 1 数据,先运行 01-track-activity.sh"
echo "[INFO] 自动触发 Phase 1 采集..."
bash "$SCRIPT_DIR/01-track-activity.sh" "$OWNER" "$REPO"
fi
# ---- 运行成长分析引擎 ----
echo "[INFO] 运行成长分析引擎 (growth-analyze.js)..."
node "$SCRIPT_DIR/growth-analyze.js" "$OUTPUT_DIR" "$OWNER" "$REPO"
echo ""
echo "[========================================]"
echo "[ Phase 2 完成 ]"
echo "[ 排行榜: $OUTPUT_DIR/contribution-ranking.md"
echo "[ 报告: $OUTPUT_DIR/contributor-growth-report.md"
echo "[========================================]"

View File

@ -1,159 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 3: 自动颁发徽章
# 功能:读 contribution-ranking.json对达段位的贡献者
# dry-run 颁发徽章issue +create / issue +comment / label +create
# 并给 good-first-issue 新人发引导评论
# 使用bash 03-award-badges.sh <owner> <repo>
# 环境变量DRY_RUN=true|false (默认 true)
# ================================================================
set -e
# ---- 自动检测并使用本地编译的 gitlink-cli ----
source "$(cd "$(dirname "$0")" && pwd)/../../gitlink-shared/scripts/detect-cli.sh"
# ---- 参数解析 ----
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 3: 自动颁发徽章 ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[ DRY_RUN: $DRY_RUN ]"
echo "[========================================]"
RANKING_JSON="$OUTPUT_DIR/contribution-ranking.json"
# ---- 检查排行数据 ----
if [ ! -f "$RANKING_JSON" ]; then
echo "[WARN] 未发现 $RANKING_JSON,先运行 Phase 1 + Phase 2"
echo "[INFO] 自动触发排行生成..."
bash "$SCRIPT_DIR/02-rank-and-tier.sh" "$OWNER" "$REPO"
fi
if [ ! -s "$RANKING_JSON" ]; then
echo "[WARN] 排行数据为空,跳过颁奖"
exit 0
fi
# ---- 颁奖候选:非 🌱 新芽 的贡献者都颁奖 ----
echo "[INFO] 提取达段位贡献者(🌿 新星 / 🌳 中坚 / 🏆 核心)..."
CONTRIBUTORS=$(node -e "
const fs=require('fs');
let d={contributors:[]};
try { d=JSON.parse(fs.readFileSync('$RANKING_JSON','utf8')); } catch(e){}
const list=d.contributors||[];
list.forEach(c=>{
if(c.tierKey && c.tierKey!=='seedling'){
process.stdout.write([c.login,c.tierKey,c.tier,c.commits,c.mergedPR,c.closedIssue,c.score].join('|')+'\n');
}
});
" 2>/dev/null || echo "")
if [ -z "$CONTRIBUTORS" ]; then
echo "[INFO] 暂无达段位的贡献者,本次不颁发徽章"
else
echo "[INFO] 共 $(echo "$CONTRIBUTORS" | wc -l) 位达段位贡献者将颁奖"
fi
# ---- 颁奖循环 ----
while IFS='|' read -r LOGIN TIER_KEY TIER COMMITS MERGED_PR CLOSED_ISSUE SCORE; do
[ -z "$LOGIN" ] && continue
case "$TIER_KEY" in
rising) BADGE="🌿"; LABEL_NAME="🌿 新星贡献者"; LABEL_COLOR="3b82f6" ;;
core) BADGE="🌳"; LABEL_NAME="🌳 中坚贡献者"; LABEL_COLOR="16a34a" ;;
topcore) BADGE="🏆"; LABEL_NAME="🏆 核心贡献者"; LABEL_COLOR="ff6b35" ;;
*) BADGE="🏅"; LABEL_NAME="🏅 贡献者"; LABEL_COLOR="f59e0b" ;;
esac
TITLE="🏅 致谢 @$LOGIN 达成 $TIER 段位"
BODY="感谢 @$LOGIN 在本周期内的贡献:
| 维度 | 数据 |
|------|------|
| 提交数 | $COMMITS |
| 合并 PR | $MERGED_PR |
| 关闭 Issue | $CLOSED_ISSUE |
| 成长分 | $SCORE |
恭喜晋升 **$TIER** 段位,获得 $BADGE 徽章!"
echo ""
echo "[INFO] --- @$LOGIN ($TIER, 成长分 $SCORE) ---"
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] 将为 @$LOGIN 颁发 $TIER 徽章"
echo "[DRY-RUN] 将创建标签: $LABEL_NAME (#$LABEL_COLOR)"
echo "[DRY-RUN] 将创建致谢 Issue: $TITLE"
else
echo "[INFO] 为 @$LOGIN 颁发 $TIER 徽章..."
# 创建徽章标签(已存在则忽略错误)
gitlink-cli label +create --owner "$OWNER" --repo "$REPO" --name "$LABEL_NAME" --color "$LABEL_COLOR" --format json 2>&1 || echo "[WARN] 标签 $LABEL_NAME 可能已存在"
# 创建致谢 Issue
gitlink-cli issue +create -t "$TITLE" -b "$BODY" --format json 2>&1 || echo "[WARN] 创建致谢 Issue 失败:@$LOGIN"
fi
done <<< "$CONTRIBUTORS"
# ---- 新人引导good-first-issue 首次贡献者) ----
echo ""
echo "[INFO] 检查首次贡献者,发 good-first-issue 引导评论..."
NEWCOMERS=$(node -e "
const fs=require('fs');
let d={contributors:[]};
try { d=JSON.parse(fs.readFileSync('$RANKING_JSON','utf8')); } catch(e){}
(d.contributors||[]).filter(c=>c.isFirstTime).forEach(c=>{
process.stdout.write(c.login+'\n');
});
" 2>/dev/null || echo "")
if [ -z "$NEWCOMERS" ]; then
echo "[INFO] 本次未识别到首次贡献者"
else
while IFS= read -r LOGIN; do
[ -z "$LOGIN" ] && continue
GUIDE_BODY="👋 欢迎新贡献者 @$LOGIN!这是你的首次提交。可参考仓库内 good-first-issue 标签的 Issue 继续参与社区,期待你的下一次贡献!"
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] 将为首次贡献者 @$LOGIN 发送引导评论"
else
echo "[INFO] 为首次贡献者 @$LOGIN 发送引导评论(需指定 Issue 号,此处跳过自动评论)"
# 实际执行需指定具体 Issue 号:
# gitlink-cli issue +comment --owner "$OWNER" --repo "$REPO" --number <id> --body "$GUIDE_BODY"
fi
done <<< "$NEWCOMERS"
fi
# ---- 颁奖清单汇总 ----
SUMMARY="$OUTPUT_DIR/award-summary.txt"
{
echo "颁奖时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "仓库: $OWNER/$REPO"
echo "DRY_RUN: $DRY_RUN"
echo ""
echo "达段位贡献者:"
if [ -n "$CONTRIBUTORS" ]; then
echo "$CONTRIBUTORS" | while IFS='|' read -r LOGIN TIER_KEY TIER C M I S; do
echo " - @$LOGIN ($TIER, 成长分 $S)"
done
else
echo " (无)"
fi
echo ""
echo "首次贡献者:"
if [ -n "$NEWCOMERS" ]; then
echo "$NEWCOMERS" | sed 's/^/ - @/'
else
echo " (无)"
fi
} > "$SUMMARY"
echo ""
echo "[========================================]"
echo "[ Phase 3 完成 ]"
echo "[ 颁奖清单: $SUMMARY"
echo "[========================================]"

View File

@ -1,56 +0,0 @@
#!/bin/bash
# ================================================================
# 贡献者成长体系 — 全流程串联脚本
# 功能:依次执行 贡献追踪 → 排行段位 → 颁发徽章 → 生成 HTML 报告
# 使用bash contributor-growth-full.sh <owner> <repo>
# 环境变量DRY_RUN=true|false (默认 true)
# ================================================================
set -e
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "============================================"
echo " 贡献者成长体系"
echo " Target: $OWNER/$REPO"
echo " DRY_RUN: $DRY_RUN"
echo " 开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================"
echo ""
# Phase 1: 贡献活动追踪
echo "▸ Phase 1/3: 贡献活动追踪"
bash "$SCRIPT_DIR/01-track-activity.sh" "$OWNER" "$REPO"
echo ""
# Phase 2: 排行与段位
echo "▸ Phase 2/3: 贡献排行与成长等级"
bash "$SCRIPT_DIR/02-rank-and-tier.sh" "$OWNER" "$REPO"
echo ""
# Phase 3: 颁发徽章
echo "▸ Phase 3/3: 自动颁发徽章"
DRY_RUN="$DRY_RUN" bash "$SCRIPT_DIR/03-award-badges.sh" "$OWNER" "$REPO"
echo ""
# 生成 HTML 可视化报告
echo "▸ 生成 HTML 可视化报告..."
SHARED_SCRIPT="$SCRIPT_DIR/../../gitlink-shared/scripts/md-to-html.js"
if [ -f "$OUTPUT_DIR/contribution-ranking.md" ]; then
node "$SHARED_SCRIPT" "$OUTPUT_DIR/contribution-ranking.md" 2>/dev/null || true
fi
if [ -f "$OUTPUT_DIR/contributor-growth-report.md" ]; then
node "$SHARED_SCRIPT" "$OUTPUT_DIR/contributor-growth-report.md" 2>/dev/null || true
fi
echo ""
echo "============================================"
echo " 全流程完成"
echo " 结束时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo " 📄 Markdown: $OUTPUT_DIR/"
echo " 🌐 HTML: 已生成"
echo "============================================"

View File

@ -1,323 +0,0 @@
#!/usr/bin/env node
/**
* 贡献者成长分析引擎
* 用法: node growth-analyze.js <output_dir> [owner] [repo]
*
* 读取 _output/
* - contributors-stat.json 贡献者代码统计基线
* - contributors.json 贡献者列表识别首次贡献者的历史基线
* - commits.json 近期提交
* - prs-merged.json 已合并 PR
* - issues-closed.json 已关闭 Issue
*
* 输出
* - contribution-ranking.md 排行榜表格
* - contribution-ranking.json 机器可读排行 03 颁奖脚本读取
* - contributor-growth-report.md 成长报告含综合评分 /10 md-to-html 渲染评分环
*/
const fs = require('fs');
const path = require('path');
const dir = process.argv[2] || '_output';
const owner = process.argv[3] || 'z2_cc';
const repo = process.argv[4] || 'gitlink-cli';
// ---------- 工具:读取 JSON兼容 data 是数组或 {issues/pulls/commits/contributors/...} ----------
function readJSON(name) {
try { return JSON.parse(fs.readFileSync(path.join(dir, name), 'utf8')); }
catch (e) { return { data: [] }; }
}
// 兼容多种响应形态data 是数组 / data 是 {issues:[]}/ {pulls:[]} / 顶层为 {data:{}} 包裹
function toArray(raw) {
if (Array.isArray(raw)) return raw;
if (Array.isArray(raw && raw.data)) return raw.data;
const inner = raw && raw.data;
if (inner && typeof inner === 'object') {
for (const k of ['contributors', 'issues', 'pulls', 'commits', 'list', 'items', 'users']) {
if (Array.isArray(inner[k])) return inner[k];
}
}
if (raw && typeof raw === 'object') {
for (const k of ['contributors', 'issues', 'pulls', 'commits', 'list', 'items', 'users']) {
if (Array.isArray(raw[k])) return raw[k];
}
}
return [];
}
// 从对象中尽量挖出 login 字段(不同接口字段名不同)
function pickLogin(obj) {
if (!obj) return null;
return obj.login || obj.username || obj.name ||
(obj.author && (obj.author.login || obj.author.name || obj.author.username)) ||
(obj.user && (obj.user.login || obj.user.name || obj.user.username)) ||
(obj.committer && (obj.committer.login || obj.committer.name)) ||
null;
}
// ---------- 读取所有数据 ----------
const contribStatRaw = readJSON('contributors-stat.json');
const contributorsRaw = readJSON('contributors.json');
const commitsRaw = readJSON('commits.json');
const prsMergedRaw = readJSON('prs-merged.json');
const issuesClosedRaw = readJSON('issues-closed.json');
const statList = toArray(contribStatRaw);
const historyList = toArray(contributorsRaw);
const commitList = toArray(commitsRaw);
const prList = toArray(prsMergedRaw);
const issueList = toArray(issuesClosedRaw);
// 历史贡献者 login 集合(用于识别首次贡献者)
const historyLogins = new Set(historyList.map(pickLogin).filter(Boolean));
// ---------- 按 login 聚合多维指标 ----------
const map = new Map(); // login -> stats
function bump(login, field) {
if (!login) return;
if (!map.has(login)) {
map.set(login, { login, commits: 0, mergedPR: 0, closedIssue: 0, isFirstTime: false });
}
const s = map.get(login);
if (field) s[field] = (s[field] || 0) + 1;
}
commitList.forEach(c => bump(pickLogin(c), 'commits'));
prList.forEach(p => bump(pickLogin(p), 'mergedPR'));
issueList.forEach(i => bump(pickLogin(i), 'closedIssue'));
// 若聚合后为空API 失败),退而用 contributors-stat 作为基础贡献者清单
if (map.size === 0 && statList.length > 0) {
statList.forEach(c => {
const login = pickLogin(c);
if (login) bump(login, null);
});
}
// 标记首次贡献者
for (const s of map.values()) {
s.isFirstTime = !historyLogins.has(s.login);
}
// ---------- 计算成长分与段位 ----------
// 段位定义0-9 🌱新芽 / 10-29 🌿新星 / 30-79 🌳中坚 / ≥80 🏆核心
const TIERS = [
{ key: 'topcore', min: 80, name: '🏆 核心', badge: '🏆' },
{ key: 'core', min: 30, name: '🌳 中坚', badge: '🌳' },
{ key: 'rising', min: 10, name: '🌿 新星', badge: '🌿' },
{ key: 'seedling', min: 0, name: '🌱 新芽', badge: '🌱' },
];
function tierOf(score) {
return TIERS.find(t => score >= t.min);
}
function progressBar(score, tier) {
// 按段位下界升序排列:[seedling(0), rising(10), core(30), topcore(80)]
const sorted = [...TIERS].sort((a, b) => a.min - b.min);
const idx = sorted.findIndex(t => t.key === tier.key);
const lo = tier.min;
// 上一级(更高)段位 = sorted[idx+1];最高段无上界
const upper = idx < sorted.length - 1 ? sorted[idx + 1] : null;
const hi = upper ? upper.min : (lo + 10);
const span = Math.max(hi - lo, 1);
const pos = Math.min(score - lo, span);
const ratio = Math.max(0, Math.min(1, pos / span));
const filled = Math.round(ratio * 10);
const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
const next = upper;
const remain = next ? Math.max(0, next.min - score) : 0;
return { bar, next, remain };
}
const contributors = Array.from(map.values()).map(s => {
const score = s.commits * 1 + s.mergedPR * 5 + s.closedIssue * 3 + (s.isFirstTime ? 10 : 0);
const tier = tierOf(score);
return { ...s, score, tierKey: tier.key, tier: tier.name, badge: tier.badge };
});
// 按成长分降序
contributors.sort((a, b) => b.score - a.score);
// 排名
contributors.forEach((c, i) => { c.rank = i + 1; });
// ---------- 段位分布统计 ----------
const tierDist = TIERS.map(t => {
const members = contributors.filter(c => c.tierKey === t.key);
return { ...t, count: members.length };
});
const totalContributors = contributors.length;
const newcomers = contributors.filter(c => c.isFirstTime);
const topContributor = contributors[0] || null;
// ---------- 社区活跃度综合评分0-10供 md-to-html 渲染评分环) ----------
// 维度:贡献者规模(40%) + 段位深度(35%) + 新人流入(25%)
const sizeScore = totalContributors >= 10 ? 10 : totalContributors >= 5 ? 8 :
totalContributors >= 3 ? 6 : totalContributors >= 1 ? 4 : 0;
const topcoreCount = (tierDist.find(t => t.key === 'topcore') || {}).count || 0;
const coreCount = (tierDist.find(t => t.key === 'core') || {}).count || 0;
const depthScore = topcoreCount >= 2 ? 10 : topcoreCount >= 1 ? 8 :
coreCount >= 2 ? 7 : coreCount >= 1 ? 5 : 3;
const newcomerCount = newcomers.length;
const influxScore = newcomerCount >= 3 ? 10 : newcomerCount >= 2 ? 8 :
newcomerCount >= 1 ? 6 : 4;
const activityScore = Math.round((sizeScore * 0.4 + depthScore * 0.35 + influxScore * 0.25) * 10) / 10;
const activityLevel = activityScore >= 8 ? '🟢 活跃' :
activityScore >= 6 ? '🟢 良好' :
activityScore >= 4 ? '🟡 一般' : '🔴 待激活';
// ---------- 时间戳 ----------
const now = new Date();
const dateStr = now.toISOString().slice(0, 10);
const timeStr = now.toISOString().slice(0, 19).replace('T', ' ');
// ---------- 生成 contribution-ranking.md ----------
function rankingTable() {
if (contributors.length === 0) return '> 暂无贡献者数据';
let lines = '| 排名 | 贡献者 | 提交 | 合并PR | 关闭Issue | 成长分 | 段位 | 进度条 |\n';
lines += '|------|--------|------|--------|-----------|--------|------|--------|\n';
contributors.forEach(c => {
const pb = progressBar(c.score, TIERS.find(t => t.key === c.tierKey));
const progress = pb.next
? `${pb.bar}${pb.next.name} 还差 ${pb.remain}`
: `${pb.bar} 已达顶级`;
const newcomerMark = c.isFirstTime ? ' 🆕' : '';
lines += `| #${c.rank} | @${c.login}${newcomerMark} | ${c.commits} | ${c.mergedPR} | ${c.closedIssue} | ${c.score} | ${c.tier} | ${progress} |\n`;
});
return lines;
}
const rankingMd = `# 🏆 贡献者成长排行
**报告日期** ${dateStr}
**项目** ${owner}/${repo}
${rankingTable()}
## 段位说明
| 段位 | 成长分区间 | 含义 |
|------|-----------|------|
| 🌱 新芽 | 0 9 | 刚起步的新贡献者 |
| 🌿 新星 | 10 29 | 持续活跃的潜力成员 |
| 🌳 中坚 | 30 79 | 团队核心生产力 |
| 🏆 核心 | 80 | 不可或缺的项目骨干 |
## 成长分公式
\`成长分 = commits × 1 + mergedPR × 5 + closedIssue × 3 + (首次贡献者 ? +10 : 0)\`
---
*数据采集时间${timeStr}*
*AI 生成建议人工复核*
`;
fs.writeFileSync(path.join(dir, 'contribution-ranking.md'), rankingMd, 'utf8');
// ---------- 生成 contribution-ranking.json供 03 颁奖脚本读取) ----------
const rankingJson = {
project: `${owner}/${repo}`,
generated_at: timeStr,
contributors: contributors.map(c => {
const t = TIERS.find(x => x.key === c.tierKey);
const pb = progressBar(c.score, t);
return {
rank: c.rank,
login: c.login,
commits: c.commits,
mergedPR: c.mergedPR,
closedIssue: c.closedIssue,
score: c.score,
tierKey: c.tierKey,
tier: c.tier,
badge: c.badge,
isFirstTime: c.isFirstTime,
nextTier: pb.next ? pb.next.name : null,
remainToNext: pb.remain,
};
}),
};
fs.writeFileSync(path.join(dir, 'contribution-ranking.json'), JSON.stringify(rankingJson, null, 2), 'utf8');
// ---------- 生成 contributor-growth-report.md含综合评分供 md-to-html 渲染评分环) ----------
function tierDistPie() {
if (totalContributors === 0) return '暂无数据';
return tierDist.map(t => `${t.name}: ${t.count} 人 (${totalContributors > 0 ? Math.round(t.count / totalContributors * 100) : 0}%)`).join(' ');
}
const awardSuggestions = contributors
.filter(c => c.tierKey !== 'seedling')
.slice(0, 10)
.map(c => `- 🏅 为 **@${c.login}** 颁发 ${c.tier} 徽章(成长分 ${c.score}):创建致谢 Issue \`🏅 致谢 @${c.login} 达成 ${c.tier} 段位\``)
.join('\n');
const newcomerSection = newcomers.length > 0
? newcomers.map(c => `- 🆕 **@${c.login}**(成长分 ${c.score},段位 ${c.tier})— 建议发 good-first-issue 引导评论`).join('\n')
: '- 本周期暂无首次贡献者';
const reportMd = `# 🌱 贡献者成长报告
**报告日期** ${dateStr}
**项目** ${owner}/${repo}
**综合评分** ${activityScore}/10 ${activityLevel}
## 社区活跃度概览
| 指标 | 数据 | 状态 |
|------|------|------|
| 贡献者总数 | ${totalContributors} | ${sizeScore >= 7 ? '🟢' : sizeScore >= 5 ? '🟡' : '🔴'} |
| 🏆 核心贡献者 | ${topcoreCount} | ${topcoreCount >= 1 ? '🟢' : '🔴'} |
| 🌳 中坚贡献者 | ${coreCount} | ${coreCount >= 1 ? '🟢' : '🟡'} |
| 首次贡献者 | ${newcomerCount} | ${influxScore >= 7 ? '🟢' : '🟡'} |
| 段位深度评分 | ${depthScore}/10 | ${depthScore >= 7 ? '🟢' : '🟡'} |
| 新人流入评分 | ${influxScore}/10 | ${influxScore >= 7 ? '🟢' : '🟡'} |
**段位分布** ${tierDistPie()}
## 成长分模型
\`\`\`
成长分 = commits × 1 + mergedPR × 5 + closedIssue × 3 + (首次贡献者 ? +10 : 0)
段位划分
09 🌱 新芽
1029 🌿 新星
3079 🌳 中坚
80 🏆 核心
\`\`\`
## Top 贡献者
${topContributor ? `**当前榜首:** 🥇 @${topContributor.login}(成长分 ${topContributor.score}${topContributor.tier}` : '暂无贡献者'}
${rankingTable()}
## 新人识别首次贡献者
${newcomerSection}
## 颁奖建议清单
${awardSuggestions || '- 暂无达段位的贡献者,本次不颁发徽章'}
## 改进建议
${sizeScore < 7 ? '1. ⚠️ 贡献者规模偏小,建议标记 good-first-issue 吸引新成员' : '1. ✅ 贡献者规模良好'}
${influxScore < 7 ? '2. ⚠️ 新人流入偏少建议完善新人引导与贡献指南CONTRIBUTING.md' : '2. ✅ 新人流入健康'}
${depthScore < 7 ? '3. ⚠️ 缺乏中坚/核心贡献者,建议加强核心团队培养' : '3. ✅ 段位深度健康'}
---
*数据采集时间${timeStr}*
*AI 生成建议人工复核*
`;
fs.writeFileSync(path.join(dir, 'contributor-growth-report.md'), reportMd, 'utf8');
console.log('✅ 成长排行与报告已生成');
console.log(' - contribution-ranking.md');
console.log(' - contribution-ranking.json');
console.log(' - contributor-growth-report.md');

View File

@ -1,200 +0,0 @@
---
name: gitlink-duplicate-detector
version: 1.0.0
description: "重复 Issue 检测与关联收敛:扫描仓库开放 Issue按标题+正文做语义相似度聚类,识别重复簇、选出主 Issue经确认后发布关联评论并可选关闭重复项。当用户需要收敛重复 Issue、清理看板、或在处理新 Issue 前查重时触发。"
metadata:
requires:
bins: ["gitlink-cli"]
cliHelp: "gitlink-cli issue --help"
requiresVersion: "需要 gitlink-cli 含 `issue +comments`、`label`、`issue +list --keyword` 的版本本仓库源码已具备npm 发布版 v0.1.13 暂缺,待 ≥ v0.2.0"
---
# gitlink-duplicate-detector重复 Issue 检测与关联收敛)
**CRITICAL — 开始前必须先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md),其中包含认证、权限处理和 API 注意事项。**
**CRITICAL — 所有 Shortcuts 在执行写入/删除操作(评论、关闭、打标签)前,务必先确认用户意图;默认 dry-run只读分析。**
## 说明
本 Skill 在**同一 `owner/repo` 内**扫描开放 Issue对「标题subject+ 正文description」做语义相似度聚类找出疑似重复簇为每个簇选出「主 Issue」输出结构化《重复 Issue 收敛报告》;经用户逐条确认后,在重复项上发布指向主 Issue 的关联评论,并可(可选)关闭重复项。目的是收敛 Issue 列表、避免重复劳动。
**与 `gitlink-issue-triage` 的边界**triage 给单个 Issue **分类打标签/分派**;本 Skill 在 Issue **之间**找重复关系,**不分配类别标签**(至多复用项目已有的「重复/duplicate」标签作为幂等标记。两者职责正交可串联。
## 前置条件
- 已 `gitlink-cli auth login``auth status` 为已登录)。
- gitlink-cli 版本需支持 `issue +comments`、`label +list`、`issue +list --keyword`、`issue +update --label`本仓库源码已具备npm 发布版 v0.1.13 不具备,需用源码编译版或 ≥ v0.2.0)。检查方式:
```bash
gitlink-cli issue +comments --help # 存在即满足
gitlink-cli label --help # 存在即满足
```
## 依赖的 Shortcuts
| Shortcut | 关键参数 | 用途 |
|----------|----------|------|
| `issue +list` | `--state/-s`、`--keyword/-k`、`--label`(标签ID)、`-m`、`-a`、`-p`、`-l`、`--format json` | 批量拉取开放 Issue`number`/`subject`/`comment_journals_count`/`tags`/`created_at` |
| `issue +view` | `--number/-n`**Web 编号**)、`--format json` | 取单条 `description` 正文 |
| `issue +comments` | `--number/-n`、`-p`、`-l` | 读已有评论(**幂等检查**:是否已存在关联标记) |
| `issue +comment` | `--number/-n`、`--body/-b` | 在重复项上发布「指向主 Issue」的关联评论 |
| `issue +close` | `--number/-n`、`--comment/-c` | 关闭重复项(可选,需确认) |
| `issue +update` | `--number/-n`、`--label`(标签ID) | 可选:给重复项打「重复」标签(幂等标记) |
| `label +list` | — | 确认是否存在「重复/duplicate」标签并取其 ID |
> ⚠️ `--number` 取的是 **Web URL 编号**(如 `#21`),来自 `issue +list` 返回的 `number` 字段,**不是** `database_id`
## 工作流程
```
1. issue +list --state open --limit 100 --format json
→ 取全部开放 Issue必要时 --page 翻页;大仓可用 --keyword 预筛某主题)
2. 取每条的 number / subject / comment_journals_count / tags / created_at
3. 粗筛候选对:相同标签、标题共享组件/模块词、或同作者连续提交
4. issue +view --number N仅对候选
→ 取 description 正文,与候选对做相似度比对
5. 聚类 + 主从判定 → 生成《重复 Issue 收敛报告》(见下)
----- 以上为只读分析,默认到此为止 -----
6. (用户确认后)幂等检查(主用评论幂等):
issue +comments --number N → 读 data.journals[],看 is_journal_detail=false 的 notes
是否已有「🔁 疑似重复 / duplicate-of」标记 → 有则跳过
再查 status_name=关闭 → 已关闭则跳过
7. (用户逐条确认后)写动作:
- issue +comment --number N --body "..." → 关联评论(主幂等依据)
- issue +close --number N --comment "..." → 可选,关闭重复项
- (标签标记 `issue +update --label` 实测不可靠,见「已知限制」,不建议依赖)
```
## 判定规则参考
### 相似度判定01
综合 **词面相似度(标题+正文关键词 Jaccard****Agent 语义判断**,给出分数与一句话理由:
| 分数区间 | 判定 | 建议动作 |
|----------|------|----------|
| ≥ 0.85 | **高度疑似重复**(正文几乎一致/同作者同时间) | 关联评论 + 建议关闭 |
| 0.600.85 | **疑似重复**(主题相同,细节有出入) | 关联评论,由人决定是否关闭 |
| 0.400.60 | **相关但非重复**(同模块不同问题) | 仅在报告里「相关项」列出,**不**关联、**不**关闭 |
| < 0.40 | 不相关 | 不处理 |
> 强信号(任一命中即可显著加分):正文逐字相同、同作者同一分钟内提交、标题仅序号/编号差异(如 "测试 issue 1" vs "测试 issue 2")。
> 必须避免**过度合并**症状不同如「描述丢失」vs「状态框变红」vs「关闭时间缺失」即使都关于 `+view/+update`,也应判为「相关但非重复」。
### 主 Issue 选择(每个重复簇选 1 个)
按优先级依次比较,取首个胜出者:
1. `comment_journals_count` 最大(讨论最充分);
2. `created_at` 最早(先提出);
3. 正文 `description` 较长/更完整。
### 幂等规则(避免重复评论/重复关闭)— 已实测验证
对每个拟处理的重复项 `N`,执行写动作前:
1. **评论幂等(主,已验证可靠)**`issue +comments --number N`,读 `data.journals[]`**仅看 `is_journal_detail=false` 的条目的 `notes`**;若含标记串(`🔁 疑似重复` / `duplicate-of` / `重复,指向 #`)→ 跳过评论。
- 响应结构:`data` 是**对象**,评论在 `data.journals[]`;每条含 `is_journal_detail`true=系统动态如「创建了疑修/将状态更改为关闭」false=文字评论)、`notes`(评论正文)、`operate_content`(动态描述)。系统动态 `notes` 为空,须过滤。
2. **状态幂等(已验证可靠)**`issue +list --state closed` 含该编号,或 `+view``status_name=关闭` → 跳过关闭。
3. **标签幂等(不推荐,见「已知限制」)**`issue +update --label` 实测返回 `ok` 但标签未真正生效,**不可靠**,不要依赖它做幂等判定。
## 关联评论模板
在**重复项**上发布(`issue +comment --number <重复项> --body "..."`
```markdown
🔁 **疑似重复 Issue**
本 Issue 与 #<主Issue编号> 描述的问题高度相似,已标记为重复项。
- 主 Issue<主Issue标题> → https://www.gitlink.org.cn/<owner>/<repo>/issues/<主Issue编号>
- 相似度:<分数><一句话理由>
请到主 Issue 继续跟进;如确认重复,本 Issue 将被关闭。
(由 gitlink-duplicate-detector 辅助识别,最终以维护者判断为准)
```
关闭时留言(`issue +close --number <重复项> --comment "..."`
```markdown
关闭:与 #<主Issue编号> 重复,后续讨论请移步主 Issue。
```
## 使用示例
> 以下命令在目标仓库的 git 目录下可省略 `--owner/--repo`(自动从 `git remote origin` 解析。AI 场景统一加 `--format json`
```bash
# 0) 前置:确认版本能力 + 登录
gitlink-cli auth status
gitlink-cli issue +comments --help # 存在 → 版本满足
gitlink-cli label +list --owner <o> --repo <r> --format json # 看是否有「重复」标签及 ID
# 1) 拉取全部开放 Issue含 number/subject/comment_journals_count/tags/created_at
gitlink-cli issue +list --owner <o> --repo <r> --state open --limit 100 --format json
# 2) (可选)按主题预筛,缩小比对范围
gitlink-cli issue +list --owner <o> --repo <r> --keyword "登录" --state open --format json
# 3) 对候选对取正文做相似度比对
gitlink-cli issue +view --owner <o> --repo <r> --number 11 --format json
gitlink-cli issue +view --owner <o> --repo <r> --number 12 --format json
# 4) 幂等检查:读重复项已有评论,看是否已有关联标记
gitlink-cli issue +comments --owner <o> --repo <r> --number 12 --format json
# 5) 报告输出后,用户确认 → 发布关联评论(写操作,务必先确认)
gitlink-cli issue +comment --owner <o> --repo <r> --number 12 \
--body "🔁 疑似重复 Issue本 Issue 与 #11 高度相似(正文逐字一致,相似度 0.98)。主 Issue → https://www.gitlink.org.cn/<o>/<r>/issues/11"
# 6) ⚠️ 不推荐:打「重复」标签。实测 issue +update --label 返回 ok 但标签未生效,
# 不可靠。幂等请依赖步骤 4 的评论标记,而非标签。
# gitlink-cli issue +update --owner <o> --repo <r> --number 12 --label 298661
# 7) 可选:关闭重复项(破坏性,必须确认)
gitlink-cli issue +close --owner <o> --repo <r> --number 12 \
--comment "关闭:与 #11 重复,后续讨论请移步主 Issue。"
```
## 输出:重复 Issue 收敛报告Markdown
````markdown
# 重复 Issue 收敛报告 — <owner>/<repo>
扫描范围:开放 Issue 共 N 条 | 生成时间:<时间> | 模式dry-run只读
## 🔴 重复簇 1高度疑似
- **主 Issue**#11 `[test] batch-close 测试 issue 1`(作者 wbtiger2026-05-130 评论)
- **重复项**
- #12 `[test] batch-close 测试 issue 2` — 相似度 **0.98**(正文逐字相同、同作者同时间)
- **建议动作**:在 #12 发关联评论 → (确认后)关闭 #12
## 🟡 相关但非重复(不合并,仅提示)
- 主题「`+view`/`+update` 返回数据异常」:
- #15 `issue +view 返回的数据与网页显示不一致`
- #5 `认领/执行任务时描述信息消失`
- #18 `+update 后状态框变红色`
- #14 `pr +view 缺少 PR 关闭时间`
→ 症状各异(相似度 0.40.55),建议分别处理,不予合并。
## ✅ 待用户确认的写动作清单
| 重复项 | 动作 | 命令 |
|--------|------|------|
| #12 | 评论 + 关闭 | `issue +comment ...``issue +close --comment ...` |
````
> 真实数据跑通的完整报告见 [`examples/duplicate-detection-workflow.md`](examples/duplicate-detection-workflow.md)。
## 已知限制实测v0.2.0-dev / 本地源码版)
- **`issue +update --label` 不可靠**:实测在 `z2_cc/gitlink_help_center``--label <id>` 返回 `ok`,但 `+view`/`+list` 的 `tags` 均为空,标签未真正生效。**因此幂等一律以评论(`+comments` 的 `notes` 标记)为准,不要依赖标签。**
- **`+comments` 含系统动态**:返回的 `data.journals[]` 混有「创建了疑修 / 状态更改为关闭」等系统动态(`is_journal_detail=true``notes` 空);判定文字评论须过滤 `is_journal_detail=false`
- **`+list` 不含正文**:聚类前对每个候选 `+view``description`;大仓先用 `--keyword`/作者/时间窗粗筛降量。
- **`create`/`view` 不返回 Web 编号**`issue +create` 与 `+view` 的响应里 `number` 可能为空Web 编号以 `issue +list``number` 字段为准。
## 注意事项
- **默认 dry-run**:首次运行只产出报告,**不**评论/关闭/打标;所有写动作需用户逐条确认。
- **不碰他人仓库**:只在你有写权限、或用户明确指定的仓库执行写动作;在他人公开仓只做只读分析。
- **`--number` = Web 编号**(来自 `+list``number` 字段),勿用 `database_id`
- **正文需 `+view` 补取**`+list` 不含 `description`,聚类前对候选对逐个 `+view`;大仓库注意调用次数,先用 `--keyword`/标签/作者粗筛。
- **避免过度合并**:宁可漏报(列「相关项」)不可误并;维护者判断优先。
- **幂等**:写动作前用 `+comments` 查标记、用 `tags` 查标签,已处理则跳过。
- **不分配类别标签**:与 triage 划清边界;本 Skill 至多使用「重复」这一功能性标记标签。

View File

@ -1,202 +0,0 @@
# 重复 Issue 检测 — 端到端工作流示例与验证记录
> 配套文档:[`../SKILL.md`](../SKILL.md)
> 本文记录一次**真实跑通**的完整工作流(只读分析 + 写动作计划),含真实命令输出,作为「使用示例 + Agent 平台验证结果」交付物。
## 验证环境
| 项 | 值 |
|----|----|
| Agent 平台 | Claude Code |
| gitlink-cli | `local-build`(本仓库源码编译产物,**非** npm 发布版 v0.1.13 |
| 登录用户 | `z2_cc``auth status` ✓) |
| 测试目标 | `Gitlink/gitlink-cli`19 条开放 Issue |
| 验证日期 | 2026-06-17 |
> 选 `Gitlink/gitlink-cli` 是因其开放 Issue 较多、含真实重复/测试 Issue**写动作未在该他人仓库执行**,仅做只读分析 + 命令语法已 `--help` 验证。
## 步骤 1拉取全部开放 Issue
```bash
gitlink-cli issue +list --owner Gitlink --repo gitlink-cli --state open --limit 50 --format json
```
解析 `data.issues[]`,取 `number`(Web编号) / `subject` / `comment_journals_count` / `tags` / `created_at`
```
all_count: 19
#21 [3评论] 2026-06-14 dataset 快捷命令需要的后端 API 支持
#20 [1评论] 2026-06-12 bug: api 命令单次调用不替换 :owner/:repo 占位符0.2.0
#6 [3评论] 2026-04-25 只要创建Iusse就让Agent开始干活
#1 [1评论] 2026-04-01 CLI测试Issue - 已更新标题
#18 [0评论] 2026-05-22 giklink-cli issue +update后issue状态框变红色
#17 [0评论] 2026-05-21 API是否支持自动读取仓库内文件README等
#16 [5评论] 2026-05-19 [Bug] Windows 平台完全不可用Release 缺少 Windows 二进制…
#14 [1评论] 2026-05-16 pr +view 的返回中缺少PR关闭时间
#4 [4评论] 2026-04-18 PR使用gd login无法自动完成
#5 [1评论] 2026-04-24 通过这个skill认领任务描述信息消失
#7 [1评论] 2026-04-25 目前看Gitlink-skill返回的PR ID和实际的不符
#15 [1评论] 2026-05-19 issue +view 返回的数据与网页显示不一致
#11 [0评论] 2026-05-13 [test] batch-close 测试 issue 1
#12 [0评论] 2026-05-13 [test] batch-close 测试 issue 2
#9 [2评论] 2026-05-12 feat(api): 希望 Issue API 支持按项目内序号查询
#8 [1评论] 2026-05-12 Test: PR#7 标题已修改
#10 [1评论] 2026-05-12 [test] PR#11 v1 API 测试 - 已更新
#2 [4评论] 2026-04-03 gitlink-cli 使用讨论与反馈收集
#3 [1评论] 2026-04-04 Skill测试Issue-0404 (已更新)
```
## 步骤 2粗筛候选对
标题信号已显出两个簇:
- **簇 A**`#11` / `#12` —— `[test] batch-close 测试 issue 1/2`,同作者同时间,强重复嫌疑。
- **簇 B**(主题「`+view`/`+update` 返回数据异常」):`#5` / `#14` / `#15` / `#18` —— 需看正文区分「重复」还是「相关」。
## 步骤 3取正文做相似度比对
```bash
gitlink-cli issue +view --owner Gitlink --repo gitlink-cli --number 11 --format json
gitlink-cli issue +view --owner Gitlink --repo gitlink-cli --number 12 --format json
```
| 编号 | 作者 | 创建时间 | 正文(节选) |
|------|------|----------|--------------|
| #11 | wbtiger | 2026-05-13 19:06 | `PR #12 测试用,验证后关闭` |
| #12 | wbtiger | 2026-05-13 19:06 | `PR #12 测试用,验证后关闭` |
**正文逐字相同、同作者、同一分钟提交**,相似度 **0.98**,判为**高度疑似重复**。
簇 B 正文各异(#5「描述丢失」、#14「关闭时间缺失」、#15「返回旧数据」、#18「状态框变红」相似度 0.400.55 → **相关但非重复**,不合并。
## 步骤 4幂等检查写动作前
```bash
gitlink-cli issue +comments --owner Gitlink --repo gitlink-cli --number 12 --format json
```
实测输出(节选)—— 注意 `+comments` 返回的是**活动日志**,需区分:
```json
[
{ "is_journal_detail": true, "operate_content": "创建了<b>疑修</b>", "notes": "", "user": {"login":"wbtiger"} },
{ "is_journal_detail": true, "operate_content": "…", "notes": "" },
{ "is_journal_detail": true, "operate_content": "…", "notes": "" }
]
```
**判定规则**:仅当某条 `notes` **非空且含标记串**`duplicate-of` / `重复,指向 #`)才视为已处理。此处 3 条均为系统日志(`notes` 空)→ **未处理,可执行写动作**
> 真实文字评论才会带 `notes`(如 #21 的「新建声明: 我来解决」)。`comment_journals_count` 与 `+comments` 条数口径不同(后者含系统日志),幂等一律以 `notes` 内容为准。
另查 `issue +list``tags`#12 为空 → 未打「重复」标签 → 双重确认未处理。
## 步骤 5输出报告dry-run默认产物
````markdown
# 重复 Issue 收敛报告 — Gitlink/gitlink-cli
扫描:开放 Issue 19 条 | 模式dry-run只读 | 2026-06-17
## 🔴 重复簇 1高度疑似
- 主 Issue#11 `[test] batch-close 测试 issue 1`wbtiger2026-05-13正文"PR #12 测试用,验证后关闭"
- 重复项:
- #12 `[test] batch-close 测试 issue 2` — 相似度 0.98(正文逐字一致、同作者同时间)
- 幂等:#12 无 duplicate 标记评论、无「重复」标签 → 待处理
- 建议动作:评论关联 #11 → 打「重复」标签 → 关闭 #12
## 🟡 相关但非重复(仅提示,不合并)
主题「+view/+update 返回数据异常」:#5 / #14 / #15 / #18,症状各异(相似度 0.400.55),分别处理。
## ✅ 待确认写动作
| 重复项 | 动作 | 命令 |
|--------|------|------|
| #12 | 评论+打标+关闭 | 见步骤 6 |
````
## 步骤 6写动作计划需用户逐条确认未在他人仓库执行
```bash
# 6.1 取「重复」标签 ID已确认存在id=298661描述"表示已存在类似的疑修"
gitlink-cli label +list --owner Gitlink --repo gitlink-cli --format json
# 6.2 关联评论
gitlink-cli issue +comment --owner Gitlink --repo gitlink-cli --number 12 \
--body "🔁 疑似重复 Issue本 Issue 与 #11 高度相似(正文逐字一致,相似度 0.98)。主 Issue → https://www.gitlink.org.cn/Gitlink/gitlink-cli/issues/11"
# 6.3 打「重复」标签做幂等标记
gitlink-cli issue +update --owner Gitlink --repo gitlink-cli --number 12 --label 298661
# 6.4 关闭重复项
gitlink-cli issue +close --owner Gitlink --repo gitlink-cli --number 12 \
--comment "关闭:与 #11 重复,后续讨论请移步主 Issue。"
```
> 以上命令语法均经 `--help` 验证可用;因 `Gitlink/gitlink-cli` 非登录用户所有,**未实际执行写动作**。如需完整写链路验证,请在 `z2_cc` 自有仓库上重跑(可先 `issue +create` 造两条重复 Issue
## 关键验证结论
| 能力 | 命令 | 状态 |
|------|------|------|
| 批量拉取(含 Web 编号/标签/评论数/时间) | `issue +list --state --limit --format json` | ✅ 真实返回 |
| 关键词预筛 | `issue +list --keyword Windows` → 命中 1 条 | ✅ |
| 取正文 | `issue +view --number 11/12``description` | ✅ |
| 读评论(幂等) | `issue +comments --number 12` → 含 `notes`/`is_journal_detail` | ✅ |
| 标签管理 | `label +list` → 「重复」标签 id=298661 | ✅ |
| 评论/关闭 | `issue +comment` / `+close --number` | ✅ **实际执行成功**(见附录) |
| 打标签 | `issue +update --label` | ⚠️ 返回 ok 但未生效(见附录) |
> ⚠️ 版本前提:以上能力依赖含 `+comments`/`label`/`--keyword` 的 gitlink-cli本仓库源码已具备npm 发布版 v0.1.13 不具备)。参赛验证基于本地源码编译产物。
---
## 附写链路实测验证z2_cc/gitlink_help_center
为验证写动作,在 z2_cc 拥有 Owner 权限的复刻仓 `z2_cc/gitlink_help_center` 实跑全链路(该仓已自带「重复」标签 id=315565、「测试」标签 id=315564
### A. 造两条高度相似的测试 Issue
```bash
gitlink-cli issue +create --owner z2_cc --repo gitlink_help_center -t "【dup-test】登录按钮点击无反应" -b "## 复现步骤 ..." # → id=144589, Web #22
gitlink-cli issue +create --owner z2_cc --repo gitlink_help_center -t "【dup-test】登录按钮点了没反应" -b "## 复现步骤 ..." # → id=144590, Web #23
```
(正文几乎逐字一致、标题同义 → 相似度 ~0.95,构造为重复对)
### B. 幂等检查(只读)
```bash
gitlink-cli issue +comments --owner z2_cc --repo gitlink_help_center --number 23 --format json
```
`data.journals[]` 仅 1 条系统动态(`is_journal_detail=true``notes` 空),无 duplicate 标记 → **可执行写动作**
### C. 写动作执行结果
| 动作 | 命令 | 结果 |
|------|------|------|
| 关联评论 | `issue +comment --number 23 --body "🔁 疑似重复…指向 #22"` | ✅ 发布成功journal id=476901 |
| 打「重复」标签 | `issue +update --number 23 --label 315565` | ⚠️ 返回 ok`+list`/`+view` 的 `tags=[]`**未生效** |
| 关闭重复项 | `issue +close --number 23 --comment "关闭:与 #22 重复…"` | ✅ 关闭成功 |
### D. 验证写动作落地
```bash
gitlink-cli issue +comments --owner z2_cc --repo gitlink_help_center --number 23 --format json
```
实测 `data.journals[]`5 条):
```
[0] is_journal_detail=true operate_content="创建了<b>疑修</b>" notes=""
[1] is_journal_detail=false operate_content="" notes="🔁 疑似重复 Issue本 Issue 与 #22 高度相似…"
[2] is_journal_detail=true operate_content="将状态由<b>新增</b>更改为<b>关闭</b>" notes=""
[3] is_journal_detail=true operate_content="将结束日期设置为<b>2026-06-17</b>" notes=""
[4] is_journal_detail=false operate_content="" notes="关闭:与 #22 重复,后续讨论请移步主 Issue #22。"
```
```bash
gitlink-cli issue +list --owner z2_cc --repo gitlink_help_center --state closed --format json
```
`#23 status=关闭``#22 status=新增`(主 Issue 保持开放)。✅
### E. 结论
- **评论 + 关闭链路完全可用**,且 `+comments` 能可靠回读评论(`is_journal_detail=false` 的 `notes`)→ **评论幂等成立**
- **`+update --label` 不可靠**(返回 ok 但标签未生效)→ 幂等**不依赖标签**,仅用评论标记。
- 验证后已清理测试 Issue`issue +delete` / 关闭清理),不在帮助中心仓留痕。

View File

@ -1,167 +0,0 @@
# gitlink-issue-triage API 参考
> 分拣相关的 gitlink-cli 命令返回字段说明。先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解 envelope `{ok, data, meta}` 与全局参数。
## 前置ID 解析命令
分拣写入参数(`--label`/`--assignee`/`--priority`)都吃 **ID**,必须先解析。
### `label +list` — 标签name → id
```bash
gitlink-cli label +list --format json
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `data.issue_tags[].id` | int | **标签 ID写入时传这个** |
| `data.issue_tags[].name` | string | 标签名称GitLink 默认为中文:缺陷/功能/疑问/文档/任务…) |
| `data.issue_tags[].color` | string | 颜色hex |
| `data.issue_tags[].description` | string | 标签说明 |
### `label +assigners` — 可指派人login → id
```bash
gitlink-cli label +assigners --format json
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `data.assigners[].id` | int | **用户 ID`--assignee` 传这个)** |
| `data.assigners[].login` | string | 登录名 |
| `data.assigners[].name` | string | 显示名/角色(如「后端组」) |
### `label +priorities` — 优先级name → id
```bash
gitlink-cli label +priorities --format json
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `data.priorities[].id` | int | 优先级 ID`--priority` 传这个) |
| `data.priorities[].name` | string | 名称(如 高/正常/低) |
### `label +create` — 补建缺失标签(确认后)
```bash
gitlink-cli label +create --name <name> --color <hex_without_#> --format json
```
| 参数 | 说明 |
|------|------|
| `-n, --name` | 标签名称(必填) |
| `-c, --color` | 颜色 hex不带 #,如 `ff0000`),可选 |
---
## 分拣主体命令
### `issue +list` — 列出 Issue
```bash
gitlink-cli issue +list --state open --format json
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `data.issues[].number` | int | **Issue 编号web URL 中的编号,写入用这个)** |
| `data.issues[].id` | int | Issue 内部 ID |
| `data.issues[].name` / `subject` | string | 标题 |
| `data.issues[].tags` | array | 已打标签(**为空 = 未分拣,需处理** |
| `data.issues[].assigners` | array | 已指派人 |
| `data.issues[].priority` | object | 优先级 `{id, name}` |
| `data.issues[].author` | object | 作者 `{login, name}` |
> ⚠️ `--state` 仅影响统计计数,返回列表可能含所有状态。**幂等筛选**:保留 `tags` 为空的 Issue跳过已打标签的。
### `issue +view` — 查看详情(语义分析用)
```bash
gitlink-cli issue +view --number <n> --format json
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `data.issue.number` | int | Issue 编号 |
| `data.issue.subject` | string | 标题 |
| `data.issue.description` | string | **描述(语义分析的主要输入)** |
| `data.issue.status_id` | int | 状态 ID |
| `data.issue.tags` | array | 已打标签(`[{id,name,color}]`**为空 = 未分拣** |
| `data.issue.priority` | object | 优先级 |
> 写入参数用 `--number`web 编号),不是内部 `id`
### `issue +batch-update` — 批量更新(同标签批量场景)
```bash
gitlink-cli issue +batch-update \
--numbers <a,b,c> \
--label <单个id> \
[--assignee <id>] [--priority <id>] \
[--dry-run] --format json
```
| 参数 | 说明 |
|------|------|
| `-n, --numbers` | 逗号分隔的 Issue 编号 |
| `-l, --label` | 标签 **ID**;⚠️ **集合式**——把传入的标签集合打到 `--numbers` 里**每一个** Issue**非按位置对应** |
| `-a, --assignee` | 指派人 **ID** |
| `-m, --milestone` / `-p, --priority` | 里程碑 / 优先级 ID |
| `-s, --state` | open / closed / 数字 status_id |
| `--dry-run` | **预览不写入** |
| `--from` | 从 CSV 读编号(大批量场景) |
> ⚠️ **实测**`--label a,b,c` 会把 {a,b,c} 全部打到这批每个 Issue集合式。因此**仅用于多个 Issue 共用同一(组)标签**;各 Issue 标签不同时改用下方 Raw API。`--dry-run` 输出含 `updates.issue_tag_ids`(扁平数组,印证集合式)。
### `issue +update` — 单个 Issue 更新
```bash
gitlink-cli issue +update --number <n> --assignee <id> --format json
```
| 参数 | 说明 |
|------|------|
| `-n, --number` | Issue 编号 |
| `-l, --label` | ⚠️ **实测不可用**CLI 发单数 `issue_tag_id` 被平台忽略,标签打不上。打标签改用 Raw API `issue_tag_ids` |
| `-a, --assignee` | 指派人 **ID** |
| `-t, --title` / `-b, --body` | 新标题/描述(更新会自动保留原 subject/description不会清空 |
| `-s, --state` / `-m, --milestone` / `-p, --priority` | 状态/里程碑/优先级 |
### `issue +comment` — 添加引导评论
```bash
gitlink-cli issue +comment --number <n> --body "<评论内容>" --format json
```
| 参数 | 说明 |
|------|------|
| `-n, --number` | Issue 编号 |
| `-b, --body` | 评论内容(支持 Markdown |
---
## Raw API 兜底
Shortcut 未覆盖时用 Raw API。**Issue 更新需先 GET 拿到当前 `subject`/`description` 再带上提交**,否则可能清空描述(见 gitlink-shared 已知坑)。
```bash
# 打标签issue_tag_ids 为标签 ID 数组)
gitlink-cli api PATCH /:owner/:repo/issues/:number --body '{
"issue_tag_ids": [<tag_id>, ...],
"subject": "<原标题>",
"description": "<原描述>"
}'
```
| 字段 | 说明 |
|------|------|
| `issue_tag_ids` | 标签 **ID 数组**(不是名称) |
| `subject` / `description` | 必须回带原值,防止清空 |
## 数据获取最佳实践
1. **始终 `--format json`** 便于解析。
2. 写入参数一律传 **ID**:标签/指派人/优先级都先解析为 ID。
3. **幂等**`issue +list` 后客户端筛 `labels` 为空的,避免重复分拣。
4. 批量前先 `--dry-run` 预览,核对 `--numbers``--label`/`--assignee` 位置对应。

View File

@ -1,7 +1,7 @@
---
name: gitlink-issue-triage
version: 1.2.0
description: "当用户需要批量处理新提交的 GitLink Issue自动分类、打标签、分配责任人、添加引导评论时触发。适用于 Issue 积压无人分流、新 Issue 缺少分类标签、需要按类别指派维护者等场景。"
version: 1.0.0
description: "Issue 自动分拣:根据 Issue 内容自动分类、打标签、分配责任人、添加引导评论。当用户需要自动处理新提交的 Issue 时触发。"
metadata:
requires:
bins: ["gitlink-cli"]
@ -11,207 +11,77 @@ metadata:
# gitlink-issue-triageIssue 自动分拣)
**CRITICAL — 开始前必须先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md),其中包含认证、权限处理和 API 注意事项。**
**CRITICAL — 所有写入/删除操作前务必先确认用户意图分拣属于批量写入必须先出方案→用户确认→dry-run 预览→再执行。**
**CRITICAL — GitLink 操作只能用 `gitlink-cli`。禁止用 `gh`GitHub CLI操作 GitLink 资源。`gh` 仅适用于 GitHub 平台。**
**CRITICAL — 所有 Shortcuts 在执行写入/删除操作前,务必先确认用户意图。**
## 核心原则
## 说明
1. **语义分类为主,关键词表为辅**:你是 AI Agent价值在于读懂 Issue 意图(如「登录后白屏、控制台报 500」即使没有「bug」字眼也应判为 Bug。下方关键词表只是兜底/加速,不要退化成正则匹配。
2. **建议优先,确认后写入**:先输出「分拣方案表」给用户确认,**禁止未经确认直接打标签/改指派人**。尤其禁止用 `--yes` 绕过确认,除非用户明确说「直接应用/不用确认」。
3. **幂等**:只处理「尚未分拣」的 Issue无标签或仅有默认标签避免对已分拣 Issue 重复操作。
4. **打标签用 Raw API批量仅限同标签**:实测 `issue +update --label` 不可用、`+batch-update --label` 是集合式(整组标签打到每个 Issue故各 Issue 不同标签时用 Raw API `issue_tag_ids`(详见 Step 5仅当多 Issue 共用同一标签时才用 `+batch-update`
本 Skill 组合多个 gitlink-cli 命令,实现 Issue 的自动化分类和处理流程:
## 工作流概览
1. 获取新提交的 Issue 列表
2. 根据 Issue 内容(标题 + 描述)自动判断类别
3. 为 Issue 打上对应标签、分配责任人
4. 添加引导评论
| 阶段 | 操作 | 命令 |
|------|------|------|
| ① 解析 ID必做前置 | 取仓库标签/可指派人/优先级,建立 名称→ID 映射 | `label +list` / `label +assigners` / `label +priorities` |
| ② 取未分拣 Issue | 拉取 open Issue客户端筛掉已打标签的 | `issue +list` |
| ③ 语义分析 | 逐个读标题+描述,判类别/标签/责任人/评论 | `issue +view` |
| ④ 出方案 | 输出「分拣方案表」,等用户确认 | (无写入) |
| ⑤ 打标签 | 用户确认后,逐 Issue 用 Raw API 打标签(不同标签);同标签可批量 | `api PATCH .../issues/:n` / `+batch-update` |
| ⑥ 引导评论 | 为每个 Issue 添加分类引导评论 | `issue +comment` |
## 依赖的 Shortcuts
---
| Shortcut | 用途 |
|----------|------|
| `issue +list` | 获取待处理的 Issue 列表 |
| `issue +view` | 查看 Issue 详细内容 |
| `issue +update` | 修改 Issue 状态/标签 |
| `issue +comment` | 添加评论 |
| `label +list` | 查看可用标签 |
| `user +info` | 查询用户信息 |
## 详细工作流
## 处理流程
### Step 1解析 ID**必做前置,切勿跳过**
GitLink 的标签、指派人、优先级参数都吃 **ID 而非名称**。先拉取并建立映射:
```bash
# 标签name → id返回在 data.issue_tags[];标签名因仓库而异,如某仓库为 缺陷/功能/疑问/文档…)
gitlink-cli label +list --format json
# 可指派人login → id如 alice→101
gitlink-cli label +assigners --format json
# 优先级name → id数值因仓库而异如某仓库为 低→1/正常→2/高→3/紧急→4以实际输出为准
gitlink-cli label +priorities --format json
```
> 没有 ID 映射就无法正确执行 Step ⑤⑥。若目标标签不存在,见 Step 4「补建标签」。
### Step 2取未分拣 Issue幂等筛选
```bash
# 拉取所有 open Issue
gitlink-cli issue +list --state open --format json
1. issue +list --state open → 获取所有打开的 Issue
2. issue +view --number {id} → 查看 Issue 详情
3. 分析 subject + description → 判断 Issue 类别
4. label +list → 查看可用标签
5. issue +update --label {label} → 打标签
6. issue +comment --body "..." → 添加引导评论
```
筛选规则(客户端过滤):**保留尚未打标签的 Issue**`tags` 字段为空),跳过已有分类标签的,避免重复分拣。
### Step 3语义分析
对每个待分拣 Issue
```bash
gitlink-cli issue +view --number <issue_number> --format json
```
读取 `subject` + `description`,按下方「分类规则参考」判断类别、推荐标签、推荐责任人角色、引导评论要点。
### Step 4出「分拣方案表」建议不写入
输出一张表给用户确认,**此阶段不执行任何写入**
```markdown
| # | 标题 | 判定类别 | 标签(id) | 责任人(id) | 评论文案要点 |
|---|------|---------|----------|-----------|-------------|
| 12 | 登录后白屏 500 | Bug | bug(1) | bob(102) | 请补浏览器/复现步骤/后端日志 |
| 13 | 希望支持暗黑模式 | Feature | enhancement(2) | alice(101) | 请确认范围:全局/页面级、是否跟随系统 |
```
**补建标签(可选)**:若方案需要的标签在 `label +list` 中不存在(如缺 `bug`),不要静默跳过,也**不要擅自创建**——在方案表中标注「标签缺失」,待用户确认后用 `gitlink-cli label +create --name bug` 创建,再继续。
**等待用户确认**:用户没说「确认/执行」前,停在 Step 4。**禁止用 `--yes` 自行推进。**
### Step 5打标签用户确认方案后
> ⚠️ **实测要点2026-06-15 端到端验证)**
> - `issue +update --label <id>` **不可用**——CLI 发送单数 `issue_tag_id`,平台忽略,标签打不上。
> - `issue +batch-update --label a,b,c` 是**集合式**:把 `{a,b,c}` 打到 `--numbers` 里**每一个** Issue**不是**按位置对应。仅适合「多个 Issue 共用同一(组)标签」。
> - 可用的打标签方式是 Raw API 的 `issue_tag_ids`(复数数组)。
**情形 A各 Issue 标签不同(最常见)→ 逐 Issue 用 Raw API已验证**
```bash
gitlink-cli api PATCH /:owner/:repo/issues/<number> --body '{
"issue_tag_ids": [<标签id>],
"subject": "<原标题>",
"description": "<原描述>"
}'
```
`issue_tag_ids` 是数组,**整体替换**该 Issue 的标签集;务必回带 `subject`/`description`,否则描述会被清空(见 gitlink-shared 已知坑)。
**情形 B多个 Issue 共用同一标签 → 批量(先 dry-run 再执行):**
```bash
# dry-run 预览(同一标签打到这批所有 Issue
gitlink-cli issue +batch-update --numbers <a,b,c> --label <单个id> --dry-run --format json
# 核对后去掉 --dry-run 正式执行
```
**指派人**`issue +update --number <n> --assignee <user_id>``user_id` 来自 `label +assigners`)。若 `label +assigners` 为空(如个人仓库无可指派成员),**留空并在方案表注明**,不要乱指派。
### Step 6引导评论
为每个 Issue 添加分类引导评论(语气专业,包含分类理由 + 需要补充的信息):
```bash
gitlink-cli issue +comment --number 12 --body "已自动分拣为 **Bug**,转交 @bob
为加快定位,请补充:运行环境、复现步骤、浏览器控制台与后端日志。维护者会尽快处理。"
```
---
## 分类规则参考
### 类别判定(语义优先,关键词兜底)
| 类别 | 标题关键词 | 建议标签 | 建议负责人 |
|------|-----------|---------|-----------|
| Bug | 错误、失败、异常、bug、crash、报错 | bug | 项目维护者 |
| 功能需求 | 建议、希望、需要、feature、支持 | enhancement | PM |
| 文档 | 文档、README、文档缺失、拼写 | documentation | 文档负责人 |
| 问题咨询 | 请问、怎么、如何、help、question | question | 社区支持 |
| 性能 | 慢、卡顿、性能、优化、performance | performance | 核心开发者 |
| 类别 | 语义信号 | 关键词兜底 | 建议标签 | 责任人角色 |
|------|---------|-----------|----------|-----------|
| Bug | 运行时报错、崩溃、行为异常、阻断主流程 | 错误/失败/异常/crash/报错/500/白屏 | bug | 后端或前端(按错误来源) |
| 功能需求 | 希望新增能力、改进现有行为 | 建议/希望/需要/feature/支持 | enhancement | PM / 对应模块开发 |
| 文档 | 文档缺失/错误/拼写 | 文档/README/拼写 | documentation | 文档负责人 |
| 问题咨询 | 询问用法、求助 | 请问/怎么/如何/help/question | question | 社区支持 / 文档 |
| 性能 | 慢、卡顿、资源占用 | 慢/卡顿/性能/优化/performance | performance | 核心开发者 |
> 上表「建议标签」是语义类别名,**实际标签名以 `label +list` 为准**——GitLink 默认标签是中文(缺陷/功能/疑问/文档/任务…),需先把类别映射到仓库实际标签的 ID 再打。
### 角色 → 默认责任人映射(需用 `label +assigners` 的实际 ID 替换)
| 角色 | 何时指派 |
|------|---------|
| 后端 | 服务端错误、API、数据库相关 |
| 前端 | UI、样式、浏览器端错误 |
| PM | 需求范围、优先级决策 |
| 文档 | 文档/问答类 |
| 核心开发者 | 性能、架构、安全 |
> 实际指派时,把「角色」替换为 `label +assigners` 中对应的 **user_id**。若角色无对应成员,**留空并在方案表注明**,不要乱指派。
---
## 命令速查
## 使用示例
```bash
# 前置:解析 ID
gitlink-cli label +list --format json # 标签 name→id
gitlink-cli label +assigners --format json # 可指派人 login→id
gitlink-cli label +priorities --format json # 优先级 name→id
gitlink-cli label +create --name <name> --color <hex> # 补建缺失标签(确认后)
# 1. 获取所有打开的 Issue
gitlink-cli issue +list --owner myuser --repo myrepo --state open --format json
# 分拣主体
gitlink-cli issue +list --state open --format json # 取未分拣(客户端筛 tags 为空的)
gitlink-cli issue +view --number <n> --format json # 读详情做语义分析(标签字段为 tags
# 2. 查看某个 Issue 的详细内容
gitlink-cli issue +view --owner myuser --repo myrepo --number 5 --format json
# 打标签(已验证可用):
# - 各 Issue 不同标签 → 逐个 Raw APIissue_tag_ids 整体替换)
gitlink-cli api PATCH /:owner/:repo/issues/<n> --body '{"issue_tag_ids":[<id>],"subject":"<>","description":"<>"}'
# - 多 Issue 共用同一标签 → 批量(集合式,先 --dry-run
gitlink-cli issue +batch-update --numbers <a,b,c> --label <单个id> --dry-run
# 3. 查看仓库可用标签
gitlink-cli label +list --owner myuser --repo myrepo
gitlink-cli issue +comment --number <n> --body "<引导评论>" # 引导评论
gitlink-cli issue +update --number <n> --assignee <user_id> # 指派人user_id 来自 label +assigners
# 4. 为 Issue 打标签(假设判断为 bug
gitlink-cli issue +update --owner myuser --repo myrepo --number 5 --state open
# 5. 添加分类引导评论
gitlink-cli issue +comment --owner myuser --repo myrepo --number 5 --body "感谢提交 Issue已自动分类为 **Bug**,请补充以下信息:
- 运行环境(操作系统、版本)
- 复现步骤
- 期望行为与实际行为
项目维护者会尽快处理。"
```
> ⚠️ `issue +update --label``+batch-update --label a,b,c`(多标签)均不可靠,详见红线。
---
## Raw API 参考
打标签的**主要可用方式**是 Raw APIShortcut 的 `--label` 不可靠,见红线)。务必回带 `subject`/`description` 防清空:
```bash
# 打标签issue_tag_ids 为标签 ID 数组,整体替换该 Issue 标签集)
gitlink-cli api PATCH /:owner/:repo/issues/:number --body '{
"issue_tag_ids": [<tag_id>, ...],
"subject": "<原标题>",
"description": "<原描述>"
}'
```
> 字段说明详见 [`REFERENCE.md`](REFERENCE.md)。
---
## 红线与常见错误
- ❌ **未经用户确认就打标签/指派**——必须方案表→确认→执行。
- ❌ **用 `--yes` 绕过确认门**——除非用户明确要求「直接应用」。
- ❌ **用 `issue +update --label` 打标签**——实测 CLI 发单数 `issue_tag_id` 被平台忽略,标签打不上;改用 Raw API `issue_tag_ids`Step 5
- ❌ **用 `+batch-update --label a,b,c` 给不同 Issue 打不同标签**——它是集合式,会把 {a,b,c} 全打到每个 Issue仅用于多 Issue 共用同一标签。
- ❌ **把标签名称当 ID 传**——必须先用 `label +list` 解析为 ID返回在 `data.issue_tags[]`,标签名以实际为准)。
- ❌ **重复分拣已分类 Issue**——Step 2 客户端筛掉 `tags` 非空的。
- ❌ **用 `gh` 操作 GitLink**——只用 `gitlink-cli`
- 所有命令加 `--format json` 便于解析;输出为 `{ok, data, meta}` envelope。
## 注意事项
- 分拣是批量写入,评论会通知 Issue 相关人,内容请专业、可操作。
- `issue +list``--state` 仅影响统计计数,列表可能含全部状态,需客户端二次过滤。
- 若 Issue 描述信息不足以判定类别,在方案表标注「信息不足,建议先发评论索取复现信息」,不要强行分类。
- 每次操作前先列出当前待处理的 Issue评估数量。
- 添加评论前先确认 Issue 内容,避免误分类。
- 标签名称需要先在项目中确认是否存在,不存在则跳过。
- 分配责任人前需确认该用户是否为项目成员。

View File

@ -1,188 +1,81 @@
# Issue 批量自动分拣完整工作流示例
# Issue 自动分拣完整工作流示例
**场景**:仓库 `z2_cc/gitlink-cli` 积压了一批未分类的 open Issue需要批量分流自动判定类别、打标签、指派责任人、添加引导评论。
> 本示例遵循 SKILL.md 的核心原则:**语义分类为主、建议优先确认后写入、幂等、批量为主**。所有写入操作都经过「方案→确认→dry-run→执行」四步。
**场景**:项目收到一个新 Issue需要自动判断类别、打标签、添加引导评论。
## 前置条件
- `gitlink-cli` 已安装并登录`gitlink-cli auth status` 正常)
- `gitlink-cli` 已安装并登录
- 对目标仓库有写入权限
- 已阅读 [`../../gitlink-shared/SKILL.md`](../../gitlink-shared/SKILL.md)
---
## 工作流步骤
## Step 1解析 ID建立 名称→ID 映射)
```bash
gitlink-cli label +list --format json
gitlink-cli label +assigners --format json
gitlink-cli label +priorities --format json
```
**`label +list` 输出示例:**
```json
{
"ok": true,
"data": { "labels": [
{"id": 1, "name": "bug"},
{"id": 2, "name": "enhancement"},
{"id": 3, "name": "documentation"},
{"id": 4, "name": "question"},
{"id": 5, "name": "performance"}
]}
}
```
**`label +assigners` 输出示例:**
```json
{
"ok": true,
"data": { "assigners": [
{"id": 101, "login": "alice", "name": "前端组"},
{"id": 102, "login": "bob", "name": "后端组"},
{"id": 103, "login": "carol", "name": "文档组"}
]}
}
```
→ 建立映射:标签 `bug→1, enhancement→2, question→4`;指派人 `alice→101, bob→102, carol→103`
## Step 2取未分拣 Issue客户端筛掉已打标签的
### Step 1查看待处理的 Issue
```bash
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state open --format json
```
筛出**尚未打标签**的 3 个(已分类的跳过,保证幂等):
| number | subject | labels |
|--------|---------|--------|
| 12 | 登录后页面白屏,控制台报 500 | (空) |
| 13 | 希望能支持暗黑模式 | (空) |
| 14 | 请问怎么配置 webhook | (空) |
## Step 3语义分析逐个读详情
```bash
gitlink-cli issue +view --owner z2_cc --repo gitlink-cli --number 12 --format json
```
**输出示例:**
```json
{
"ok": true,
"data": { "issue": {
"number": 12,
"subject": "登录后页面白屏,控制台报 500",
"description": "输入账号密码点登录后页面直接白屏,浏览器控制台显示 500 Internal Server Error。Chrome 120 / macOS。"
}}
"issues": [
{
"number": 10,
"subject": "登录页面报错500 Internal Server Error",
"status_id": 1,
"author": {"login": "newuser"}
}
]
}
```
**语义判定(注意 #12 没有「bug」字眼靠语义识别**
- **#12**500 + 阻断登录主流程 → **Bug**500 是服务端响应 → 后端 bob
- **#13**:「希望支持暗黑模式」→ **功能需求 enhancement**UI/样式 → 前端 alice
- **#14**:「请问怎么配置 webhook」→ **问题咨询 question**;答疑 → 文档 carol
## Step 4出「分拣方案表」建议不写入等用户确认
```
分拣方案(共 3 个 Issue请确认后我将 dry-run 预览):
| # | 标题 | 类别 | 标签(id) | 责任人(id) |
|-----|----------------------|----------|-----------------|-------------|
| 12 | 登录后白屏 500 | Bug | bug(1) | bob(102) |
| 13 | 希望支持暗黑模式 | Feature | enhancement(2) | alice(101) |
| 14 | 请问怎么配置 webhook | Question | question(4) | carol(103) |
引导评论将分别请求:#12 复现步骤/后端日志;#13 主题范围确认;#14 直接答复+文档化。
确认执行吗?(回复「确认」我进入 dry-run 预览;如需调整请指出)
```
> ⏸️ **停在此处等用户确认。禁止用 `--yes` 自行推进。**
## Step 5打标签用户确认方案后
> ⚠️ 各 Issue 标签不同,**用 Raw API 逐个打**(实测 `issue +update --label` 不可用、`+batch-update --label` 是集合式,见 SKILL.md 红线)。务必回带 `subject`/`description` 防清空。
### Step 2查看 Issue 详细内容
```bash
# #12 → bug(1)
gitlink-cli api PATCH /:owner/:repo/issues/12 --body '{
"issue_tag_ids": [1], "subject": "登录后页面白屏,控制台报 500",
"description": "输入账号密码点登录后页面直接白屏,控制台显示 500 Internal Server Error。Chrome 120/macOS。"
}'
# #13 → enhancement(2)
gitlink-cli api PATCH /:owner/:repo/issues/13 --body '{
"issue_tag_ids": [2], "subject": "希望能支持暗黑模式", "description": "希望加暗黑主题切换。"
}'
# #14 → question(4)
gitlink-cli api PATCH /:owner/:repo/issues/14 --body '{
"issue_tag_ids": [4], "subject": "请问怎么配置 webhook", "description": "想把推送事件通知到群机器人。"
}'
gitlink-cli issue +view --owner z2_cc --repo gitlink-cli --number 10 --format json
```
> 多个 Issue **共用同一标签**时,可改用批量:`issue +batch-update --numbers <a,b,c> --label <单个id> --dry-run` → 去 `--dry-run`
> 指派人:`issue +update --number <n> --assignee <user_id>``user_id` 来自 `label +assigners`;无可指派人则留空)。
### Step 3分析 Issue 内容判断类别
**验证打标结果:**
根据标题和描述中的关键词判断:
| 关键词 | 类别 |
|--------|------|
| 报错、错误、bug | Bug |
| 建议、希望 | 功能需求 |
| 文档 | 文档 |
| 请问、怎么 | 问题咨询 |
### Step 4添加分类评论
```bash
gitlink-cli issue +view --number 12 --format json # data.issue.tags 应为 [{"id":1,"name":"bug"}]
gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 10 --body "感谢提交 Issue已自动分类为 **Bug**
请补充以下信息以便排查:
- 运行环境(操作系统、浏览器版本)
- 复现步骤
- 错误截图或日志
项目维护者会尽快处理。"
```
## Step 6引导评论逐个添加
### Step 5确认处理结果
```bash
# #12 Bug
gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 12 \
--body "已自动分拣为 **Bug**,转交 @bob。为加快定位,请补充:运行环境、稳定复现步骤、浏览器控制台与后端对应时间点的报错日志。"
# #13 Feature
gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 13 \
--body "已自动分拣为 **enhancement**,转交 @alice。落地前请确认范围:① 全局暗黑主题还是特定页面;② 是否跟随系统 prefers-color-scheme③ 配色基准。"
# #14 Question
gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 14 \
--body "已自动分拣为 **question**,转交 @carol。快速回答Webhook 在「仓库设置 → Webhooks」新增填回调 URL、选触发事件GitLink 会向该 URL 发 POST。完整字段说明将补充到 docs/。"
gitlink-cli issue +view --owner z2_cc --repo gitlink-cli --number 10 --format json
```
---
## 命令速览
## 完整命令速览
```bash
# 1. 解析 ID
gitlink-cli label +list --format json
gitlink-cli label +assigners --format json
# 1. 获取待处理 Issue
gitlink-cli issue +list --state open
# 2. 取未分拣 Issue客户端筛无标签的
gitlink-cli issue +list --state open --format json
# 2. 查看详情
gitlink-cli issue +view --number <id>
# 3. 语义分析
gitlink-cli issue +view --number <n> --format json
# 4. 出方案表 → 用户确认(不写入)
# 5. 打标签:各 Issue 不同标签 → 逐个 Raw APIissue_tag_ids 整体替换)
gitlink-cli api PATCH /:owner/:repo/issues/<n> --body '{"issue_tag_ids":[<id>],"subject":"<>","description":"<>"}'
# 多 Issue 共用同一标签 → 批量(先 --dry-run
gitlink-cli issue +batch-update --numbers <a,b,c> --label <单个id> --dry-run
# 6. 引导评论
gitlink-cli issue +comment --number <n> --body "<评论>"
# 3. 添加分类评论
gitlink-cli issue +comment --number <id> --body "<评论内容>"
```
## 退化场景:单个 Issue
只需分拣一个 Issue 时:
```bash
# 打标签Raw API+update --label 实测不可用)
gitlink-cli api PATCH /:owner/:repo/issues/<n> --body '{"issue_tag_ids":[<id>],"subject":"<原标题>","description":"<原描述>"}'
# 指派人(可选)
gitlink-cli issue +update --number <n> --assignee <user_id>
# 引导评论
gitlink-cli issue +comment --number <n> --body "<评论>"
```
同样遵循「方案→确认→执行」,不要直接 `--yes`

View File

@ -1,158 +0,0 @@
---
name: gitlink-multi-repo-coordination
version: 1.0.0
description: "多仓库协同:统一 Issue 追踪 → PR 状态看板 → Release 协调发布。跨多个仓库聚合 Issue/PR/Release 数据,生成协同看板与协调发版建议。"
metadata:
requires:
bins: ["gitlink-cli", "jq"]
cliHelp: "gitlink-cli issue --help / gitlink-cli pr --help / gitlink-cli release --help"
---
# gitlink-multi-repo-coordination多仓库协同
> **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解认证、全局参数和 API 注意事项。
>
> **CRITICAL — 所有 GitLink 操作必须使用 `gitlink-cli`,禁止使用 `gh`GitHub CLI操作 GitLink 资源。**
## 说明
本 Skill 面向**跨多仓库协同**场景,把分散在多个 `owner/repo` 的 Issue、PR、Release 数据聚合为统一看板,并给出协调发版建议:
1. **统一 Issue 追踪** — 遍历多个仓库聚合打开的 Issue按仓库分组、按优先级/标签汇总,识别跨仓库重复/关联 Issue
2. **PR 状态看板** — 聚合各仓库打开/已合并 PR识别长期未合并 PR
3. **Release 协调发布** — 汇总各仓库最新版本做版本对齐分析给出协调发布建议dry-run 下只生成建议,不真正发版)
**与单仓库 Skill 的区别:** 单仓库 Skillissue-triage、project-health、release-auto只看一个仓库本工作流把多个仓库视为一个整体协同视图。
---
## 三阶段工作流总览
```mermaid
flowchart LR
A[多仓库列表 REPOS] --> B[Phase 1: 统一 Issue 追踪]
B --> C[Phase 2: PR 状态看板]
C --> D[Phase 3: Release 协调发布]
subgraph B[Phase 1: 统一 Issue 追踪]
B1[遍历每个仓库采集 open Issue] --> B2[按仓库分组聚合]
B2 --> B3[标题相似度识别跨仓库关联]
B3 --> B4[生成统一 Issue 看板]
end
subgraph C[Phase 2: PR 看板]
C1[遍历每个仓库采集 open/merged PR] --> C2[聚合 PR 状态]
C2 --> C3[按更新时间识别长期未合并]
C3 --> C4[生成 PR 看板]
end
subgraph D[Phase 3: Release 协调]
D1[遍历每个仓库采集 release] --> D2[版本对齐分析]
D2 --> D3[识别落后/可同步发版仓库]
D3 --> D4[生成协调发布建议]
end
```
---
## Phase 1统一 Issue 追踪
### 命令清单
```bash
# 遍历 REPOS 中每个仓库采集打开的 Issue
for repo_full in $(echo $REPOS | tr ',' ' '); do
owner=${repo_full%/*}
repo=${repo_full#*/}
gitlink-cli issue +list --owner "$owner" --repo "$repo" --state open --format json
done
```
### 聚合逻辑
- 按仓库分组展示打开的 Issue
- 按 Issue 数量/标签汇总各仓库状态
- 通过**标题关键词相似度**识别跨仓库可能重复/关联的 Issue如多仓库都出现"登录失败"类 Issue
- 输出 `issue-tracker.md`
---
## Phase 2PR 状态看板
### 命令清单
```bash
for repo_full in $(echo $REPOS | tr ',' ' '); do
owner=${repo_full%/*}
repo=${repo_full#*/}
gitlink-cli pr +list --owner "$owner" --repo "$repo" --state open --format json
gitlink-cli pr +list --owner "$owner" --repo "$repo" --state merged --format json
done
```
### 聚合逻辑
- 统计每个仓库打开 PR / 已合并 PR 数量
- 按 `updated_at` 排序识别长期未合并 PR默认阈值 > 14 天 🔴)
- 汇总到 PR 看板表(仓库 | 标题 | 状态 | 更新时间)
- 输出 `pr-dashboard.md`
---
## Phase 3Release 协调发布
### 命令清单
```bash
for repo_full in $(echo $REPOS | tr ',' ' '); do
owner=${repo_full%/*}
repo=${repo_full#*/}
gitlink-cli release +list --owner "$owner" --repo "$repo" --format json
done
```
### 协调逻辑
- 提取每个仓库最新 `tag_name`,按语义化版本比较
- 标记版本**落后**的仓库(最新版本明显低于中位数)
- 识别**可同步发版**的仓库组(最新版本相近、上次发版时间相近)
- dry-run 下只生成协调发布建议报告 `release-coordination.md`**不调用 `release +create`**
---
## 可复现脚本
本 Skill 提供可直接执行的 Bash 脚本,位于 `scripts/` 目录:
| 脚本 | 功能 | 使用方式 |
|------|------|----------|
| `01-unified-issue-tracker.sh` | Phase 1 统一 Issue 追踪 | `REPOS=z2_cc/gitlink-cli bash 01-unified-issue-tracker.sh` |
| `02-pr-dashboard.sh` | Phase 2 PR 看板 | `REPOS=z2_cc/gitlink-cli bash 02-pr-dashboard.sh` |
| `03-release-coordination.sh` | Phase 3 Release 协调 | `REPOS=z2_cc/gitlink-cli bash 03-release-coordination.sh` |
| `multi-repo-full.sh` | 全流程串联 + HTML 报告 | `REPOS=z2_cc/gitlink-cli bash multi-repo-full.sh` |
| `dashboard-gen.js` | 多仓库聚合引擎Node | 由 full 脚本调用 |
### 环境变量
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `REPOS` | `z2_cc/gitlink-cli` | 逗号分隔的 `owner/repo` 列表 |
| `DRY_RUN` | `true` | dry-run 模式(不实际创建 Release |
```bash
# Dry-run默认安全—— 单仓库
REPOS="z2_cc/gitlink-cli" bash scripts/multi-repo-full.sh
# 多仓库协同
REPOS="z2_cc/gitlink-cli,z2_cc/gitlink-bisync" DRY_RUN=true bash scripts/multi-repo-full.sh
```
---
## 注意事项
1. **dry-run 优先**Phase 3 的 `release +create` 默认不执行dry-run=false 时才实际发版
2. **Token 有效**:运行前确认 `gitlink-cli auth status` 返回正常;未认证时脚本会优雅降级(采集失败 → 写空 JSON → 仍生成报告)
3. **离线兼容**:本机 Windows Node 不识别 MSYS 绝对路径,因此 `dashboard-gen.js` 全程使用 `path.join(dir, ...)` 相对路径
4. **相似度判断为辅助**:跨仓库 Issue 关联仅基于标题关键词相似度,最终结论建议人工复核
5. **输出文件**:所有 JSON 数据保存到 `scripts/_output/` 目录供审计

View File

@ -1,176 +0,0 @@
# 多仓库协同工作流 — 端到端示例
**场景**:组织维护多个相关仓库(如 `z2_cc/gitlink-cli``z2_cc/gitlink-bisync`),希望把它们视为一个整体,统一追踪 Issue、聚合 PR 状态、协调发版节奏。
## 前置条件
- `gitlink-cli` 已安装并登录(`gitlink-cli auth status`
- 通过环境变量 `REPOS` 指定要协同的仓库列表
- `jq` 已安装(用于 JSON 解析)
- 离线/未认证时脚本会优雅降级(采集失败 → 写空 JSON → 仍生成报告)
## 环境变量
```bash
# 单仓库(默认)
export REPOS="z2_cc/gitlink-cli"
# 多仓库协同
export REPOS="z2_cc/gitlink-cli,z2_cc/gitlink-bisync"
# dry-run默认 true不实际创建 Release
export DRY_RUN=true
```
## 工作流步骤
### Step 1统一 Issue 追踪Phase 1
```bash
# 遍历 REPOS 中每个仓库采集 open Issue
for repo_full in $(echo $REPOS | tr ',' ' '); do
owner=${repo_full%/*}
repo=${repo_full#*/}
gitlink-cli issue +list --owner "$owner" --repo "$repo" --state open --format json \
> "_output/issues-${owner}-${repo}.json"
done
```
**输出示例issues-z2_cc-gitlink-cli.json**
```json
{
"ok": true,
"data": {
"issues": [
{"number": 42, "subject": "登录页面 500 报错", "state": 1, "created_at": "2026-06-20"},
{"number": 43, "subject": "建议增加 webhook 投递监控", "state": 1, "created_at": "2026-06-22"}
]
}
}
```
**输出示例issues-z2_cc-gitlink-bisync.json**
```json
{
"ok": true,
"data": {
"issues": [
{"number": 7, "subject": "登录接口 500 报错", "state": 1, "created_at": "2026-06-21"}
]
}
}
```
**AI 分析逻辑:**
```
按仓库分组:
z2_cc/gitlink-cli → 2 个 open Issue
z2_cc/gitlink-bisync → 1 个 open Issue
跨仓库关联(标题关键词相似度):
#42 (cli) "登录页面 500 报错" ↔ #7 (bisync) "登录接口 500 报错"
关键词重叠 = {登录, 500, 报错} → 3 个重叠 → 高度疑似跨仓库关联 Issue
```
**Expected:** `_output/issues-<owner>-<repo>.json` 每仓库一份;`issue-tracker.md` 含分组表 + 关联表。
### Step 2PR 状态看板Phase 2
```bash
for repo_full in $(echo $REPOS | tr ',' ' '); do
owner=${repo_full%/*}
repo=${repo_full#*/}
gitlink-cli pr +list --owner "$owner" --repo "$repo" --state open --format json
gitlink-cli pr +list --owner "$owner" --repo "$repo" --state merged --format json
done
```
**AI 分析逻辑:**
```
PR 汇总:
z2_cc/gitlink-cli 打开 4 / 已合并 12 → 合并率 75% 🟢
z2_cc/gitlink-bisync 打开 8 / 已合并 2 → 合并率 20% 🔴
长期未合并(> 14 天):
PR #15 (bisync) "重构同步引擎" 上次更新 32 天前 → 🔴
PR #11 (cli) "添加 wiki 模板" 上次更新 21 天前 → 🟡
```
**Expected:** `pr-dashboard.md` 含汇总表 + 长期未合并 PR 排行 + 各仓库明细。
### Step 3Release 协调发布Phase 3
```bash
for repo_full in $(echo $REPOS | tr ',' ' '); do
owner=${repo_full%/*}
repo=${repo_full#*/}
gitlink-cli release +list --owner "$owner" --repo "$repo" --format json
done
```
**输出示例releases-z2_cc-gitlink-cli.json**
```json
{
"ok": true,
"data": {
"releases": [
{"tag_name": "v0.3.0", "name": "v0.3.0", "created_at": "2026-06-24"}
]
}
}
```
**输出示例releases-z2_cc-gitlink-bisync.json**
```json
{
"ok": true,
"data": {
"releases": [
{"tag_name": "v0.1.2", "name": "v0.1.2", "created_at": "2026-05-10"}
]
}
}
```
**AI 分析结果:**
```
版本对齐分析:
z2_cc/gitlink-cli v0.3.0 ✅
z2_cc/gitlink-bisync v0.1.2 🔴 主版本 0.1 < 中位数主版本 0.x 同主版本
(主版本均为 0落后判断依赖次版本差异
协调发布建议:
1. z2_cc/gitlink-bisync 落后较多,建议优先发版追赶 cli
2. dry-run 模式下不调用 release +create需人工确认后实际发版
```
```bash
# dry-run只生成建议默认
echo "[DRY-RUN] 仅生成 release-coordination.md未创建任何 Release"
# 实际发版需 DRY_RUN=false 且由人工逐仓库执行(脚本不会自动批量 create
```
**Expected:** `release-coordination.md` 含各仓库版本表 + 对齐分析 + 协调建议列表;不实际创建 Release。
## 完整命令速览
```bash
# 一键全流程dry-run多仓库
REPOS="z2_cc/gitlink-cli,z2_cc/gitlink-bisync" bash skills/gitlink-multi-repo-coordination/scripts/multi-repo-full.sh
# 等价的手动步骤
REPOS="z2_cc/gitlink-cli,z2_cc/gitlink-bisync"
bash skills/gitlink-multi-repo-coordination/scripts/01-unified-issue-tracker.sh
REPOS=$REPOS bash skills/gitlink-multi-repo-coordination/scripts/02-pr-dashboard.sh
REPOS=$REPOS bash skills/gitlink-multi-repo-coordination/scripts/03-release-coordination.sh
node skills/gitlink-multi-repo-coordination/scripts/dashboard-gen.js \
skills/gitlink-multi-repo-coordination/scripts/_output
```
## 注意事项
- 所有写操作(特别是 `release +create`)默认 dry-run确认后通过 `DRY_RUN=false` 由人工逐仓库执行
- 跨仓库 Issue 关联仅基于标题关键词相似度,最终结论建议人工复核
- 未认证/无网络时脚本会优雅降级:采集失败写空 JSON聚合引擎仍能跑完产出空报告
- 本机 Windows Node 不识别 MSYS `/c/...` 路径,`dashboard-gen.js` 全程使用相对路径

View File

@ -1,50 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 1: 统一 Issue 追踪
# 功能:遍历 REPOS 采集每个仓库的 open Issue落盘为 issues-<owner>-<repo>.json
# 使用REPOS="owner1/repo1,owner2/repo2" bash 01-unified-issue-tracker.sh
# 环境变量REPOS (默认 z2_cc/gitlink-cli)
# ================================================================
set -e
# 自动检测并使用本地编译的 gitlink-cli
source "$(cd "$(dirname "$0")" && pwd)/../../gitlink-shared/scripts/detect-cli.sh"
REPOS=${REPOS:-z2_cc/gitlink-cli}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 1: 统一 Issue 追踪 ]"
echo "[ REPOS: $REPOS"
echo "[========================================]"
# 遍历每个仓库
IFS=',' read -ra REPO_ARRAY <<< "$REPOS"
for repo_full in "${REPO_ARRAY[@]}"; do
owner=${repo_full%/*}
repo=${repo_full#*/}
if [ -z "$owner" ] || [ -z "$repo" ] || [ "$owner" = "$repo_full" ]; then
echo "[WARN] 跳过非法仓库标识: $repo_full(应为 owner/repo"
continue
fi
out_file="$OUTPUT_DIR/issues-${owner}-${repo}.json"
echo "[INFO] 采集 open Issue: $owner/$repo"
gitlink-cli issue +list --owner "$owner" --repo "$repo" --state open --format json > "$out_file" 2>&1 || {
echo "[WARN] 采集 $owner/$repo Issue 失败,写入空数据兜底"
echo '{"data":{"issues":[]}}' > "$out_file"
}
# 解析 Issue 数量(兼容 data 为数组或 {issues:[]}
# 单行 node -e本机 Windows 原生 Node 下 multiline -e 字符串会损坏,故用单行
cnt=$(node -e "const fs=require('fs');try{const d=JSON.parse(fs.readFileSync(process.argv[1],'utf8')).data||{};const items=Array.isArray(d)?d:(d.issues||[]);process.stdout.write(String(items.length));}catch(e){process.stdout.write('0');}" "$out_file" 2>/dev/null || echo "0")
echo "[INFO] └─ $owner/$repo: $cnt 个 open Issue"
done
echo ""
echo "[========================================]"
echo "[ Phase 1 完成 ]"
echo "[ 数据保存至: $OUTPUT_DIR/ ]"
echo "[========================================]"

View File

@ -1,66 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 2: PR 状态看板
# 功能:遍历 REPOS 采集每个仓库的 open / merged PR落盘为 prs-<owner>-<repo>.json
# 使用REPOS="owner1/repo1,owner2/repo2" bash 02-pr-dashboard.sh
# 环境变量REPOS (默认 z2_cc/gitlink-cli)
#
# 注意:本机为 Windows 原生 NodeMSYS bash 多行 node -e 字符串会损坏(换行处理问题),
# 因此合并逻辑写在专用 .js 文件中(避开 multiline -e
# ================================================================
set -e
source "$(cd "$(dirname "$0")" && pwd)/../../gitlink-shared/scripts/detect-cli.sh"
REPOS=${REPOS:-z2_cc/gitlink-cli}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 2: PR 状态看板 ]"
echo "[ REPOS: $REPOS"
echo "[========================================]"
IFS=',' read -ra REPO_ARRAY <<< "$REPOS"
for repo_full in "${REPO_ARRAY[@]}"; do
owner=${repo_full%/*}
repo=${repo_full#*/}
if [ -z "$owner" ] || [ "$owner" = "$repo_full" ]; then
echo "[WARN] 跳过非法仓库标识: $repo_full"
continue
fi
out_file="$OUTPUT_DIR/prs-${owner}-${repo}.json"
open_tmp="$OUTPUT_DIR/.prs-open-${owner}-${repo}.tmp"
merged_tmp="$OUTPUT_DIR/.prs-merged-${owner}-${repo}.tmp"
echo "[INFO] 采集 PR: $owner/$repoopen + merged"
# 采集 open PR
gitlink-cli pr +list --owner "$owner" --repo "$repo" --state open --format json > "$open_tmp" 2>&1 || {
echo "[WARN] 采集 $owner/$repo open PR 失败"
echo '{"data":{"pulls":[]}}' > "$open_tmp"
}
# 采集 merged PR
gitlink-cli pr +list --owner "$owner" --repo "$repo" --state merged --limit 50 --format json > "$merged_tmp" 2>&1 || {
echo "[WARN] 采集 $owner/$repo merged PR 失败"
echo '{"data":{"pulls":[]}}' > "$merged_tmp"
}
# 合并两份临时文件为单个 prs-<owner>-<repo>.json
# 使用 node 文件argv 索引:[2]=open, [3]=merged, [4]=out避开 multiline -e 损坏
node "$SCRIPT_DIR/_merge-pr-json.js" "$open_tmp" "$merged_tmp" "$out_file" 2>/dev/null || {
echo '[WARN] 合并 PR JSON 失败,写空兜底'
echo '{"open":[],"merged":[]}' > "$out_file"
}
rm -f "$open_tmp" "$merged_tmp" 2>/dev/null || true
echo "[INFO] └─ $owner/$repo: PR 已聚合 → $out_file"
done
echo ""
echo "[========================================]"
echo "[ Phase 2 完成 ]"
echo "[ 数据保存至: $OUTPUT_DIR/ ]"
echo "[========================================]"

View File

@ -1,48 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 3: Release 协调发布
# 功能:遍历 REPOS 采集每个仓库的 release 列表,落盘为 releases-<owner>-<repo>.json
# 使用REPOS="owner1/repo1,owner2/repo2" bash 03-release-coordination.sh
# 环境变量REPOS (默认 z2_cc/gitlink-cli)
# 注意:本脚本只采集数据,不会真正调用 release +createdry-run 由 full 脚本默认 true
# ================================================================
set -e
source "$(cd "$(dirname "$0")" && pwd)/../../gitlink-shared/scripts/detect-cli.sh"
REPOS=${REPOS:-z2_cc/gitlink-cli}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 3: Release 协调发布 ]"
echo "[ REPOS: $REPOS"
echo "[========================================]"
IFS=',' read -ra REPO_ARRAY <<< "$REPOS"
for repo_full in "${REPO_ARRAY[@]}"; do
owner=${repo_full%/*}
repo=${repo_full#*/}
if [ -z "$owner" ] || [ "$owner" = "$repo_full" ]; then
echo "[WARN] 跳过非法仓库标识: $repo_full"
continue
fi
out_file="$OUTPUT_DIR/releases-${owner}-${repo}.json"
echo "[INFO] 采集 Release: $owner/$repo"
gitlink-cli release +list --owner "$owner" --repo "$repo" --format json > "$out_file" 2>&1 || {
echo "[WARN] 采集 $owner/$repo Release 失败,写入空数据兜底"
echo '{"data":{"releases":[]}}' > "$out_file"
}
latest=$(node -e "const fs=require('fs');try{const d=JSON.parse(fs.readFileSync(process.argv[1],'utf8')).data||{};const items=Array.isArray(d)?d:(d.releases||[]);process.stdout.write(items[0]&&items[0].tag_name?items[0].tag_name:'none');}catch(e){process.stdout.write('none');}" "$out_file" 2>/dev/null || echo "none")
echo "[INFO] └─ $owner/$repo: 最新 tag = $latest"
done
echo ""
echo "[========================================]"
echo "[ Phase 3 完成dry-run未创建 Release]"
echo "[ 数据保存至: $OUTPUT_DIR/ ]"
echo "[========================================]"

View File

@ -1,23 +0,0 @@
/**
* 合并 open/merged PR JSON 02-pr-dashboard.sh 调用
* argv: [2]=open.json [3]=merged.json [4]=output.json
*/
const fs = require('fs');
const path = require('path');
function safe(p) {
try {
const raw = JSON.parse(fs.readFileSync(p, 'utf8'));
const d = raw.data != null ? raw.data : raw;
if (Array.isArray(d)) return d;
if (d && Array.isArray(d.pulls)) return d.pulls;
return [];
} catch (e) { return []; }
}
const openList = safe(process.argv[2]);
const mergedList = safe(process.argv[3]);
const outPath = process.argv[4];
fs.writeFileSync(outPath, JSON.stringify({ open: openList, merged: mergedList }, null, 2));
process.stdout.write('open=' + openList.length + ' merged=' + mergedList.length);

View File

@ -1,303 +0,0 @@
/**
* 多仓库协同聚合引擎
* 用法: node dashboard-gen.js <_output 目录>
*
* 读取 _output/ 下所有 issues-*.json / prs-*.json / releases-*.json
* 生成 4 markdownissue-tracker.md / pr-dashboard.md / release-coordination.md / multi-repo-overview.md
*
* 重要所有路径用 path.join(dir, ...)不硬编码绝对路径本机 Windows Node 不识别 MSYS /c/... 路径
*/
const fs = require('fs');
const path = require('path');
const dir = process.argv[2] || '_output';
const now = new Date();
const dateStr = now.toISOString().slice(0, 10);
const timeStr = now.toISOString().slice(0, 19).replace('T', ' ');
// ==== 工具:相对路径安全读 JSON ====
function readJSONSafe(p) {
try { return JSON.parse(fs.readFileSync(p, 'utf8')); }
catch (e) { return null; }
}
// 兼容 data 是数组或 {issues:[]}/{pulls:[]}/{releases:[]} 多种形态
function extractList(raw, key) {
if (!raw) return [];
const d = raw.data != null ? raw.data : raw;
if (Array.isArray(d)) return d;
if (d && Array.isArray(d[key])) return d[key];
return [];
}
// 从 issues-<owner>-<repo>.json 文件名解析 owner/repo
function parseRepoFromName(name, prefix) {
const stem = name.replace(new RegExp('^' + prefix + '-'), '').replace(/\.json$/, '');
// owner-repoowner / repo 中的 / 已被切分为 -,这里 owner 不含 -repo 可能含 -
const idx = stem.indexOf('-');
if (idx < 0) return { owner: '', repo: stem };
return { owner: stem.slice(0, idx), repo: stem.slice(idx + 1) };
}
// ==== 扫描 _output 目录 ====
let files = [];
try { files = fs.readdirSync(dir); }
catch (e) { files = []; }
const issueFiles = files.filter(f => f.startsWith('issues-') && f.endsWith('.json'));
const prFiles = files.filter(f => f.startsWith('prs-') && f.endsWith('.json'));
const releaseFiles = files.filter(f => f.startsWith('releases-') && f.endsWith('.json'));
// ==== 聚合 Issue ====
const repos = []; // {key, owner, repo, openIssues:[], prOpen, prMerged, releases, latestTag}
const issueMap = new Map();
issueFiles.forEach(f => {
const { owner, repo } = parseRepoFromName(f, 'issues');
const raw = readJSONSafe(path.join(dir, f));
const items = extractList(raw, 'issues').map(it => ({
number: it.number || it.id || '',
title: it.subject || it.title || '(无标题)',
labels: it.labels || [],
created_at: it.created_at || '',
updated_at: it.updated_at || ''
}));
const key = `${owner}/${repo}`;
issueMap.set(key, items);
repos.push({ key, owner, repo, openIssues: items });
});
// ==== 聚合 PR ====
prFiles.forEach(f => {
const { owner, repo } = parseRepoFromName(f, 'prs');
const raw = readJSONSafe(path.join(dir, f));
const key = `${owner}/${repo}`;
let node = repos.find(r => r.key === key);
if (!node) { node = { key, owner, repo, openIssues: [] }; repos.push(node); }
// prs-*.json 是 {open:[], merged:[]}(由 02 脚本聚合)
const open = (raw && Array.isArray(raw.open)) ? raw.open : extractList(raw, 'pulls');
const merged = (raw && Array.isArray(raw.merged)) ? raw.merged : [];
node.prOpen = open.map(p => ({
number: p.number || p.id || '',
title: p.title || p.subject || '(无标题)',
status: p.status || 'open',
updated_at: p.updated_at || p.updated_time || ''
}));
node.prMerged = merged.map(p => ({
number: p.number || p.id || '',
title: p.title || p.subject || '(无标题)',
status: 'merged',
updated_at: p.updated_at || p.updated_time || ''
}));
});
// ==== 聚合 Release ====
releaseFiles.forEach(f => {
const { owner, repo } = parseRepoFromName(f, 'releases');
const raw = readJSONSafe(path.join(dir, f));
const key = `${owner}/${repo}`;
let node = repos.find(r => r.key === key);
if (!node) { node = { key, owner, repo, openIssues: [] }; repos.push(node); }
const list = extractList(raw, 'releases').map(r => ({
tag: r.tag_name || r.name || '',
name: r.name || r.tag_name || '',
created_at: r.created_at || r.created_time || ''
}));
node.releases = list;
node.latestTag = list[0] ? list[0].tag : 'none';
node.latestReleaseTime = list[0] ? list[0].created_at : '';
});
// 兜底:无任何仓库时给一条占位
if (repos.length === 0) {
repos.push({ key: '(无数据)', owner: '', repo: '', openIssues: [], prOpen: [], prMerged: [], releases: [], latestTag: 'none' });
}
// ==== 跨仓库关联 Issue标题关键词相似度 ====
function keywords(title) {
return (title || '').toLowerCase().replace(/[^0-9a-z一-龥]/g, ' ').split(/\s+/).filter(w => w.length > 1);
}
const crossLinks = [];
const allIssues = [];
repos.forEach(r => (r.openIssues || []).forEach(i => allIssues.push({ ...i, repo: r.key })));
for (let i = 0; i < allIssues.length; i++) {
for (let j = i + 1; j < allIssues.length; j++) {
if (allIssues[i].repo === allIssues[j].repo) continue;
const ka = new Set(keywords(allIssues[i].title));
const kb = keywords(allIssues[j].title);
const overlap = kb.filter(w => ka.has(w)).length;
if (overlap >= 2) {
crossLinks.push({ a: allIssues[i], b: allIssues[j], overlap });
}
}
}
// ==== 长期未合并 PR> 14 天) ====
const STALE_DAYS = 14;
function daysAgo(s) {
if (!s) return Infinity;
const t = new Date(String(s).replace(' ', 'T')).getTime();
if (isNaN(t)) return Infinity;
return (Date.now() - t) / (24 * 60 * 60 * 1000);
}
const stalePRs = [];
repos.forEach(r => (r.prOpen || []).forEach(p => {
const d = daysAgo(p.updated_at);
if (d > STALE_DAYS) stalePRs.push({ ...p, repo: r.key, days: Math.round(d) });
}));
stalePRs.sort((a, b) => b.days - a.days);
// ==== 版本对齐分析 ====
function parseSemver(tag) {
const m = String(tag).match(/v?(\d+)\.(\d+)\.(\d+)/);
return m ? [parseInt(m[1]), parseInt(m[2]), parseInt(m[3])] : null;
}
const versioned = repos.filter(r => parseSemver(r.latestTag));
const lagging = [];
if (versioned.length >= 2) {
const majors = versioned.map(r => parseSemver(r.latestTag)[0]);
const median = majors.slice().sort((a, b) => a - b)[Math.floor(majors.length / 2)];
versioned.forEach(r => {
const v = parseSemver(r.latestTag);
if (v[0] < median) lagging.push({ repo: r.key, tag: r.latestTag, reason: `主版本 ${v[0]} < 中位数 ${median}` });
});
}
// ==== 生成 issue-tracker.md ====
let issueMd = `# 🎯 统一 Issue 追踪看板\n\n**报告日期:** ${dateStr}\n**仓库列表:** ${repos.map(r => r.key).join(', ')}\n\n`;
issueMd += `## 一、按仓库分组\n\n`;
repos.forEach(r => {
issueMd += `### ${r.key}${r.openIssues.length} 个 open\n\n`;
if (!r.openIssues.length) { issueMd += '_无打开 Issue_\n\n'; return; }
issueMd += '| # | 标题 | 标签 | 创建时间 |\n|---|------|------|----------|\n';
r.openIssues.slice(0, 20).forEach(i => {
issueMd += `| ${i.number} | ${i.title} | ${(i.labels || []).join(',')} | ${i.created_at || '—'} |\n`;
});
issueMd += '\n';
});
issueMd += `## 二、跨仓库关联 Issue标题相似度\n\n`;
if (crossLinks.length === 0) {
issueMd += '_未发现跨仓库标题高度相似的 Issue_\n\n';
} else {
issueMd += '| 仓库 A | Issue | 仓库 B | Issue | 重叠词数 |\n|--------|-------|--------|-------|----------|\n';
crossLinks.slice(0, 15).forEach(c => {
issueMd += `| ${c.a.repo} | #${c.a.number} ${c.a.title} | ${c.b.repo} | #${c.b.number} ${c.b.title} | ${c.overlap} |\n`;
});
if (crossLinks.length > 15) issueMd += `\n_共 ${crossLinks.length} 条潜在关联,仅展示前 15 条_\n`;
}
issueMd += `\n---\n*数据采集时间:${timeStr}*\n*AI 生成,跨仓库关联仅基于标题关键词,建议人工复核*\n`;
fs.writeFileSync(path.join(dir, 'issue-tracker.md'), issueMd, 'utf8');
// ==== 生成 pr-dashboard.md ====
let prMd = `# 🔀 PR 状态看板\n\n**报告日期:** ${dateStr}\n**仓库列表:** ${repos.map(r => r.key).join(', ')}\n\n`;
prMd += `## 一、PR 汇总\n\n| 仓库 | 打开 PR | 已合并 PR | 状态 |\n|------|---------|-----------|------|\n`;
repos.forEach(r => {
const op = (r.prOpen || []).length;
const mg = (r.prMerged || []).length;
const st = op > 10 ? '🔴 积压' : op > 3 ? '🟡 注意' : '🟢 正常';
prMd += `| ${r.key} | ${op} | ${mg} | ${st} |\n`;
});
prMd += `\n## 二、长期未合并 PR> ${STALE_DAYS} 天)\n\n`;
if (stalePRs.length === 0) {
prMd += '_🟢 未发现长期未合并 PR_\n\n';
} else {
prMd += '| 仓库 | # | 标题 | 距上次更新(天) |\n|------|---|------|------------------|\n';
stalePRs.slice(0, 20).forEach(p => {
prMd += `| ${p.repo} | ${p.number} | ${p.title} | ${p.days} ${p.days > 30 ? '🔴' : '🟡'} |\n`;
});
}
prMd += `\n## 三、各仓库打开 PR 明细\n\n`;
repos.forEach(r => {
if (!r.prOpen || r.prOpen.length === 0) return;
prMd += `### ${r.key}\n\n| # | 标题 | 更新时间 |\n|---|------|----------|\n`;
r.prOpen.slice(0, 15).forEach(p => {
prMd += `| ${p.number} | ${p.title} | ${p.updated_at || '—'} |\n`;
});
prMd += '\n';
});
prMd += `---\n*数据采集时间:${timeStr}*\n`;
fs.writeFileSync(path.join(dir, 'pr-dashboard.md'), prMd, 'utf8');
// ==== 生成 release-coordination.md ====
let relMd = `# 🚀 Release 协调发布建议\n\n**报告日期:** ${dateStr}\n**仓库列表:** ${repos.map(r => r.key).join(', ')}\n\n`;
relMd += `## 一、各仓库最新版本\n\n| 仓库 | 最新 Tag | 发布时间 |\n|------|----------|----------|\n`;
repos.forEach(r => {
relMd += `| ${r.key} | ${r.latestTag || '—'} | ${r.latestReleaseTime || '—'} |\n`;
});
relMd += `\n## 二、版本对齐分析\n\n`;
if (lagging.length === 0) {
relMd += '_🟢 各仓库版本基本对齐或仓库数不足_\n\n';
} else {
relMd += '| 仓库 | 最新 Tag | 原因 |\n|------|----------|------|\n';
lagging.forEach(l => relMd += `| ${l.repo} | ${l.tag} | ${l.reason} |\n`);
}
relMd += `\n## 三、协调发布建议\n\n`;
const suggestions = [];
// 建议 1落后仓库优先发版
if (lagging.length > 0) suggestions.push(`🔴 **${lagging.map(l => l.repo).join('、')}** 版本落后,建议优先安排发版以对齐主版本`);
// 建议 2可同步发版的仓库组同主版本
const groups = {};
versioned.forEach(r => { const v = parseSemver(r.latestTag); const k = `${v[0]}.x.x`; (groups[k] = groups[k] || []).push(r.key); });
Object.entries(groups).forEach(([k, list]) => {
if (list.length >= 2) suggestions.push(`🟢 ${list.join('、')} 处于同主版本(${k}),可考虑协调同步发版`);
});
if (suggestions.length === 0) suggestions.push('🟢 当前无需特殊协调,各仓库可独立发版');
suggestions.forEach((s, i) => { relMd += `${i + 1}. ${s}\n`; });
relMd += `\n> **说明:** dry-run 模式下只生成建议,不实际调用 \`release +create\`。如需实际发版,请在 full 脚本设置 \`DRY_RUN=false\`\n\n`;
relMd += `---\n*数据采集时间:${timeStr}*\n`;
fs.writeFileSync(path.join(dir, 'release-coordination.md'), relMd, 'utf8');
// ==== 生成 multi-repo-overview.md含综合评分 ====
const totalOpenIssues = repos.reduce((s, r) => s + (r.openIssues || []).length, 0);
const totalOpenPRs = repos.reduce((s, r) => s + (r.prOpen || []).length, 0);
const totalMergedPRs = repos.reduce((s, r) => s + (r.prMerged || []).length, 0);
const mergeRate = (totalOpenPRs + totalMergedPRs) > 0
? Math.round(totalMergedPRs / (totalOpenPRs + totalMergedPRs) * 100) : 0;
const laggingRate = versioned.length > 0 ? Math.round(lagging.length / versioned.length * 100) : 0;
// 协同健康度评分10 分制)
let score = 10;
if (totalOpenIssues > 20) score -= 2; else if (totalOpenIssues > 10) score -= 1;
if (mergeRate < 40) score -= 2; else if (mergeRate < 70) score -= 1;
if (stalePRs.length > 5) score -= 2; else if (stalePRs.length > 0) score -= 1;
if (laggingRate > 50) score -= 2; else if (laggingRate > 0) score -= 1;
if (score < 0) score = 0;
const level = score >= 9 ? '🟢 优秀' : score >= 7 ? '🟢 良好' : score >= 5 ? '🟡 一般' : score >= 3 ? '🔴 堪忧' : '🔴 危险';
let ovMd = `# 📊 多仓库协同总览\n\n`;
ovMd += `**报告日期:** ${dateStr}\n**仓库数:** ${repos.length}\n`;
ovMd += `**综合评分:** ${score}/10 协同健康度 ${level}\n\n`;
ovMd += `## 一、跨仓库指标汇总\n\n| 仓库 | 打开 Issue | 打开 PR | 已合并 PR | 最新 Release | 状态 |\n|------|-----------|---------|-----------|--------------|------|\n`;
repos.forEach(r => {
const op = (r.openIssues || []).length;
const popen = (r.prOpen || []).length;
const pmerged = (r.prMerged || []).length;
const st = op > 10 || popen > 10 ? '🔴' : (op > 3 || popen > 3) ? '🟡' : '🟢';
ovMd += `| ${r.key} | ${op} | ${popen} | ${pmerged} | ${r.latestTag || '—'} | ${st} |\n`;
});
ovMd += `\n## 二、协同指标\n\n| 指标 | 数值 | 状态 |\n|------|------|------|\n`;
ovMd += `| 跨仓库关联 Issue | ${crossLinks.length} | ${crossLinks.length > 5 ? '🟡 需关注' : '🟢'} |\n`;
ovMd += `| 长期未合并 PR>${STALE_DAYS}天) | ${stalePRs.length} | ${stalePRs.length > 5 ? '🔴' : stalePRs.length > 0 ? '🟡' : '🟢'} |\n`;
ovMd += `| PR 合并率 | ${mergeRate}% | ${mergeRate > 60 ? '🟢' : mergeRate > 30 ? '🟡' : '🔴'} |\n`;
ovMd += `| 版本落后仓库占比 | ${laggingRate}% | ${laggingRate > 50 ? '🔴' : laggingRate > 0 ? '🟡' : '🟢'} |\n`;
ovMd += `\n## 三、协同建议摘要\n\n`;
const sumSuggestions = [];
if (crossLinks.length > 5) sumSuggestions.push('🟡 跨仓库关联 Issue 较多,建议建立统一标签体系');
if (stalePRs.length > 0) sumSuggestions.push(`🟡 存在 ${stalePRs.length} 个长期未合并 PR建议加快审查`);
if (lagging.length > 0) sumSuggestions.push(`🔴 ${lagging.length} 个仓库版本落后,建议优先对齐`);
if (mergeRate < 50) sumSuggestions.push(`🔴 PR 合并率仅 ${mergeRate}%,建议加快 PR 处理`);
if (sumSuggestions.length === 0) sumSuggestions.push('🟢 多仓库协同状态良好,继续保持');
sumSuggestions.forEach((s, i) => { ovMd += `${i + 1}. ${s}\n`; });
ovMd += `\n## 四、相关报告\n\n- [统一 Issue 追踪](./issue-tracker.md)\n- [PR 状态看板](./pr-dashboard.md)\n- [Release 协调建议](./release-coordination.md)\n\n`;
ovMd += `---\n*数据采集时间:${timeStr}*\n*AI 生成,建议人工复核*\n`;
fs.writeFileSync(path.join(dir, 'multi-repo-overview.md'), ovMd, 'utf8');
console.log('多仓库聚合报告已生成:');
console.log(' - ' + path.join(dir, 'issue-tracker.md'));
console.log(' - ' + path.join(dir, 'pr-dashboard.md'));
console.log(' - ' + path.join(dir, 'release-coordination.md'));
console.log(' - ' + path.join(dir, 'multi-repo-overview.md'));
console.log(`协同健康度评分: ${score}/10 ${level}`);

View File

@ -1,70 +0,0 @@
#!/bin/bash
# ================================================================
# 多仓库协同 — 全流程串联脚本
# 功能:依次执行 Phase 1Issue 追踪)→ Phase 2PR 看板)→ Phase 3Release 协调)
# → 调 dashboard-gen.js 聚合 → 调 md-to-html.js 把四份 md 转 HTML
# 使用REPOS="owner1/repo1,owner2/repo2" bash multi-repo-full.sh
# 环境变量:
# REPOS 逗号分隔的 owner/repo 列表(默认 z2_cc/gitlink-cli
# DRY_RUN true|false默认 true不实际创建 Release
# ================================================================
set -e
REPOS=${REPOS:-z2_cc/gitlink-cli}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "============================================"
echo " 多仓库协同"
echo " REPOS: $REPOS"
echo " DRY_RUN: $DRY_RUN"
echo " 开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================"
echo ""
# Phase 1
echo "▸ Phase 1/3: 统一 Issue 追踪"
REPOS="$REPOS" bash "$SCRIPT_DIR/01-unified-issue-tracker.sh" 2>&1 || echo "[WARN] Phase 1 异常,继续后续阶段"
echo ""
# Phase 2
echo "▸ Phase 2/3: PR 状态看板"
REPOS="$REPOS" bash "$SCRIPT_DIR/02-pr-dashboard.sh" 2>&1 || echo "[WARN] Phase 2 异常,继续后续阶段"
echo ""
# Phase 3
echo "▸ Phase 3/3: Release 协调发布"
REPOS="$REPOS" bash "$SCRIPT_DIR/03-release-coordination.sh" 2>&1 || echo "[WARN] Phase 3 异常,继续后续阶段"
echo ""
# 聚合引擎
echo "▸ 聚合数据,生成多仓库看板..."
node "$SCRIPT_DIR/dashboard-gen.js" "$OUTPUT_DIR" 2>&1 || echo "[WARN] 聚合引擎执行失败"
# 生成 HTML 可视化报告
echo "▸ 生成 HTML 可视化报告..."
SHARED_SCRIPT="$SCRIPT_DIR/../../gitlink-shared/scripts/md-to-html.js"
for md_name in issue-tracker pr-dashboard release-coordination multi-repo-overview; do
md_file="$OUTPUT_DIR/${md_name}.md"
if [ -f "$md_file" ]; then
node "$SHARED_SCRIPT" "$md_file" 2>/dev/null || echo "[WARN] 转换 $md_name 失败"
fi
done
echo ""
# dry-run 提示
if [ "$DRY_RUN" = "false" ]; then
echo "[INFO] DRY_RUN=false如需协调发版请人工执行 release +create脚本不自动发版"
else
echo "[INFO] DRY_RUN=true仅生成协调建议未创建任何 Release"
fi
echo ""
echo "============================================"
echo " 全流程完成"
echo " 结束时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo " 📄 Markdown: $OUTPUT_DIR/"
echo " 🌐 HTML: 已生成"
echo "============================================"

View File

@ -0,0 +1,117 @@
# gitlink-newcomer-guide API 参考
> **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解认证与全局参数。
## 命令参考
### issue +list
```bash
gitlink-cli issue +list --owner <owner> --repo <repo> --state open --format json
```
| 参数 | 必填 | 说明 |
|------|------|------|
| `--state, -s` | 否 | `open`/`closed`/`all`(默认 `open`**过滤不准确,需客户端二次过滤** |
| `--page, -p` | 否 | 页码(默认 1总数 >20 需翻页) |
| `--limit, -l` | 否 | 每页数量(默认 20 |
| `--format` | 否 | `json`/`table`/`yaml` |
API`GET /v1/{owner}/{repo}/issues?state=&page=&limit=`
### issue +view
```bash
gitlink-cli issue +view --owner <owner> --repo <repo> --number <index> --format json
```
| 参数 | 必填 | 说明 |
|------|------|------|
| `--number, -n` | **是** | Issue 网页编号(`project_issues_index` |
API`GET /v1/{owner}/{repo}/issues/{number}`
### issue +comment写操作
```bash
gitlink-cli issue +comment --owner <owner> --repo <repo> --number <index> --body "..."
```
| 参数 | 必填 | 说明 |
|------|------|------|
| `--number, -n` | **是** | Issue 网页编号 |
| `--body, -b` | **是** | 评论内容(映射为 v1 字段 `notes` |
API`POST /v1/{owner}/{repo}/issues/{number}/journals`Body `{"notes": body}`
> [!CAUTION] 写操作——执行前确认用户意图。
### 读取已有评论(用于去重)
```bash
gitlink-cli api GET /v1/:owner/:repo/issues/<number>/journals --query 'page=1&limit=50' --format json
```
返回 `data.journals[]`**注意是 `data.journals[]`,不是 `data[]`**)。每条 journal 分两类:
| journal 类型 | 特征字段 | 文本字段 |
|------|------|------|
| 评论 journal用户评论 | 含 `notes`、`attachments`、`children_journals`、`comments_count` | `notes`(评论正文) |
| 操作 journal状态/描述变更) | 含 `operate_category`、`operate_content`**无 `notes`** | `operate_content`(操作描述) |
**去重**:遍历 `data.journals[]`,仅对含 `notes` 字段的评论 journal检查其 `notes` 是否含标记串 `gitlink-newcomer-guide:v1`(操作 journal 无 `notes`,自然跳过)。
## Issue JSON 关键字段
| 字段 | 说明 |
|------|------|
| `project_issues_index` | Issue 网页编号(用于 `--number` |
| `subject` | 标题 |
| `status_id` | 状态1=新增、2=正在解决、3=已解决、5=关闭、0=未知 |
| `tags[]` | 标签数组,每个元素含 `name` |
| `assigners` | 负责人列表(空=未认领) |
| `priority` | 优先级null 或 `{name}` |
| `comment_journals_count` | 评论数(`+view` 返回) |
| `created_at`/`updated_at` | 时间 |
## 入门标签名变体
`tags[].name` 匹配以下任一(大小写不敏感)即视为入门 Issue
| 变体 |
|------|
| `good first issue` / `good-first-issue` / `good_first_issue` |
| `新手` / `新手任务` / `入门` |
| `help wanted` / `help-wanted` |
| `easy` / `beginner` / `低难度` |
匹配正则:`/good.?first.?issue|新手|入门|help.?wanted|easy|beginner|低难度/i`
## status_id 状态对照
| status_id | 含义 | 处理 |
|-----------|------|------|
| 1 | 新增 | ✅ 纳入候选 |
| 2 | 正在解决 | ✅ 纳入候选 |
| 3 | 已解决 | ❌ 排除 |
| 5 | 关闭 | ❌ 排除 |
| 0 | 未知 | ⚠️ 可纳入但标注"状态未知" |
## 幂等去重规则
- **标记串**`<!-- gitlink-newcomer-guide:v1 -->`追加在每条引导评论末尾网页不可见API 可读)。
- **发评论前**`api GET /v1/:owner/:repo/issues/<number>/journals`,遍历 `data.journals[]` 扫描评论 journal 的 `notes` 是否含标记串(操作 journal 无 `notes`,自动跳过)。
- 命中 → 跳过;未命中 → 发评论。
- **版本演进**:更新引导文案时把标记串改为 `v2`,即可对老 Issue 重发新版引导。
## 已知坑
- `issue +list --state open` 过滤不准确,返回可能含已关闭 Issue → 客户端按 `status_id` 二次过滤。
- 总数 >20 需 `--page 2..` 翻页(看 `meta.total_count`)。
- `gitlink-cli``label` 子命令;标签信息只来自 `issue +list``tags[]`。**经实测 `GET /v1/:owner/:repo/labels` 端点不存在**(返回 GitLink 首页 HTML无法通过 API 列出仓库标签或获取标签 ID若需在 `issue +create --label <id>` 中指定标签,标签 ID 只能从 GitLink 网页后台获取。
- **Windows Git BashMSYS路径坑**`gitlink-cli api GET /v1/...` 的 `/v1/...` 参数会被 MSYS 自动转换为 Windows 路径(如 `D:/Git/v1/...`),导致请求落到首页返回 HTML。解决命令前加 `MSYS_NO_PATHCONV=1`,或改用 PowerShell/cmd 执行 raw `api` 调用。
## References
- [gitlink-newcomer-guide SKILL](SKILL.md)
- [gitlink-shared](../gitlink-shared/SKILL.md)

View File

@ -12,6 +12,7 @@ metadata:
**CRITICAL — 开始前必须先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md),其中包含认证、权限处理和 API 注意事项。**
**CRITICAL — 所有 Shortcuts 在执行写入/删除操作前,务必先确认用户意图。**
**CRITICAL — `issue +comment` 是写操作,执行前必须确认用户意图;重复运行通过标记串幂等去重,不会刷屏。**
## 说明
@ -19,23 +20,29 @@ metadata:
## 依赖的 Shortcuts
| Shortcut | 用途 |
| Shortcut / 命令 | 用途 |
|----------|------|
| `issue +list` | 获取标记了 good-first-issue 的 Issue |
| `issue +list` | 列出 Issue用返回的 `tags[].name` 检测 good-first-issue |
| `issue +view` | 查看 Issue 详细内容 |
| `issue +comment` | 添加引导评论 |
| `label +list` | 查看可用标签 |
| `issue +comment` | 添加引导评论(写操作,先确认) |
| `api GET .../issues/:number/journals` | 读取已有评论,做幂等去重 |
| `repo +info` | 获取仓库基本信息 |
> 说明:`gitlink-cli` 没有 `label` 子命令(实测 `unknown command "label"`。good-first-issue 直接从 `issue +list``tags[].name` 字段判断,无需单独列标签。
## 工作流程
```
1. issue +list → 获取所有打开的 Issue
2. 筛选含 good-first-issue 标签的 Issue
3. issue +view --number {id} → 查看 Issue 详情
4. 分析 Issue 内容 → 判断适合的引导信息
5. issue +comment --body "..." → 添加引导评论
6. 可选issue +update → 分配 mentor
1. repo +info → 确认 owner/repo、默认分支
2. issue +list --state open --format json必要时 --page 2.. 翻页)
3. 客户端按 status_id 过滤:保留 1新增、2正在解决排除 3已解决、5关闭
—— 抵消 --state open 过滤不准确的已知问题
4. 按 tags[].name 匹配入门标签(/good.?first.?issue|新手|入门|help.?wanted|easy|beginner|低难度/i
5. 排除已分配assigners 非空)的 Issue除非标签是 help wanted
6. issue +view --number <index> → 取 description / comment_journals_count 判断 Issue 类型
7. 【去重】api GET /v1/:owner/:repo/issues/<index>/journals --format json
→ 扫描已有评论是否含标记串 `gitlink-newcomer-guide:v1`,命中则跳过
8. issue +comment --number <index> --body "<模板 + 标记串>" → 写操作,先确认用户意图
```
## 引导评论模板
@ -62,6 +69,8 @@ metadata:
- 在开发过程中遇到任何问题,也欢迎随时提问
祝你编码愉快!
<!-- gitlink-newcomer-guide:v1 -->
```
### 功能需求类 Issue
@ -85,6 +94,8 @@ metadata:
4. 提交 Pull Request描述你的改动
如有任何问题,随时留言!
<!-- gitlink-newcomer-guide:v1 -->
```
### 文档类 Issue
@ -108,25 +119,29 @@ metadata:
- 代码块请标注语言类型
期待你的贡献!
<!-- gitlink-newcomer-guide:v1 -->
```
## 使用示例
```bash
# 1. 查找所有标记了 good-first-issue 的 Issue
# 1. 列出开放 Issue用返回的 tags[].name 检测 good-first-issue
gitlink-cli issue +list --owner myuser --repo myrepo --state open --format json
# 2. 查看某个 Issue 的详细内容(判断类型)
# 2. 客户端过滤status_id ∈ {1,2} 且 tags[].name 匹配 good-first-issue且 assigners 为空
# 3. 查看 Issue 详情,判断类型
gitlink-cli issue +view --owner myuser --repo myrepo --number 10 --format json
# 3. 查看仓库可用标签
gitlink-cli label +list --owner myuser --repo myrepo
# 4. 【去重】读取已有评论,检查是否含标记串
gitlink-cli api GET /v1/myuser/myrepo/issues/10/journals --format json
# 4. 添加引导评论
gitlink-cli issue +comment --owner myuser --repo myrepo --number 10 --body "你好!欢迎参与贡献..."
# 5. 添加引导评论(写操作,先确认;评论末尾含 <!-- gitlink-newcomer-guide:v1 -->
gitlink-cli issue +comment --owner myuser --repo myrepo --number 10 --body "你好!欢迎参与贡献 🎉
...(正文)...
# 5. 可选:将 Issue 标记为已分配
gitlink-cli issue +update --owner myuser --repo myrepo --number 10
<!-- gitlink-newcomer-guide:v1 -->"
```
## 注意事项
@ -135,3 +150,5 @@ gitlink-cli issue +update --owner myuser --repo myrepo --number 10
- 如果 Issue 已经被 Assignee 认领,不需要再添加引导评论。
- 不要修改 good-first-issue 标签,由项目维护者管理。
- 引导评论建议使用温和、鼓励的语气。
- good-first-issue 检测依赖 `issue +list` 返回的 `tags[].name``gitlink-cli` 无 `label` 子命令,不要尝试调用任何形如 `gitlink-cli` + `label` 的写法
- `--state open` 过滤不准确,必须客户端按 `status_id`(保留 1、2二次过滤

View File

@ -28,7 +28,17 @@ gitlink-cli issue +view --owner z2_cc --repo gitlink-cli --number 10 --format js
- 是否是文档改进?→ 使用文档模板
- 是否是功能需求?→ 使用功能模板
### Step 3添加引导评论
### Step 3去重检查幂等
```bash
gitlink-cli api GET /v1/z2_cc/gitlink-cli/issues/10/journals --format json
```
扫描返回的 `data.journals[]`(仅评论 journal 有 `notes`,操作 journal 无 `notes` 自动跳过)的 `notes` 是否含标记串 `gitlink-newcomer-guide:v1`
- **命中** → 跳过该 Issue输出"已引导过 #10,跳过"
- **未命中** → 继续 Step 4
### Step 4添加引导评论
```bash
gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 10 --body "你好!欢迎参与贡献 🎉
@ -44,10 +54,12 @@ gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 10 --body "
- 如果对问题描述有疑问,可以在下方留言
- 开发过程中遇到任何问题,也欢迎随时提问
祝你编码愉快!"
祝你编码愉快!
<!-- gitlink-newcomer-guide:v1 -->"
```
### Step 4:确认引导已生效
### Step 5:确认引导已生效
```bash
gitlink-cli issue +view --owner z2_cc --repo gitlink-cli --number 10 --format json
@ -69,3 +81,24 @@ gitlink-cli issue +view --number <id>
# 3. 添加引导评论
gitlink-cli issue +comment --number <id> --body "<引导内容>"
```
## 批量场景
对多个 good-first-issue 循环执行:
```bash
# 伪流程
for index in <候选 issue 编号列表>; do
# 去重检查
already=$(gitlink-cli api GET /v1/<owner>/<repo>/issues/$index/journals --format json | grep -c "gitlink-newcomer-guide:v1")
if [ "$already" -gt 0 ]; then
echo "已引导过 #$index跳过"; continue
fi
# 按类型选模板 + 标记串,发评论(写操作,建议先汇总再批量确认)
gitlink-cli issue +comment --owner <owner> --repo <repo> --number $index --body "<模板>
<!-- gitlink-newcomer-guide:v1 -->"
done
```
输出汇总:`已引导 N 个 / 跳过 M 个`。

View File

@ -1,205 +0,0 @@
---
name: gitlink-pr-deep-review
version: 1.0.0
description: "PR 深度审查:编排代码质量审查 + 自研推理层,综合评估一个 PR 的实现质量、跨模块影响、需求/设计一致性、业务安全合规,给出综合裁决与动作建议。当用户需要深度审查 Pull Request、判断改动是否对得起需求/是否影响其他模块时触发。"
metadata:
requires:
bins: ["gitlink-cli"]
cliHelp: "gitlink-cli pr --help"
requiresVersion: "需要 gitlink-cli 含 `pr +versions/+version-diff/+review` 的版本本仓库源码已具备npm 发布版 v0.1.13 能力不全,需源码编译版或 ≥ v0.2.0"
---
# gitlink-pr-deep-reviewPR 深度审查)
**CRITICAL — 开始前必须先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md),其中包含认证、权限处理和 API 注意事项。**
**CRITICAL — 所有 Shortcuts 在执行写入操作(回贴评审/评论)前,务必先确认用户意图;默认 dry-run综合评审一律用 `--status common`(评论),不替人 approve/reject。**
**CRITICAL — GitLink 操作只能用 `gitlink-cli`,禁止用 `gh`GitHub CLI操作 GitLink 资源。**
## 说明
本 Skill 围绕 **PR 审查**提供深度服务:对给定 PR**编排** `gitlink-code-review`(或 linter取得"实现层"质量结果,再叠加本 Skill 的**自研推理层**——跨模块影响、需求/设计一致性、业务级安全/合规——交叉合成一份综合评审报告,给出风险评分与动作建议(阻断/谨慎/放行),并可在确认后回贴到 PR。
它**不重复** code-review 的风格/缺陷检测,而是**消费**其结果作为风险输入,专注于 code-review 回答不了的问题:**这个改动该不该这样改、会牵动什么、对不对得起它的目标。**
## 前置条件
- 已 `gitlink-cli auth login``auth status` 为已登录)。
- gitlink-cli 版本需支持 `pr +versions` / `+version-diff` / `+review`本仓库源码已具备npm 发布版 v0.1.13 不具备)。
- **本地有目标仓库的 clone**(跨模块调用方用 `git grep`、设计文档用本地读取)。
- (可选)读过 [`../gitlink-code-review/SKILL.md`](../gitlink-code-review/SKILL.md),便于编排其实现层工作流。
## 与 `gitlink-code-review` 的边界
| 维度 | `gitlink-code-review`(被编排) | `gitlink-pr-deep-review`(本 Skill |
|---|---|---|
| 审查对象 | 代码**本身**diff 内在质量) | 改动的**意图、设计、跨模块影响** |
| 核心问题 | 代码写得对不对/好不好 | 该不该这样改、会牵动什么、对不对得起目标 |
| 视角 | 单文件、当下 | 跨文件、关联需求/架构 |
| 工作性质 | 机械检测为主 | 推理判断为主 |
| 关系 | 上游信号 | 编排者 + 综合裁决 |
> 职责正交code-review 管"实现质量",本 Skill 管"设计/意图/影响一致性",可串联。
## 依赖的 Shortcuts
| Shortcut | 关键参数 | 用途 |
|----------|----------|------|
| `pr +view` | `--id <Web#>`、`--format json` | 标题=`data.issue.subject`**正文=`data.issue.description`(嵌套)**`comments_count` |
| `pr +files` | `--id` | 变更文件列表 |
| `pr +version-diff` | `--id`、`--version-id` | **真实 diff 内容**version_id 来自 `+versions` |
| `pr +versions` | `--id` | patchset 列表,取 `version_id` |
| `pr +reviews` | `--id` | 已有评审(避免重复回贴) |
| `pr +review` | `--id`、`--status common`、`--content`、`--dry-run` | 回贴综合评审(默认 dry-run |
| `pr +commits` / `pr +comments` | `--id` | 提交 / 评审行内评论(上下文) |
| `issue +view` | `--number <Web#>` | 关联 Issue 需求锚点 |
| `git grep`(本地) | `git grep -n "<symbol>" -- '*.ext'` | 跨模块**直接调用方** |
| 本地文件 `git show`/Read | — | 设计文档读取 |
> ⚠️ `--id`**Web 编号**`pr +list` 的 `pull_request_number`),非内部 `id`
## 工作流程
```
1. pr +view --id <N> → 取标题/正文issue.subject / issue.description
2. pr +files --id <N> → 变更文件清单
pr +versions --id <N> → 取 version_id
pr +version-diff --id <N> --version-id <V> → 真实 diff
3. 锚点获取(见下「锚点获取流程」) → 需求/设计一致性依据
4. 编排实现层:按 gitlink-code-review/SKILL.md 跑实现层审查
→ 取分级问题清单Critical/Warning/Suggestion作为风险输入
5. 跨模块影响:对改动符号 git grep 找直接调用方 → 标破坏性变更
6. 推理层:需求/设计一致性 + 业务安全/合规一致性(对照锚点)
7. 综合裁决:实现层 + 影响 + 一致性 + 安全 交叉 → 风险评分 + 动作建议
----- 以上为只读分析,默认到此为止 -----
8. 确认后pr +review --id <N> --status common --content "<综合报告>" [--dry-run]
```
## 锚点获取流程(需求一致性审查的依据)
需求/设计一致性需要一个"锚点"(正确性的参照)。按下列**交互式决策树**获取:
```
Step A询问使用者 —— 仓库中是否有与该 PR 相关的设计/需求文档?
├─ 有 → 使用者提供文档路径(仓库内相对路径)→ 本地读取git show <path> / Read→ design_doc
└─ 无 → design_doc = ∅
Step B自动检测 PR 关联 Issue
└─ pr +view 的 issue.description 里正则提取 #N → issue +view --number N → linked_issue
(无 #N 则 linked_issue = ∅)
Step C组合锚点
├─ design_doc ✓ + linked_issue ✓ → 锚点 = 两者合并Issue=需求源,文档=设计源)【置信度高】
├─ 仅其一 → 锚点 = 该单一来源【置信度中】
└─ 两者皆无 → 锚点 = PR 标题/描述自述目标;报告显著标注
「⚠️ 无外部需求锚点,一致性结论置信度降低」【置信度低】
```
> 无锚点时**不要拒绝审查**,而是降级为"以 PR 自述目标为准",并明确标注置信度。
## 评审维度与规则
### ① 实现层(编排 `gitlink-code-review`
- 调度 code-review 工作流(或项目 linter取其分级问题清单。
- 本 Skill **不重新检测**风格/缺陷,只**消费**:把 Critical/Warning 数量与位置作为风险输入。
### ② 跨模块影响(机械,自研)
- 从 diff 提取**改动符号**(函数名、类型名、导出标识)。
- 对每个符号 `git grep -n "<symbol>" -- '<glob>'` 找**直接调用方**(仅一层,不追传递依赖)。
- 标注破坏性变更:签名改变/删除/重命名 → 受影响调用方清单 + 影响范围分级(核心模块/边缘/无)。
### ③ 需求/设计一致性(推理,自研)
- 以**锚点**判断PR 是否真正实现了需求?设计是否与现有架构一致?有无过度设计/设计缺陷?
- 锚点缺失时降级(见上),结论标注低置信度。
### ④ 业务级安全/合规一致性(推理,自研)
- 非通用红线(注入/硬编码密钥等属 code-review而是**结合需求上下文**判断业务约束是否对齐(如:该改动是否绕过了应有的权限校验、是否合规留痕)。
### ⑤ 综合裁决(合成)
| 综合风险 | 触发条件(任一) | 动作建议 |
|---|---|---|
| 🔴 高 | 实现层有 Critical / 破坏性变更影响核心模块 / 需求未实现 | **阻断**合入 |
| 🟡 中 | 实现层有 Warning / 影响边缘模块 / 设计有改进点 | **谨慎**:修改后再合 |
| 🟢 低 | 实现层仅 Suggestion / 无跨模块破坏 / 与锚点一致 | **放行** |
## 综合评审报告模板
````markdown
## 🔍 PR 深度审查 — #<N> <标题>
**关联锚点**<Issue #X / 设计文档 path / 无外部锚点置信度低>
### 📎 实现层(编排 gitlink-code-review
- Critical: <n> | Warning: <n> | Suggestion: <n>(详见 code-review 报告)
- 摘要:<最关键的 13 >
### 🧩 跨模块影响
- 改动符号:<列表>
- 直接调用方受影响:<文件:行 列表 / >
- 影响范围:核心模块 / 边缘 / 无
### 🎯 需求/设计一致性
- 需求达成:✅/⚠️/❌ <理由>
- 设计一致性:✅/⚠️/❌ <理由>
### 🔒 业务安全/合规
- <结论 + 理由>
### 🏁 综合裁决
| 维度 | 结果 |
|---|---|
| 实现质量 | ✅/⚠️/❌ |
| 跨模块影响 | ✅/⚠️/❌ |
| 一致性 | ✅/⚠️/❌ |
| 安全合规 | ✅/⚠️/❌ |
**综合风险:🔴高/🟡中/🟢低 → 建议:<阻断/谨慎/放行>。一句话理由:<...>**
````
## 使用示例
> 在目标仓库的 git 目录下可省略 `--owner/--repo`。AI 场景统一 `--format json`
```bash
# 0) 前置
gitlink-cli auth status
gitlink-cli pr +versions --help # 存在 → 版本满足
git config pull.rebase false 2>/dev/null; cd <目标仓库 clone>
# 1) 取 PR 上下文N = Web 编号,来自 pr +list 的 pull_request_number
N=1
gitlink-cli pr +view --id $N --format json # 标题=issue.subject, 正文=issue.description
gitlink-cli pr +files --id $N --format json # 变更文件
VID=$(gitlink-cli pr +versions --id $N --format json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const d=JSON.parse(s).data;const a=Array.isArray(d)?d:d.versions;process.stdout.write(String((a[0]||{}).id));});')
gitlink-cli pr +version-diff --id $N --version-id $VID --format json # 真实 diff
# 2) 锚点:从 PR body 提取关联 Issue → 取需求
ISSUE_N=$(gitlink-cli pr +view --id $N --format json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const b=JSON.parse(s).data.issue.description;const m=b.match(/#(\d+)/);process.stdout.write(m?m[1]:"");});')
[ -n "$ISSUE_N" ] && gitlink-cli issue +view --number $ISSUE_N --format json
# 另:询问使用者是否有设计文档,有则 git show <path> 读取
# 3) 跨模块直接调用方(对每个改动符号)
git grep -n "ChangedFunction" -- '*.go'
# 4) 编排实现层:按 ../gitlink-code-review/SKILL.md 跑一遍,取分级问题清单
# 5) 综合裁决后,确认 → 回贴(默认 dry-run--status common 不替人 approve/reject
gitlink-cli pr +review --id $N --status common \
--content "## 🔍 PR 深度审查 ..." --dry-run # 先预览
# 确认无误后去掉 --dry-run 正式回贴
```
## 已知限制实测v0.2.0-dev / 本地源码版)
- **`pr +diff` 不存在**:本地版无此子命令(`skills/gitlink-pr/SKILL.md` 里的 `+diff` 已过时)。用 `pr +files` + `pr +version-diff`
- **`pr +view` 正文嵌套**:标题在 `data.issue.subject`、正文在 `data.issue.description`**非顶层**字段。
- **`pr +comments` 只列评审行内评论**,不含普通评论。普通 `pr +comment` 是否落地,用 `pr +view``comments_count` 验证。
- **CLI 远程文件读取不可用**`api GET .../sub_entries` 返回 404、`.../raw/...` 返回空。设计文档**一律走本地**`git show`/Read
- **跨模块仅直接调用方**:不追多层传递依赖(按设计,控制规模)。
- **无锚点降级**PR 未关联 Issue 且无设计文档时,一致性结论置信度低,须显著标注。
## 注意事项
- **默认 dry-run**:综合评审先 `--dry-run` 预览,确认后再正式回贴。
- **不越权**:回贴用 `--status common`(评论),**不**用 `approved`/`rejected` 替人决定合入。
- **编排而非复制**:实现层交给 code-review/linter本 Skill 只消费其结果,不重写检测规则(避免与 code-review 重合)。
- **大 PR**`pr +version-diff` 输出可能很大,分段处理;`git grep` 限定文件 glob 控制规模。
- **锚点优先级**:关联 Issue 是最可靠的需求源;设计文档次之;两者皆无才降级。

View File

@ -1,149 +0,0 @@
# PR 深度审查 — 端到端工作流示例与验证记录
> 配套文档:[`../SKILL.md`](../SKILL.md)
> 本文记录一次**真实跑通**的完整工作流(只读分析 + 写动作),含真实命令输出,作为「使用示例 + Agent 平台验证结果」交付物。
## 验证环境
| 项 | 值 |
|----|----|
| Agent 平台 | Claude Code |
| gitlink-cli | `local-build`(本仓库源码编译产物,**非** npm 发布版 v0.1.13 |
| 登录用户 | `z2_cc``auth status` ✓) |
| 测试目标 | `z2_cc/gitlink-cli`z2_cc 有写权限Owner |
| 测试 PR | #1`feat(auth): 登录态过期自动跳转登录页`body 引用 `#17` |
| 验证日期 | 2026-06-17 |
## 测试数据构造(造一个"PR + 关联 Issue"的真实样本)
为覆盖「关联 Issue 锚点」+「写链路」,先造测试数据(验证后已清理):
```bash
# 1) 造需求锚点 Issue→ Web #17
gitlink-cli issue +create --owner z2_cc --repo gitlink-cli \
-t "[deep-review-test] 登录态过期未自动跳转" -b "## 需求 ..." # → id=144670, #17
# 2) 造带 diff 的分支并 push提交署名 z2_cc
git checkout -b test/pr-deep-review-probe
# <新增 _deep_review_probe.md>
git commit -m "test(pr-deep-review): ...(关联 #17"
git push -u origin test/pr-deep-review-probe
# 3) 建 PRbody 引用 #17(→ Web #1
gitlink-cli pr +create --owner z2_cc --repo gitlink-cli \
--head test/pr-deep-review-probe --base master \
--title "feat(auth): 登录态过期自动跳转登录页(含回跳)" \
--body "## 关联需求\n修复 #17 :登录态过期未自动跳转。..." # → id=144671, #1
```
## 步骤 1取 PR 上下文(实测输出)
```bash
N=1
gitlink-cli pr +view --owner z2_cc --repo gitlink-cli --id $N --format json
```
→ 标题在 `data.issue.subject`、**正文在 `data.issue.description`**(嵌套,非顶层):
```
PR 标题: feat(auth): 登录态过期自动跳转登录页(含回跳)
body 长度: 153 ← data.issue.description
```
```bash
gitlink-cli pr +files --id 1 --format json # → 变更文件: 1 (_deep_review_probe.md)
VID=$(gitlink-cli pr +versions --id 1 --format json | ...) # → version_id=17388
gitlink-cli pr +version-diff --id 1 --version-id 17388 # → diff 条目: 1
```
## 步骤 2锚点获取实测从 body 提取 #N → 取需求)
```bash
# 从 PR body 提取关联 Issue 编号
BODY=$(gitlink-cli pr +view --id 1 --format json | ... data.issue.description)
ISSUE_N=$(echo "$BODY" | ... match /#(\d+)/) # → 17
```
实测:从 153 字 body 提取到 **`#17`** ✓
```bash
gitlink-cli issue +view --number 17 --format json # 取需求锚点
```
→ 锚点 Issue`[deep-review-test] 登录态过期未自动跳转`,需求正文 120 字(含验收标准)✓
> (若使用者还提供了设计文档路径,则 `git show <path>` 读取后与 Issue 合并为锚点;本次测试仅 Issue 锚点。)
## 步骤 3跨模块直接调用方实测机制
```bash
git grep -n "<改动符号>" -- '*.go'
```
`git grep` 机制可用(本仓库实测命中准确)。本测试 PR 仅改文档无代码符号,故无调用方受影响。
## 步骤 4编排实现层 + 推理层 → 综合裁决(示例输出)
```markdown
## 🔍 PR 深度审查 — #1 feat(auth): 登录态过期自动跳转登录页
**关联锚点**#17从 PR body 自动识别)
### 📎 实现层(编排 gitlink-code-review
- Critical: 0 | Warning: 0 | Suggestion: 0本 PR 仅新增说明文档,无逻辑代码)
### 🧩 跨模块影响
- 改动符号:无(仅文档)
- 直接调用方受影响:无
### 🎯 需求/设计一致性
- 需求达成:❌ #17 要求 401→自动跳转本 PR 尚无实际拦截/跳转代码(仅文档占位)
### 🏁 综合裁决
| 维度 | 结果 |
|---|---|
| 实现质量 | ✅ |
| 跨模块影响 | ✅ |
| 一致性 | ❌ 未实现 |
**综合风险:🟡中 → 建议:谨慎,补全实现后再合入。**
```
## 步骤 5写动作实测真实回贴 + 验证落地)
```bash
# 回贴综合评审(--status common = 评论,不替人 approve/reject
gitlink-cli pr +review --owner z2_cc --repo gitlink-cli --id 1 \
--status common --content "## 🔍 PR 深度审查 ..." --format json
```
`评审已回贴 ✓`
```bash
# 验证评审落地
gitlink-cli pr +reviews --id 1 --format json # → 已有 reviews: 1含「深度审查」 ✓
```
```bash
# 补充普通评论
gitlink-cli pr +comment --owner z2_cc --repo gitlink-cli --id 1 \
--body "💡 提示:补全 401 拦截逻辑后可重新触发深度审查。" --format json
```
`评论已发布 ✓`;落地验证用 `pr +view``comments_count`=1
> ⚠️ `pr +comments` 只列**评审行内评论**,不含普通评论——普通评论落地看 `pr +view``comments_count`
## 关键验证结论
| 能力 | 命令 | 状态 |
|------|------|------|
| 取 PR 标题/正文 | `pr +view``data.issue.subject`/`data.issue.description` | ✅ 真实返回 |
| 变更文件 | `pr +files` | ✅ |
| 真实 diff | `pr +version-diff --version-id` | ✅(`pr +diff` 不存在) |
| patchset | `pr +versions` | ✅ |
| **关联 Issue 锚点** | `pr +view` body→`#N`→`issue +view` | ✅ 端到端跑通 |
| 跨模块直接调用方 | `git grep` | ✅ 机制可用 |
| **回贴综合评审** | `pr +review --status common` | ✅ 实际回贴 + `pr +reviews` 验证 |
| 普通评论 | `pr +comment` | ✅(落地看 `pr +view` `comments_count` |
## 清理
测试产物已全部清理,`z2_cc/gitlink-cli` 无残留:
- `pr +close --id 1`(关闭测试 PR
- `git push origin --delete test/pr-deep-review-probe`(删远端分支)
- `issue +delete --number 17`(删测试 Issue
- 本地切回 `master`、删本地分支(工作树干净,`master == origin/master`
> ⚠️ 版本前提:以上能力依赖含 `pr +versions/+version-diff/+review` 的 gitlink-cli本仓库源码已具备npm 发布版 v0.1.13 不具备)。参赛验证基于本地源码编译产物。

View File

@ -1,172 +0,0 @@
---
name: gitlink-project-bootstrap
version: 1.0.0
description: "项目一键初始化:输入描述 → 创建仓库 → 生成 README/LICENSE/CI → 创建初始 Issue 和里程碑。"
metadata:
requires:
bins: ["gitlink-cli", "jq"]
cliHelp: "gitlink-cli repo +create --help / gitlink-cli file +create --help / gitlink-cli milestone +create --help"
---
# gitlink-project-bootstrap项目一键初始化
> **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解认证、全局参数和 API 注意事项。
>
> **CRITICAL — 所有 GitLink 操作必须使用 `gitlink-cli`,禁止使用 `gh`GitHub CLI操作 GitLink 资源。**
## 说明
本 Skill 串联 **三个阶段** 完成一个新项目的"开箱即用"初始化:从一句自然语言项目描述出发,自动创建仓库、生成骨架文件、创建里程碑与初始 Issue让项目在几分钟内即可进入协作状态。
1. **解析需求 + 创建仓库** — 从 `PROJECT_DESC` 用 AI 提取项目名/一句话简介/主语言/许可证偏好/可见性,调用 `gitlink-cli repo +create` 创建仓库
2. **生成项目骨架** — 生成 README.md / LICENSE / .gitignore / CI 配置,通过 `gitlink-cli file +batch`(或逐个 `file +create`)推送到新仓库
3. **创建初始 Issue 和里程碑** — 创建 v0.1.0 里程碑、起始标签good-first-issue/enhancement/bug和 2-3 个初始 Issue
---
## 三阶段工作流总览
```mermaid
flowchart LR
A[项目描述 PROJECT_DESC] --> B[Phase 1: 解析 + 建仓]
B --> C[Phase 2: 骨架文件]
C --> D[Phase 3: Issue + 里程碑]
subgraph B[Phase 1: 解析 + 建仓]
B1[读取 PROJECT_DESC] --> B2[AI 提取结构化 spec]
B2 --> B3[落盘 project-spec.json]
B3 --> B4[repo +create]
end
subgraph C[Phase 2: 骨架]
C1[读取 project-spec.json] --> C2[README/LICENSE/.gitignore/CI]
C2 --> C3[file +batch 推送]
end
subgraph D[Phase 3: Issue + 里程碑]
D1[milestone v0.1.0] --> D2[label 起始标签]
D2 --> D3[issue +create ×N]
end
```
---
## Phase 1解析需求 + 创建仓库
### AI 解析逻辑
输入(环境变量 `PROJECT_DESC` 或脚本第一个额外参数)是一段自然语言描述,例如:
> 一个用 Go 编写的 GitLink 命令行工具MIT 许可证,公开仓库。
AI脚本运行时由 Agent 执行)按以下规则提取结构化字段,落盘到 `_output/project-spec.json`
| 字段 | 提取规则 | 兜底默认 |
|------|----------|----------|
| `name` | 项目名(英文小写连字符) | `my-project` |
| `description` | 一句话简介 | 取描述前 40 字 |
| `language` | 主语言go/node/python/... | `go` |
| `license` | MIT / Apache-2.0 / GPL-3.0 | `MIT` |
| `private` | 公开/私有true/false | `false` |
### 命令
```bash
# 1. 创建仓库dry-run 优先)
gitlink-cli repo +create --name <name> --description "<description>" --private true|false
# 2. 验证仓库已创建
gitlink-cli repo +info --owner <owner> --repo <name> --format json
```
---
## Phase 2生成项目骨架文件
### 生成产物(由 `skeleton-gen.js` 驱动)
| 文件 | 内容 | 依据 |
|------|------|------|
| `README.md` | 标题/简介/安装/用法/贡献/许可证 | `project-spec.json` |
| `LICENSE` | 完整许可证正文MIT/Apache-2.0/GPL-3.0 任选其一写全) | `license` 字段 |
| `.gitignore` | 按主语言给出合理模板Go/Node/Python | `language` 字段 |
| `.devops/构建流水线.yml` | 最小可用的 GitLink CI 流水线片段 | 固定模板 |
LICENSE 内嵌**完整正文**,版权行使用 `[year] [project author]` / `<owner>` 占位,便于人工替换。
### 推送命令
```bash
# 方式 A逐个创建最稳
gitlink-cli file +create --path README.md --content "$(cat README.md)" --message "docs: 初始化 README"
# 方式 B批量提交推荐单次 commit
# files 是 JSON 数组:[{"path":"README.md","content":"...","action":"create"}, ...]
gitlink-cli file +batch --files '<JSON数组>' --message "chore: 初始化项目骨架" --branch master
# 可选:列出平台内置模板
gitlink-cli util +licenses
gitlink-cli util +ignores
```
> 不确定 `file +batch` 字段名时,先 `file +batch --help` 确认;不确定就退回逐个 `file +create`
---
## Phase 3创建初始 Issue 和里程碑
### 命令
```bash
# 1. 创建里程碑 v0.1.0due-date 用今天 +30 天)
gitlink-cli milestone +create -t "v0.1.0" -d "首个里程碑:完成核心功能与文档" --due-date YYYY-MM-DD
# 2. 创建起始标签color 为 hex 无 #
gitlink-cli label +create --name "good-first-issue" --color 7057ff
gitlink-cli label +create --name "enhancement" --color a2eeef
gitlink-cli label +create --name "bug" --color d73a4a
# 3. 创建初始 Issue关联里程碑和标签
gitlink-cli issue +create -t "完善 README 文档" -b "补充安装、用法、贡献指南" --milestone <id> --label <id>
gitlink-cli issue +create -t "配置 CI 流水线" -b "确保 push/PR 触发构建与测试" --milestone <id> --label <id>
gitlink-cli issue +create -t "撰写贡献指南 CONTRIBUTING.md" -b "说明提交流程、代码规范" --milestone <id> --label <id>
```
所有写操作在 `DRY_RUN=true` 时只打印 `[DRY-RUN] 将执行 ...`,不真正调用;`DRY_RUN=false` 才真正执行。
---
## 可复现脚本
本 Skill 提供可直接执行的 Bash 脚本,位于 `scripts/` 目录:
| 脚本 | 功能 | 使用方式 |
|------|------|----------|
| `01-parse-and-create-repo.sh` | Phase 1 解析需求 + 建仓 | `bash 01-parse-and-create-repo.sh <owner> <repo>` |
| `02-generate-skeleton.sh` | Phase 2 生成骨架文件 | `bash 02-generate-skeleton.sh <owner> <repo>` |
| `03-create-issues-milestones.sh` | Phase 3 里程碑/标签/Issue | `bash 03-create-issues-milestones.sh <owner> <repo>` |
| `project-bootstrap-full.sh` | 全流程串联 | `bash project-bootstrap-full.sh <owner> <repo>` |
| `skeleton-gen.js` | Phase 2 文件生成引擎(被 02 调用) | `node skeleton-gen.js <_output_dir>` |
**所有脚本默认 dry-run 模式**(不会实际修改数据),确认无误后通过环境变量切换:
```bash
# Dry-run默认安全
PROJECT_DESC="一个用 Go 编写的 GitLink 命令行工具" \
DRY_RUN=true bash scripts/project-bootstrap-full.sh z2_cc gitlink-cli
# 实际执行
PROJECT_DESC="一个用 Go 编写的 GitLink 命令行工具" \
DRY_RUN=false bash scripts/project-bootstrap-full.sh z2_cc gitlink-cli
```
---
## 注意事项
1. **dry-run 优先**:所有写操作(`repo +create`、`file +create`、`milestone +create`、`label +create`、`issue +create`)默认不应实际执行
2. **Token 有效**:运行前确认 `gitlink-cli auth status` 返回正常;离线/未认证时脚本用 `|| echo "[WARN] ..."` 优雅降级,不中途退出
3. **AI 解析需复核**:项目名/许可证/可见性的自动提取建议人工确认后再 `DRY_RUN=false`
4. **LICENSE 占位**:生成的 LICENSE 含 `[year] [project author]` 占位,需人工替换为真实版权人
5. **`file +batch` 字段名**:先用 `--help` 确认,不确定就退回逐个 `file +create`
6. **输出文件**:所有产物保存到 `scripts/_output/`(含 `project-spec.json`、`skeleton/` 子目录、`init-report.md` 及对应 HTML供审计

View File

@ -1,164 +0,0 @@
# 项目一键初始化工作流 — 端到端示例
**场景**:开发者希望快速启动一个新项目:输入一句话描述,自动创建仓库、生成 README/LICENSE/CI 骨架、建立首个里程碑与初始 Issue5 分钟即可进入协作。
## 前置条件
- `gitlink-cli` 已安装并登录(`gitlink-cli auth status`
- 目标仓库所有者已确认(示例使用 `z2_cc`
- `jq` 已安装(用于 JSON 解析)
- `node` 已安装(用于 `skeleton-gen.js``md-to-html.js`
## 输入
```bash
export PROJECT_DESC="一个用 Go 编写的 GitLink 命令行工具MIT 许可证,公开仓库。"
```
## 工作流步骤
### Step 1解析需求 + 创建仓库
```bash
# 1.1 AI 解析 PROJECT_DESC落盘 _output/project-spec.json
# name → gitlink-cli从描述推断但本次演示仓库名复用参数 gitlink-cli-demo
# description → 一个用 Go 编写的 GitLink 命令行工具
# language → go
# license → MIT
# private → false
```
**`_output/project-spec.json` 输出示例:**
```json
{
"name": "gitlink-cli-demo",
"description": "一个用 Go 编写的 GitLink 命令行工具",
"language": "go",
"license": "MIT",
"private": false,
"owner": "z2_cc"
}
```
```bash
# 1.2 创建仓库dry-run 模式)
DRY_RUN=true
gitlink-cli repo +create --name gitlink-cli-demo \
--description "一个用 Go 编写的 GitLink 命令行工具" --private false
```
**输出示例:**
```json
{ "ok": true, "data": { "name": "gitlink-cli-demo", "id": 123456, "private": false } }
```
```bash
# 1.3 验证仓库已创建
gitlink-cli repo +info --owner z2_cc --repo gitlink-cli-demo --format json
```
**Expected:** `project-spec.json` 生成dry-run 模式下 `[DRY-RUN] 将执行 repo +create ...`,不实际建仓。
---
### Step 2生成项目骨架文件
```bash
# 2.1 运行骨架生成引擎
node scripts/skeleton-gen.js _output
```
**AI 生成逻辑说明:**
```
读取 _output/project-spec.json
→ language=go → 生成 Go 风格 .gitignorebin/、*.exe、vendor/
→ license=MIT → 写完整 MIT 正文,版权行 "Copyright (c) 2026 [project author]"
→ name + description → 拼装 README标题/简介/安装/用法/贡献/许可证)
→ 固定模板 → .devops/构建流水线.yml最小可用 Go 构建)
落盘到 _output/skeleton/{README.md, LICENSE, .gitignore, .devops/构建流水线.yml}
```
**`_output/skeleton/` 产物清单:**
```
README.md
LICENSE
.gitignore
.devops/构建流水线.yml
```
```bash
# 2.2 推送到新仓库dry-run 模式)
DRY_RUN=true
# 优先 file +batch单次 commit不确定字段时退回逐个 file +create
gitlink-cli file +batch \
--files '[{"path":"README.md","content":"# ...","action":"create"}, ...]' \
--message "chore: 初始化项目骨架" --branch master
```
**Expected:** `skeleton/` 下四个文件齐全dry-run 下 `[DRY-RUN] 将执行 file +batch ...`
---
### Step 3创建里程碑 / 标签 / 初始 Issue
```bash
# 3.1 创建里程碑 v0.1.0due-date = 今天 +30 天)
gitlink-cli milestone +create -t "v0.1.0" \
-d "首个里程碑:完成核心功能与文档" --due-date 2026-08-01
```
**输出示例:**
```json
{ "ok": true, "data": { "id": 1001, "name": "v0.1.0" } }
```
```bash
# 3.2 创建起始标签
gitlink-cli label +create --name "good-first-issue" --color 7057ff
gitlink-cli label +create --name "enhancement" --color a2eeef
gitlink-cli label +create --name "bug" --color d73a4a
```
```bash
# 3.3 创建 3 个初始 Issue关联里程碑与标签dry-run
DRY_RUN=true
gitlink-cli issue +create -t "完善 README 文档" \
-b "补充安装、用法、贡献指南" --milestone 1001 --label <enhancement_id>
gitlink-cli issue +create -t "配置 CI 流水线" \
-b "确保 push/PR 触发构建与测试" --milestone 1001 --label <enhancement_id>
gitlink-cli issue +create -t "撰写贡献指南 CONTRIBUTING.md" \
-b "说明提交流程、代码规范" --milestone 1001 --label <good_first_issue_id>
```
**Expected:** 1 个里程碑、3 个标签、3 个初始 Issue 建议生成dry-run 下全部 `[DRY-RUN]`
---
## 完整命令速览
```bash
# Phase 1: 解析 + 建仓
PROJECT_DESC="一个用 Go 编写的 GitLink 命令行工具" \
bash scripts/01-parse-and-create-repo.sh z2_cc gitlink-cli-demo
# Phase 2: 骨架
bash scripts/02-generate-skeleton.sh z2_cc gitlink-cli-demo
# Phase 3: Issue + 里程碑
bash scripts/03-create-issues-milestones.sh z2_cc gitlink-cli-demo
# 一键全流程
PROJECT_DESC="一个用 Go 编写的 GitLink 命令行工具" \
bash scripts/project-bootstrap-full.sh z2_cc gitlink-cli-demo
```
## 最终报告
`_output/init-report.md`**综合评分X/10** 形式的"初始化完成度"并列表展示已生成的产物README/LICENSE/.gitignore/CI/里程碑/标签/Issue。经 `md-to-html.js` 转换后生成可视化 HTML。
## 注意事项
- 所有写操作默认 dry-run确认后通过 `DRY_RUN=false` 实际执行
- AI 解析出的项目名/许可证/可见性建议人工复核
- 生成 LICENSE 中的 `[year] [project author]` 占位需替换为真实版权人
- 离线/未认证时脚本优雅降级,仍能产出 init-report.md 供审阅

View File

@ -1,85 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 1: 解析需求 + 创建仓库
# 功能:读取 PROJECT_DESC → AI 提取结构化 spec → 落盘 project-spec.json → repo +create
# 使用bash 01-parse-and-create-repo.sh <owner> <repo>
# 环境变量:
# PROJECT_DESC 项目自然语言描述(必填)
# DRY_RUN true|false (默认 true)
# ================================================================
set -e
# ---- 参数解析 ----
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2:=$1}
DRY_RUN=${DRY_RUN:-true}
PROJECT_DESC=${PROJECT_DESC:-$3}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 1: 解析需求 + 创建仓库 ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[ DRY_RUN: $DRY_RUN ]"
echo "[========================================]"
if [ -z "$PROJECT_DESC" ]; then
echo "[WARN] 未提供 PROJECT_DESC使用兜底默认值用于 dry-run 演示)"
PROJECT_DESC="一个用 Go 编写的 GitLink 命令行工具MIT 许可证,公开仓库。"
fi
echo "[INFO] PROJECT_DESC = $PROJECT_DESC"
# ---- Step 1: AI 解析(占位逻辑 + 兜底)----
# AI Agent 在运行本脚本时根据 PROJECT_DESC 实际内容填充以下字段。
# 这里给出基于关键词的简单兜底解析,确保离线也能产出合法 spec。
NAME="$REPO"
DESCRIPTION=$(echo "$PROJECT_DESC" | cut -c1-60)
LANGUAGE="go"
LICENSE="MIT"
PRIVATE="false"
# 简单关键词识别AI 应覆盖更复杂情形)
if echo "$PROJECT_DESC" | grep -qiE "python|py\b"; then LANGUAGE="python"; fi
if echo "$PROJECT_DESC" | grep -qiE "node|js\b|javascript|typescript|前端"; then LANGUAGE="node"; fi
if echo "$PROJECT_DESC" | grep -qi "apache"; then LICENSE="Apache-2.0"; fi
if echo "$PROJECT_DESC" | grep -qi "gpl"; then LICENSE="GPL-3.0"; fi
if echo "$PROJECT_DESC" | grep -qiE "私有|private|内部"; then PRIVATE="true"; fi
# 写入 project-spec.json
cat > "$OUTPUT_DIR/project-spec.json" <<EOF
{
"name": "$NAME",
"description": "$DESCRIPTION",
"language": "$LANGUAGE",
"license": "$LICENSE",
"private": $PRIVATE,
"owner": "$OWNER"
}
EOF
echo "[INFO] project-spec.json 已生成: $OUTPUT_DIR/project-spec.json"
cat "$OUTPUT_DIR/project-spec.json"
# ---- Step 2: 创建仓库dry-run 保护) ----
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] 将执行: gitlink-cli repo +create --name $NAME --description \"$DESCRIPTION\" --private $PRIVATE"
else
echo "[INFO] 调用 repo +create..."
RESULT=$(gitlink-cli repo +create --name "$NAME" \
--description "$DESCRIPTION" --private "$PRIVATE" --format json 2>&1) \
|| { echo "[WARN] repo +create 失败: $RESULT"; exit 0; }
echo "$RESULT" > "$OUTPUT_DIR/repo-create.json"
echo "[INFO] 仓库创建响应已保存"
fi
# ---- Step 3: 验证仓库(可失败,降级) ----
echo "[INFO] 验证仓库是否可访问..."
INFO=$(gitlink-cli repo +info --owner "$OWNER" --repo "$NAME" --format json 2>&1) \
&& echo "$INFO" > "$OUTPUT_DIR/repo-info.json" \
|| echo "[WARN] 仓库尚未创建或未登录dry-run 下属正常)"
echo ""
echo "[========================================]"
echo "[ Phase 1 完成 ]"
echo "[ spec 保存至: $OUTPUT_DIR/project-spec.json ]"
echo "[========================================]"

View File

@ -1,76 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 2: 生成项目骨架文件
# 功能:读取 project-spec.json → 生成 README/LICENSE/.gitignore/CI → 推送到仓库
# 使用bash 02-generate-skeleton.sh <owner> <repo>
# 环境变量DRY_RUN=true|false (默认 true)
# ================================================================
set -e
# 自动检测并使用本地编译的 gitlink-cli
source "$(cd "$(dirname "$0")" && pwd)/../../gitlink-shared/scripts/detect-cli.sh"
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 2: 生成项目骨架 ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[ DRY_RUN: $DRY_RUN ]"
echo "[========================================]"
# ---- Step 1: 检查 spec ----
if [ ! -f "$OUTPUT_DIR/project-spec.json" ]; then
echo "[WARN] 未找到 project-spec.json先回退执行 Phase 1 的兜底解析"
bash "$SCRIPT_DIR/01-parse-and-create-repo.sh" "$OWNER" "$REPO" >/dev/null 2>&1 || {
echo "[ERROR] project-spec.json 仍缺失,无法继续"; exit 1;
}
fi
echo "[INFO] spec 文件就绪: $OUTPUT_DIR/project-spec.json"
# ---- Step 2: 运行骨架生成引擎 ----
echo "[INFO] 运行 skeleton-gen.js 生成 README/LICENSE/.gitignore/CI..."
node "$SCRIPT_DIR/skeleton-gen.js" "$OUTPUT_DIR"
SKEL_DIR="$OUTPUT_DIR/skeleton"
if [ ! -d "$SKEL_DIR" ]; then
echo "[ERROR] skeleton 目录未生成"; exit 1
fi
echo "[INFO] 骨架文件已生成到 $SKEL_DIR/"
# ---- Step 3: 推送到仓库dry-run 保护) ----
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] 将执行: gitlink-cli file +create 逐个推送 README/LICENSE/.gitignore/CI"
echo "[DRY-RUN](或 file +batch 单次 commit建议先 file +batch --help 确认字段)"
else
echo "[INFO] 通过 file +create 逐个推送(最稳,规避 batch 字段歧义)..."
for f in README.md LICENSE .gitignore; do
if [ -f "$SKEL_DIR/$f" ]; then
CONTENT=$(cat "$SKEL_DIR/$f")
gitlink-cli file +create --owner "$OWNER" --repo "$REPO" \
--path "$f" --content "$CONTENT" --message "chore: 初始化 $f" 2>&1 \
| tee -a "$OUTPUT_DIR/file-create.log" \
|| echo "[WARN] 推送 $f 失败(已记录)"
fi
done
# CI 配置
if [ -f "$SKEL_DIR/.devops/构建流水线.yml" ]; then
CONTENT=$(cat "$SKEL_DIR/.devops/构建流水线.yml")
gitlink-cli file +create --owner "$OWNER" --repo "$REPO" \
--path ".devops/构建流水线.yml" --content "$CONTENT" \
--message "ci: 初始化构建流水线" 2>&1 \
| tee -a "$OUTPUT_DIR/file-create.log" \
|| echo "[WARN] 推送 CI 配置失败"
fi
echo "[INFO] 骨架推送完成"
fi
echo ""
echo "[========================================]"
echo "[ Phase 2 完成 ]"
echo "[ 骨架保存至: $SKEL_DIR/ ]"
echo "[========================================]"

View File

@ -1,108 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 3: 创建初始 Issue 和里程碑
# 功能:创建 v0.1.0 里程碑 → 起始标签 → 3 个初始 Issue
# 使用bash 03-create-issues-milestones.sh <owner> <repo>
# 环境变量DRY_RUN=true|false (默认 true)
# ================================================================
set -e
# 自动检测并使用本地编译的 gitlink-cli
source "$(cd "$(dirname "$0")" && pwd)/../../gitlink-shared/scripts/detect-cli.sh"
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
# 里程碑 due-date = 今天 +30 天
DUE_DATE=$(date -d "+30 days" '+%Y-%m-%d' 2>/dev/null || date -v+30d '+%Y-%m-%d' 2>/dev/null || echo "2030-12-31")
echo "[========================================]"
echo "[ Phase 3: 创建 Issue 和里程碑 ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[ DRY_RUN: $DRY_RUN ]"
echo "[========================================]"
# ---- Step 1: 创建里程碑 ----
MILESTONE_ID=""
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] 将执行: milestone +create -t v0.1.0 --due-date $DUE_DATE"
MILESTONE_ID="<pending>"
else
echo "[INFO] 创建里程碑 v0.1.0..."
MS=$(gitlink-cli milestone +create -t "v0.1.0" \
-d "首个里程碑:完成核心功能与文档" --due-date "$DUE_DATE" \
--owner "$OWNER" --repo "$REPO" --format json 2>&1) \
|| { echo "[WARN] 创建里程碑失败: $MS"; MS='{"data":{"id":""}}'; }
echo "$MS" > "$OUTPUT_DIR/milestone.json"
MILESTONE_ID=$(echo "$MS" | node -e "
let s='';
process.stdin.on('data',d=>s+=d).on('end',()=>{
try { const d=JSON.parse(s).data||{}; process.stdout.write(String(d.id||d.milestone_id||'')); }
catch(e){ process.stdout.write(''); }
});
" 2>/dev/null)
echo "[INFO] 里程碑 ID: ${MILESTONE_ID:-(未知)}"
fi
# ---- Step 2: 创建起始标签 ----
declare -a LABEL_NAMES=("good-first-issue" "enhancement" "bug")
declare -a LABEL_COLORS=("7057ff" "a2eeef" "d73a4a")
declare -a LABEL_IDS=()
for i in 0 1 2; do
NAME="${LABEL_NAMES[$i]}"
COLOR="${LABEL_COLORS[$i]}"
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] 将执行: label +create --name $NAME --color $COLOR"
LABEL_IDS[$i]="<pending>"
else
RES=$(gitlink-cli label +create --name "$NAME" --color "$COLOR" \
--owner "$OWNER" --repo "$REPO" --format json 2>&1) \
|| { echo "[WARN] 创建标签 $NAME 失败: $RES"; RES='{"data":{"id":""}}'; }
LID=$(echo "$RES" | node -e "
let s='';
process.stdin.on('data',d=>s+=d).on('end',()=>{
try { const d=JSON.parse(s).data||{}; process.stdout.write(String(d.id||'')); }
catch(e){ process.stdout.write(''); }
});
" 2>/dev/null)
LABEL_IDS[$i]="$LID"
echo "[INFO] 标签 $NAME ID: ${LID:-(未知)}"
fi
done
ENH_ID="${LABEL_IDS[1]}"
GFI_ID="${LABEL_IDS[0]}"
# ---- Step 3: 创建初始 Issue ----
declare -a ISSUE_TITLES=("完善 README 文档" "配置 CI 流水线" "撰写贡献指南 CONTRIBUTING.md")
declare -a ISSUE_BODIES=(
"补充安装、用法、贡献指南等小节,让新贡献者快速上手。"
"确保 push/PR 触发构建与测试,输出测试覆盖率。"
"说明提交流程、代码规范、Issue/PR 模板。"
)
declare -a ISSUE_LABELS=("$ENH_ID" "$ENH_ID" "$GFI_ID")
for i in 0 1 2; do
TITLE="${ISSUE_TITLES[$i]}"
BODY="${ISSUE_BODIES[$i]}"
LBL="${ISSUE_LABELS[$i]}"
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY-RUN] 将执行: issue +create -t \"$TITLE\" --milestone ${MILESTONE_ID} --label ${LBL}"
else
ISSUE_RES=$(gitlink-cli issue +create -t "$TITLE" -b "$BODY" \
--owner "$OWNER" --repo "$REPO" \
--milestone "$MILESTONE_ID" --label "$LBL" --format json 2>&1) \
|| { echo "[WARN] 创建 Issue \"$TITLE\" 失败: $ISSUE_RES"; continue; }
echo "[INFO] Issue 已创建: $TITLE"
fi
done
echo ""
echo "[========================================]"
echo "[ Phase 3 完成 ]"
echo "[ 数据保存至: $OUTPUT_DIR/ ]"
echo "[========================================]"

View File

@ -1,61 +0,0 @@
#!/bin/bash
# ================================================================
# 项目一键初始化 — 全流程串联脚本
# 功能:依次执行 解析建仓 → 骨架生成 → Issue/里程碑
# 使用bash project-bootstrap-full.sh <owner> <repo>
# 环境变量:
# PROJECT_DESC 项目自然语言描述(必填,影响 spec 解析)
# DRY_RUN true|false (默认 true)
# ================================================================
set -e
# 自动检测并使用本地编译的 gitlink-clifull 脚本统一检测一次)
source "$(cd "$(dirname "$0")" && pwd)/../../gitlink-shared/scripts/detect-cli.sh"
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
PROJECT_DESC=${PROJECT_DESC:-"一个用 Go 编写的 GitLink 命令行工具MIT 许可证,公开仓库。"}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "============================================"
echo " 项目一键初始化"
echo " Target: $OWNER/$REPO"
echo " PROJECT_DESC: $PROJECT_DESC"
echo " DRY_RUN: $DRY_RUN"
echo " 开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================"
echo ""
# Phase 1
echo "▸ Phase 1/3: 解析需求 + 创建仓库"
bash "$SCRIPT_DIR/01-parse-and-create-repo.sh" "$OWNER" "$REPO"
echo ""
# Phase 2
echo "▸ Phase 2/3: 生成项目骨架文件"
bash "$SCRIPT_DIR/02-generate-skeleton.sh" "$OWNER" "$REPO"
echo ""
# Phase 3
echo "▸ Phase 3/3: 创建初始 Issue 和里程碑"
bash "$SCRIPT_DIR/03-create-issues-milestones.sh" "$OWNER" "$REPO"
echo ""
# 生成 HTML 可视化报告
echo "▸ 生成 HTML 可视化报告..."
SHARED_SCRIPT="$SCRIPT_DIR/../../gitlink-shared/scripts/md-to-html.js"
if [ -f "$OUTPUT_DIR/init-report.md" ]; then
node "$SHARED_SCRIPT" "$OUTPUT_DIR/init-report.md" 2>/dev/null || true
fi
echo ""
echo "============================================"
echo " 全流程完成"
echo " 结束时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo " 📄 Markdown: $OUTPUT_DIR/init-report.md"
echo " 🗂 骨架: $OUTPUT_DIR/skeleton/"
echo " 🌐 HTML: 已生成"
echo "============================================"

View File

@ -1,271 +0,0 @@
const fs = require('fs');
const path = require('path');
const dir = process.argv[2] || '_output';
const specPath = path.join(dir, 'project-spec.json');
if (!fs.existsSync(specPath)) {
console.error('[ERROR] 未找到 project-spec.json: ' + specPath);
process.exit(1);
}
const spec = JSON.parse(fs.readFileSync(specPath, 'utf8'));
const NAME = spec.name || 'my-project';
const DESC = spec.description || '';
const LANG = (spec.language || 'go').toLowerCase();
const LIC = (spec.license || 'MIT').toUpperCase();
const YEAR = new Date().getFullYear();
const skeletonDir = path.join(dir, 'skeleton');
fs.mkdirSync(path.join(skeletonDir, '.devops'), { recursive: true });
// ==== README.md ====
const readme = `# ${NAME}
> ${DESC}
## 简介
${DESC}本仓库由 \`gitlink-project-bootstrap\` 自动初始化,开箱即用。
## 安装
请根据你的主语言${LANG}选择对应安装方式
\`\`\`bash
# 示例克隆仓库
git clone https://gitlink.org.cn/<owner>/${NAME}.git
cd ${NAME}
\`\`\`
## 用法
\`\`\`bash
# TODO: 在此补充构建 / 运行命令
\`\`\`
## 贡献指南
欢迎提交 Issue Pull Request提交流程请参考 [CONTRIBUTING.md](./CONTRIBUTING.md)待补
## 许可证
本项目基于 ${LIC} 许可证开源详见 [LICENSE](./LICENSE)
---
* gitlink-project-bootstrap 自动生成于 ${YEAR}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')}*
`;
// ==== LICENSE ====
let licenseText = '';
if (LIC.startsWith('APACHE')) {
licenseText = `Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright ${YEAR} [project author]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
`;
} else if (LIC.startsWith('GPL')) {
licenseText = `${LIC} License
Copyright (c) ${YEAR} [project author]
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
`;
} else {
// MIT (default)
licenseText = `MIT License
Copyright (c) ${YEAR} [project author]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
`;
}
// ==== .gitignore ====
let gitignore = '';
if (LANG === 'go') {
gitignore = `# Go
bin/
*.exe
*.exe~
*.dll
*.so
*.dylib
*.test
*.out
vendor/
go.sum
# IDE
.idea/
.vscode/
*.swp
`;
} else if (LANG === 'node') {
gitignore = `# Node
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
dist/
build/
.env
.nyc_output/
coverage/
# IDE
.idea/
.vscode/
*.swp
`;
} else if (LANG === 'python') {
gitignore = `# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
.venv/
*.egg-info/
.pytest_cache/
dist/
build/
# IDE
.idea/
.vscode/
*.swp
`;
} else {
gitignore = `# 通用
*.log
*.tmp
.idea/
.vscode/
.DS_Store
`;
}
// ==== CI yaml (最小可用 GitLink 构建流水线) ====
const ciYaml = `version: 2
name: ${NAME} 构建流水线
description: "${NAME} 自动构建与测试"
trigger:
webhook: gitlink@1.0.0
event:
- ref: push
ruleset-operator: AND
global:
concurrent: 1
workflow:
- ref: start
name: 开始
task: start
- ref: end
name: 结束
task: end
needs:
- start
`;
// ==== 写盘 ====
const produced = [];
fs.writeFileSync(path.join(skeletonDir, 'README.md'), readme, 'utf8'); produced.push('README.md');
fs.writeFileSync(path.join(skeletonDir, 'LICENSE'), licenseText, 'utf8'); produced.push('LICENSE');
fs.writeFileSync(path.join(skeletonDir, '.gitignore'), gitignore, 'utf8'); produced.push('.gitignore');
fs.writeFileSync(path.join(skeletonDir, '.devops', '构建流水线.yml'), ciYaml, 'utf8'); produced.push('.devops/构建流水线.yml');
// ==== init-report.md ====
const completionScore = 9; // 骨架完整:仓库(spec)/README/LICENSE/.gitignore/CI 已就绪Issue/里程碑由 Phase 3 补
const now = new Date();
const dateStr = now.toISOString().slice(0, 10);
const timeStr = now.toISOString().slice(0, 19).replace('T', ' ');
const report = `# 🚀 项目初始化报告
**项目** ${spec.owner || '<owner>'}/${NAME}
**生成日期** ${dateStr}
**主语言** ${LANG}
**许可证** ${LIC}
**综合评分** ${completionScore}/10 🟢 良好
## 本次初始化产物
| 类别 | 产物 | 状态 |
|------|------|------|
| 仓库规格 | project-spec.json | 已生成 |
| 项目说明 | README.md | 已生成 |
| 许可证 | LICENSE (${LIC}) | 已生成 \`[year] [project author]\` 占位,请替换) |
| 忽略规则 | .gitignore (${LANG}) | 已生成 |
| CI 配置 | .devops/构建流水线.yml | 已生成 |
| 里程碑 | v0.1.0 | Phase 3 创建 |
| 起始标签 | good-first-issue / enhancement / bug | Phase 3 创建 |
| 初始 Issue | 完善 README / 配置 CI / 贡献指南 | Phase 3 创建 |
## 待人工确认事项
1. **LICENSE 占位** \`${licenseText.split('\n')[0].includes('Copyright') ? licenseText.split('\n')[0] : 'Copyright (c) ' + YEAR + ' [project author]'}\` 中的 \`[project author]\` 替换为真实版权人
2. **README 用法**"用法"小节补充实际构建/运行命令
3. **CI 触发**根据团队约定调整 \`.devops/构建流水线.yml\` 的 trigger 与构建步骤
4. **仓库可见性**当前为 ${spec.private ? '私有' : '公开'}确认无误
## 推送到仓库
\`\`\`bash
# 优先 file +batch单次 commit
gitlink-cli file +batch --files '<JSON>' --message "chore: 初始化项目骨架" --branch master
# 或逐个 file +create
\`\`\`
---
*数据采集时间${timeStr}*
*AI 生成建议人工复核*
`;
fs.writeFileSync(path.join(dir, 'init-report.md'), report, 'utf8');
console.log('[skeleton-gen] 已生成产物:');
produced.forEach(f => console.log(' - ' + f));
console.log('[skeleton-gen] init-report.md 已生成');

View File

@ -1,7 +1,7 @@
---
name: gitlink-project-health
version: 2.0.0
description: "项目健康度报告:统计 Issue 响应时间、PR 合并效率、贡献者活跃度,生成带评分和趋势分析的项目健康度报告。"
version: 1.0.0
description: "项目健康度报告:统计 Issue 响应时间、PR 合并效率、贡献者活跃度,生成项目健康度分析报告。当用户需要了解项目整体运行状况时触发。"
metadata:
requires:
bins: ["gitlink-cli"]
@ -14,257 +14,123 @@ metadata:
## 说明
本 Skill 组合多个 gitlink-cli 命令,从不同维度采集项目数据,然后进行**量化分析**,生成带评分和趋势判断的健康度报告。
本 Skill 组合多个 gitlink-cli 命令,从不同维度采集项目数据,生成结构化的项目健康度报告。
**不仅仅是展示数据,而是对数据进行分析:**
- 计算 Issue 平均响应时间、关闭率、积压趋势
- 计算 PR 平均合并时间、合并率、堆积趋势
- 分析贡献者活跃度变化
- 给出综合评分和改进建议
## 数据来源
## 数据采集与分析
| Shortcut | 采集的数据 |
|----------|-----------|
| `issue +list` | Issue 总数、打开/关闭数量、平均响应时间 |
| `pr +list` | PR 总数、打开/合并/关闭数量、平均合并时间 |
| `repo +info` | 仓库基本信息、fork 数、watch 数 |
| `commit +list` | 近期提交频率、活跃开发者数 |
| `label +list` | 标签使用情况 |
| `milestone +list` | 里程碑完成进度 |
### 1. Issue 健康度分析
## 报告维度
### 1. Issue 健康度
```bash
# 采集数据
# 所有 Issue 统计
gitlink-cli issue +list --owner myuser --repo myrepo --state all --format json
# 已关闭的 Issue用于统计平均解决时间
gitlink-cli issue +list --owner myuser --repo myrepo --state closed --limit 30
# 待处理的 Issue
gitlink-cli issue +list --owner myuser --repo myrepo --state open
gitlink-cli issue +list --owner myuser --repo myrepo --state closed --limit 50
```
**分析逻辑:**
```
总 Issue 数 = open_count + closed_count
关闭率 = closed_count / total × 100%
Issue 积压趋势:
- 近 30 天新增 - 近 30 天关闭 = 净变化
- 净变化 > 5 → 积压增加,标记 🔴
- 净变化 < -2 积压在减少标记 🟢
- 其他 → 稳定,标记 🟡
平均响应时间 = 计算 closed 列表中 created_at 到 closed_at 的平均天数
- < 2 响应及时 🟢
- 2-7 天 → 正常 🟡
- > 7 天 → 响应偏慢 🔴
```
**评分规则:**
- 关闭率 > 80% 且平均响应 < 3 10/10
- 关闭率 > 50% → 7/10
- 关闭率 > 30% → 5/10
- 关闭率 < 30% 3/10
### 2. PR 健康度分析
### 2. PR 健康度
```bash
# 采集数据
# 所有 PR 统计
gitlink-cli pr +list --owner myuser --repo myrepo --state all --format json
# 待合并的 PR
gitlink-cli pr +list --owner myuser --repo myrepo --state open
gitlink-cli pr +list --owner myuser --repo myrepo --state merged --limit 50
# 已合并的 PR统计平均合并时间
gitlink-cli pr +list --owner myuser --repo myrepo --state merged --limit 30
```
**分析逻辑:**
```
总 PR 数 = open_count + merged_count + closed_count
合并率 = merged_count / total × 100%
PR 合并效率:
- 分析 merged 列表中 created_at 到 merged_at 的平均天数
- < 3 合并迅速 🟢
- 3-7 天 → 正常 🟡
- > 7 天 → 合并缓慢 🔴
堆积 PR超过 7 天未合并):
- 计算 open 列表中超过 7 天的 PR 数量
- 占 open 总数 < 20% 🟢
- 占 open 总数 20-50% → 🟡
- 占 open 总数 > 50% → 🔴
```
### 3. 贡献者活跃度分析
### 3. 仓库基本信息
```bash
# 采集数据
gitlink-cli commit +list --owner myuser --repo myrepo --limit 50
# 仓库概况
gitlink-cli repo +info --owner myuser --repo myrepo --format json
```
**分析逻辑:**
```
活跃贡献者 = 近 50 次提交中 unique author 数量
活跃度等级:
- ≥ 5 人 → 团队协作活跃 🟢
- 2-4 人 → 少量贡献者 🟡
- 1 人 → 单人维护 🔴
提交频率 = 近 50 次提交的时间跨度 / 50
- 每天都有提交 → 非常活跃 🟢
- 每周 2-3 次 → 正常活跃 🟡
- 每周 < 1 不活跃 🔴
新贡献者比例 = 首次贡献者数量 / 总贡献者数 × 100%
- > 20% → 社区有新鲜血液 🟢
- 5-20% → 有少量新人 🟡
- < 5% 缺少新人 🔴
```
### 4. 里程碑进度分析
### 4. 里程碑进度
```bash
# 采集数据
# 查看里程碑
gitlink-cli milestone +list --owner myuser --repo myrepo
```
**分析逻辑:**
### 5. 提交活跃度
```
里程碑完成度 = 计算每个 milestone 中 closed issues / total issues
逾期风险 = 当前日期超过 due_date 但未关闭
```bash
# 最近提交
gitlink-cli commit +list --owner myuser --repo myrepo --limit 20
```
## 综合评分计算
## 报告模板
```
综合得分 = Issue得分 × 30% + PR得分 × 30% + 活跃度得分 × 25% + 里程碑得分 × 15%
评分区间:
9-10 分 → 🟢 优秀:项目健康,保持现状
7-8 分 → 🟢 良好:个别方面需关注
5-6 分 → 🟡 一般:需要改进
3-4 分 → 🔴 堪忧:需重点治理
0-2 分 → 🔴 危险:项目急需干预
```
## 报告输出规范
生成的健康度报告必须严格按以下**固定七个模块**的顺序输出,不得增减或调序:
| 序号 | 模块标题 | 格式要求 |
|:----:|----------|----------|
| 一 | 基本信息 | 两列表格(指标 / 数据) |
| 二 | Issue 状况评分X/10 🟢🟡🔴) | 三列表格(指标 / 数据 / 状态)+ 分析行 |
| 三 | PR 状况评分X/10 🟢🟡🔴) | 三列表格(指标 / 数据 / 状态)+ 分析行 |
| 四 | 贡献者活跃度评分X/10 🟢🟡🔴) | 三列表格(指标 / 数据 / 状态)+ 分析行 |
| 五 | 里程碑进度 | 四列表格(里程碑 / 到期日 / 完成度 / 状态) |
| 六 | 综合评分计算 | 四列加权表格 + 评分区间说明 |
| 七 | 改进建议 | 带优先级编号列表 |
**注意事项:**
- 每个模块之间用 `---` 分隔
- 所有指标必须有**量化数据**(百分比、天数、人数),不能只罗列原始数字
- 评分必须有明确的**计算依据**,不能凭感觉打分
- 每个维度都需给出**分析行**和改进方向
- 使用 `🟢🟡🔴` 颜色标识状态
## 完整报告示例
收集完数据后,按以下模板生成报告:
```markdown
# 📊 项目健康度报告 — myuser/myrepo
# 项目健康度报告
**报告日期:** 2026-06-17
**综合评分:** 7.5/10 🟢 良好
## 基本信息
- 项目:{repo_name}
- 所有者:{owner}
- Stars{stars} | Forks{forks}
---
## Issue 状况
- 总 Issue 数:{total_issues}
- 打开:{open_issues}(占比 {open_percent}%
- 已关闭:{closed_issues}(占比 {closed_percent}%
## 一、基本信息
## PR 状况
- 总 PR 数:{total_prs}
- 打开:{open_prs}
- 已合并:{merged_prs}
| 指标 | 数据 |
|------|------|
| 项目 | myuser/myrepo |
| 默认分支 | master |
| Issue 总数 | 47 |
| PR 总数 | 23 |
| 近 30 天活跃贡献者 | 3 人 |
## 活跃度
- 近期提交:{recent_commits} 次
- 活跃开发者:{active_devs} 人
```
---
## 使用示例
## 二、Issue 状况评分8/10 🟢)
```bash
# 完整报告生成流程
| 指标 | 数据 | 状态 |
|------|------|------|
| 总 Issue 数 | 47 | — |
| 打开中 | 8 | — |
| 已关闭 | 39 | — |
| 关闭率 | 83% | 🟢 优秀 |
| 平均响应时间 | 1.8 天 | 🟢 响应及时 |
| 近 30 天净变化 | +2 | 🟡 略增 |
# 步骤1获取仓库信息
gitlink-cli repo +info --owner myuser --repo myrepo --format json
**分析:** Issue 关闭率很高,响应也及时。近 30 天新增略多于关闭,建议关注积压趋势。
# 步骤2获取 Issue 统计
gitlink-cli issue +list --owner myuser --repo myrepo --state open
gitlink-cli issue +list --owner myuser --repo myrepo --state all --format json
---
# 步骤3获取 PR 统计
gitlink-cli pr +list --owner myuser --repo myrepo --state open
gitlink-cli pr +list --owner myuser --repo myrepo --state merged --limit 20
## 三、PR 状况评分7/10 🟢)
# 步骤4获取提交活跃度
gitlink-cli commit +list --owner myuser --repo myrepo --limit 30
| 指标 | 数据 | 状态 |
|------|------|------|
| 总 PR 数 | 23 | — |
| 打开中 | 3 | — |
| 已合并 | 18 | — |
| 合并率 | 78% | 🟢 良好 |
| 平均合并时间 | 4.2 天 | 🟡 正常 |
| 堆积 PR>7 天) | 1 个 | 🟡 占 33% |
# 步骤5获取里程碑进度
gitlink-cli milestone +list --owner myuser --repo myrepo
**分析:** 合并率良好,但有一个 PR 超过 7 天未处理,建议关注。
---
## 四、贡献者活跃度评分7/10 🟢)
| 指标 | 数据 | 状态 |
|------|------|------|
| 近 50 次提交贡献者 | 3 人 | 🟡 少量贡献者 |
| 提交频率 | 每周 3-4 次 | 🟡 正常 |
| 新贡献者比例 | 0% | 🔴 缺少新人 |
**分析:** 项目目前由少数核心成员维护,建议标记一些 good-first-issue 吸引新贡献者。
---
## 五、里程碑进度
| 里程碑 | 到期日 | 完成度 | 状态 |
|--------|--------|--------|------|
| v1.3.0 | 2026-06-30 | 60% | 🟢 进行中 |
| v2.0.0 | 2026-08-15 | 20% | 🟡 初期 |
---
## 六、综合评分计算
| 维度 | 得分 | 权重 | 加权得分 |
|------|:----:|:----:|:--------:|
| Issue 健康度 | 8/10 | × 30% | 2.4 |
| PR 健康度 | 7/10 | × 30% | 2.1 |
| 贡献者活跃度 | 7/10 | × 25% | 1.75 |
| 里程碑进度 | 6/10 | × 15% | 0.9 |
| **综合得分** | | | **7.15/10 → 7.2 🟢 良好** |
**评分区间:**
- 9-10 分 → 🟢 优秀:项目健康,保持现状
- 7-8 分 → 🟢 良好:个别方面需关注
- 5-6 分 → 🟡 一般:需要改进
- 3-4 分 → 🔴 堪忧:需重点治理
- 0-2 分 → 🔴 危险:项目急需干预
---
## 七、改进建议
1. **🔴 高优先级** — 添加 good-first-issue 标签吸引新贡献者
2. **🟡 中优先级** — 关注堆积 PR设置自动提醒
3. **🟢 低优先级** — 定期清理积压 Issue
---
# 步骤6汇总数据生成报告
```
## 注意事项
- 每个指标都要计算**量化数据**(百分比、天数、人数),不能只罗列原始数字
- 评分需要有明确的**计算规则**(见各维度分析逻辑),不能凭感觉打分
- 每个维度都要给出**改进建议**,不能只报告现状
- 使用 `🟢🟡🔴` 颜色标识状态,一目了然
- 使用 `--format json` 获取结构化数据,便于 Agent 解析。
- 指定 `--limit` 控制数据量,避免输出过大。
- 不同项目的数据量级不同,可根据实际情况调整采样数量。
- 报告中的"健康状况"建议使用颜色标识(绿色=健康,黄色=一般,红色=需关注)。

View File

@ -1,6 +1,6 @@
# 项目健康度报告生成工作流示例(含数据分析)
# 项目健康度报告生成工作流示例
**场景**:项目维护者需要生成一份带评分和改进建议的健康度报告
**场景**:项目维护者需要生成一份项目健康度周报,了解 Issue 处理情况、PR 合并效率和整体活跃度
## 前置条件
@ -8,139 +8,85 @@
## 工作流步骤
### Step 1采集原始数据
### Step 1获取项目基本信息
```bash
gitlink-cli repo +info --owner z2_cc --repo gitlink-cli --format json
```
### Step 2统计 Issue 数据
```bash
# 所有 Issue
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state all --format json
# 打开的 Issue
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state open
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state closed --limit 50
# 已关闭的 Issue最近 30 条)
gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state closed --limit 30
```
### Step 3统计 PR 数据
```bash
# 所有 PR
gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state all --format json
# 待合并的 PR
gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state open
# 已合并的 PR
gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state merged --limit 30
gitlink-cli commit +list --owner z2_cc --repo gitlink-cli --limit 50
```
### Step 4查看近期提交活跃度
```bash
gitlink-cli commit +list --owner z2_cc --repo gitlink-cli --limit 20
```
### Step 5查看里程碑进度
```bash
gitlink-cli milestone +list --owner z2_cc --repo gitlink-cli
```
### Step 2AI 分析数据
### Step 6生成报告
对采集到的 JSON 数据进行以下分析:
```
1. Issue 分析:
- 从 all 数据中统计 open 和 closed 数量
- 从 closed 数据中计算平均响应时间created_at → closed_at
- 判断关闭率是否 > 80%
2. PR 分析:
- 从 all 数据中统计 open/merged/closed 数量
- 从 merged 数据中计算平均合并时间
- 判断是否有 PR 长期未合并
3. 活跃度分析:
- 从 commit 数据中统计 unique author 数量
- 根据提交时间判断频率
```
### Step 3生成带评分的报告
按 SKILL.md 中定义的分析逻辑计算各维度评分Issue 关闭率/响应时间、PR 合并率/堆积、贡献者活跃度),然后按加权公式计算综合得分:
```
综合得分 = Issue得分 × 30% + PR得分 × 30% + 活跃度得分 × 25% + 里程碑得分 × 15%
```
汇总以上数据,生成结构化报告:
```markdown
# 📊 项目健康度报告 — z2_cc/gitlink-cli
## 项目健康度周报
**报告日期:** 2026-06-25
**综合评分:** 7.2/10 🟢 良好
### Issue 状况
- 总 Issue 数12打开 3 / 关闭 9
- 本周新增2
- 本周解决3
### PR 状况
- 总 PR 数5打开 1 / 已合并 4
- 本周新增1
- 本周合并2
### 活跃度
- 近 20 次提交涉及3 位贡献者
- 最近提交时间2 小时前
### 里程碑
- 进行中v2.0(完成 60%
🟢 总体评价:项目健康
```
---
## 一、基本信息
| 指标 | 数据 |
|------|------|
| 项目 | z2_cc/gitlink-cli |
| 默认分支 | master |
| Issue 总数 | 16 |
| PR 总数 | 5 |
| 近 30 天活跃贡献者 | 1 人 |
---
## 二、Issue 状况评分8/10 🟢)
| 指标 | 数据 | 状态 |
|------|------|------|
| 总 Issue 数 | 16 | — |
| 打开中 | 2 | — |
| 已关闭 | 14 | — |
| 关闭率 | 87.5% | 🟢 优秀 |
| 平均响应时间 | < 2 | 🟢 响应及时 |
**分析:** 关闭率优秀,积压很少,响应及时。
---
## 三、PR 状况评分7/10 🟢)
| 指标 | 数据 | 状态 |
|------|------|------|
| 总 PR 数 | 5 | — |
| 打开中 | 1 | — |
| 已合并 | 4 | — |
| 合并率 | 80% | 🟢 良好 |
| 平均合并时间 | 3-7 天 | 🟡 正常 |
**分析:** 合并率良好,处理效率正常。
---
## 四、贡献者活跃度评分7/10 🟢)
| 指标 | 数据 | 状态 |
|------|------|------|
| 近 50 次提交贡献者 | 1 人 | 🔴 单人维护 |
| 提交频率 | 每天都有提交 | 🟢 非常活跃 |
| 新贡献者比例 | 0% | 🔴 缺少新人 |
**分析:** 目前单人维护,提交活跃但缺乏新贡献者,建议标记一些 good-first-issue 吸引新人。
---
## 五、里程碑进度
| 里程碑 | 到期日 | 完成度 | 状态 |
|--------|--------|--------|------|
| (无活跃里程碑) | — | — | 🟡 暂无数据 |
---
## 六、综合评分计算
| 维度 | 得分 | 权重 | 加权得分 |
|------|:----:|:----:|:--------:|
| Issue 健康度 | 8/10 | × 30% | 2.4 |
| PR 健康度 | 7/10 | × 30% | 2.1 |
| 贡献者活跃度 | 7/10 | × 25% | 1.75 |
| 里程碑进度 | 6/10 | × 15% | 0.9 |
| **综合得分** | | | **7.15/10 → 7.2 🟢 良好** |
**评分区间:**
- 9-10 分 → 🟢 优秀:项目健康,保持现状
- 7-8 分 → 🟢 良好:个别方面需关注
- 5-6 分 → 🟡 一般:需要改进
- 3-4 分 → 🔴 堪忧:需重点治理
- 0-2 分 → 🔴 危险:项目急需干预
---
## 七、改进建议
1. **🔴 高优先级** — 添加 good-first-issue 标签吸引新贡献者
2. 🟡 关注堆积 PR及时 review
3. 🟢 考虑添加 CI/CD 自动化
---
## 完整命令速览
```bash
gitlink-cli repo +info
gitlink-cli issue +list --state all --format json
gitlink-cli pr +list --state all --format json
gitlink-cli commit +list --limit 20
gitlink-cli milestone +list
```

View File

@ -1,187 +0,0 @@
---
name: gitlink-quality-gate
version: 1.0.0
description: "代码质量看门人PR 提交 → 深度审查 → CI 检查 → 质量评分 → 自动合并/反馈建议。串联 pr-deep-review 与 CI 检查,实现代码质量自动化门禁。"
metadata:
requires:
bins: ["gitlink-cli", "jq"]
cliHelp: "gitlink-cli pr --help / gitlink-cli ci --help"
---
# gitlink-quality-gate代码质量看门人
> **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解认证、全局参数和 API 注意事项。
>
> **CRITICAL — 所有 GitLink 操作必须使用 `gitlink-cli`,禁止使用 `gh`GitHub CLI操作 GitLink 资源。**
## 说明
本 Skill 实现 PR 的自动化质量门禁,串联 **深度代码审查****CI 状态检查**,对每个 PR 进行量化评分,根据评分结果决定是否自动合并。
### 质量门禁流程
```mermaid
flowchart LR
A[新 PR 提交] --> B[Phase 1: PR 采集]
B --> C[Phase 2: 深度审查]
C --> D[Phase 3: CI 检查]
D --> E[Phase 4: 门禁决策]
E --> F{评分 ≥ 70 且 CI 通过?}
F -->|是| G[自动合并]
F -->|否| H[反馈修改建议]
```
### 质量评分模型
```
质量总分 = CodeReview 评分 × 40% + CI 状态 × 30% + 设计一致性 × 30%
评分细则:
- CodeReview 评分0-100根据 Critical/Warning/Suggestion 数量综合计算
- 每个 Critical -20 分,每个 Warning -10 分,每个 Suggestion -3 分
- 起始 100 分,扣减后为最终得分
- CI 状态0 或 100全部通过 = 100有失败 = 0
- 设计一致性0-100PR 描述与代码变更的匹配度AI 评估
门槛:
- ≥ 70 分 + CI 通过 → 自动合并(需最终确认)
- < 70 CI 失败 阻塞并给出具体修改建议
```
---
## Phase 1PR 采集
**参考 Skill** [`../gitlink-pr/SKILL.md`](../gitlink-pr/SKILL.md)
```bash
# 1. 列出所有打开的 PR
gitlink-cli pr +list --owner <owner> --repo <repo> --state open --format json
# 2. 筛选出真实 PRpull_request_status=0
# 3. 按创建时间排序,优先处理最早的 PR
```
---
## Phase 2深度审查
**参考 Skill** [`../gitlink-pr-deep-review/SKILL.md`](../gitlink-pr-deep-review/SKILL.md)
```bash
# 1. 获取 PR 详情
gitlink-cli pr +view --id <pr_id> --format json
# 2. 获取变更文件列表
gitlink-cli pr +files --id <pr_id> --format json
# 3. 获取补丁版本差异
gitlink-cli pr +versions --id <pr_id> --format json
gitlink-cli pr +version-diff --id <pr_id> --version-id <version_id> --format json
# 4. 查看已有评审(避免重复)
gitlink-cli pr +reviews --id <pr_id> --format json
```
### AI 审查维度
| 维度 | 检查项 | 权重 |
|------|--------|------|
| 代码质量 | 命名规范、错误处理、空指针、资源泄漏、并发安全 | 40% |
| 功能正确性 | 逻辑正确性、边界条件、异常路径覆盖 | 30% |
| 代码风格 | 与项目现有风格一致性、格式化 | 15% |
| 测试覆盖 | 是否包含测试、测试覆盖率、测试质量 | 15% |
---
## Phase 3CI 状态检查
**参考 Skill** [`../gitlink-ci/SKILL.md`](../gitlink-ci/SKILL.md)
```bash
# 1. 获取 CI 构建列表
gitlink-cli ci +builds --owner <owner> --repo <repo> --format json
# 2. 获取 CI 运行记录
gitlink-cli ci +runs --owner <owner> --repo <repo> --format json
# 3. 筛选与 PR 分支相关的构建
# 4. 判断 CI 是否全部通过
```
### CI 状态判定
| CI 状态 | 评分 | 说明 |
|---------|------|------|
| 全部通过 | 100 | 所有构建步骤成功 |
| 部分通过 | 50 | 部分步骤成功(需人工判断) |
| 有失败 | 0 | 存在失败步骤,阻塞合并 |
---
## Phase 4门禁决策
### 决策逻辑
```
输入:
- code_review_score (0-100)
- ci_passing (true/false)
- design_consistency (0-100)
计算:
quality_score = code_review_score × 0.4
+ (ci_passing ? 100 : 0) × 0.3
+ design_consistency × 0.3
决策:
if quality_score >= 70 AND ci_passing == true:
→ 通过门禁,可自动合并
else:
→ 阻塞门禁,生成修改建议
```
### 命令示例
```bash
# 通过门禁 — 提交评审 + 合并
gitlink-cli pr +review --id <pr_id> --status approved --content "<review_summary>"
gitlink-cli pr +merge --id <pr_id> --do squash
# 阻塞门禁 — 提交评审含修改建议
gitlink-cli pr +review --id <pr_id> --status common --content "<fix_suggestions>"
```
---
## 可复现脚本
本 Skill 提供可直接执行的 Bash 脚本,位于 `scripts/` 目录:
| 脚本 | 功能 | 使用方式 |
|------|------|----------|
| `01-collect-prs.sh` | Phase 1 PR 采集 | `bash 01-collect-prs.sh <owner> <repo>` |
| `02-deep-review.sh` | Phase 2 深度审查 | `bash 02-deep-review.sh <owner> <repo> <pr_id>` |
| `03-ci-check.sh` | Phase 3 CI 检查 | `bash 03-ci-check.sh <owner> <repo> <pr_id>` |
| `04-quality-gate-decision.sh` | Phase 4 门禁决策 | `bash 04-quality-gate-decision.sh <owner> <repo> <pr_id>` |
| `quality-gate-full.sh` | 全流程串联(遍历所有 PR | `bash quality-gate-full.sh <owner> <repo>` |
**所有脚本默认 dry-run 模式**,确认后切换:
```bash
# Dry-run默认安全
DRY_RUN=true bash scripts/quality-gate-full.sh z2_cc gitlink-cli
# 实际执行
DRY_RUN=false bash scripts/quality-gate-full.sh z2_cc gitlink-cli
```
---
## 注意事项
1. **dry-run 优先**`pr +merge` 和 `pr +review` 默认不实际执行
2. **避免重复评审**:检查 `pr +reviews` 输出,跳过已评审的 PR
3. **CI 超时**:如果 CI 仍在运行中,标记为 pending 并等待下次检查
4. **关键 PR 例外**:涉及安全修复、架构变更的 PR 建议跳过自动合并
5. **合并方式**:默认使用 squash 合并,保持提交历史整洁

View File

@ -1,182 +0,0 @@
# 代码质量看门人工作流 — 端到端示例
**场景**:项目维护者希望自动化 PR 审查流程:新 PR 自动触发代码审查、CI 检查,质量达标后自动合并。
## 前置条件
- `gitlink-cli` 已安装并登录
- 目标仓库已确认(示例使用 `z2_cc/gitlink-cli`
- 本地已 clone 目标仓库
## 工作流步骤
### Step 1采集待审 PR
```bash
# 1.1 获取所有打开的 PR
gitlink-cli pr +list --owner z2_cc --repo gitlink-cli --state open --format json
```
**输出示例:**
```json
{
"ok": true,
"data": [
{"id": 5, "title": "feat: 添加 Wiki 管理功能", "pull_request_status": 0, "created_at": "2026-06-20"},
{"id": 6, "title": "fix: 修复 Issue 列表分页", "pull_request_status": 0, "created_at": "2026-06-22"}
]
}
```
### Step 2深度代码审查
对每个 PR 执行深度审查:
```bash
# 2.1 获取 PR 详情
gitlink-cli pr +view --id 5 --format json
# 2.2 获取变更文件
gitlink-cli pr +files --id 5 --format json
# 2.3 获取补丁版本差异
gitlink-cli pr +versions --id 5 --format json
gitlink-cli pr +version-diff --id 5 --version-id <version_id> --format json
# 2.4 检查已有评审(避免重复审查)
gitlink-cli pr +reviews --id 5 --format json
```
**输出示例version-diff**
```json
{
"ok": true,
"data": {
"files": [
{"path": "shortcuts/wiki/wiki.go", "additions": 45, "deletions": 0, "status": "added"},
{"path": "skills/gitlink-wiki/SKILL.md", "additions": 30, "deletions": 0, "status": "added"}
],
"stat": "+75/-0"
}
}
```
**AI 审查结果示例:**
```
CodeReview评分: 85/100
- 代码结构清晰,命名规范 ✅
- 错误处理完善 ✅
- 建议添加更详细的注释 (-3)
- 建议添加单元测试 (-15)
Critical: 0, Warning: 1, Suggestion: 2
```
### Step 3CI 状态检查
```bash
# 3.1 获取 CI 构建列表
gitlink-cli ci +builds --owner z2_cc --repo gitlink-cli --format json
# 3.2 获取 CI 运行记录
gitlink-cli ci +runs --owner z2_cc --repo gitlink-cli --format json
```
**输出示例:**
```json
{
"ok": true,
"data": {
"builds": [
{"id": 101, "branch": "refs/pull/5/head", "status": "success", "commit_sha": "abc123"}
]
}
}
```
### Step 4质量门禁决策
**质量评分计算:**
```
CodeReview评分 = 85 (实际扣分后)
CI 状态 = 100 (全部通过)
设计一致性 = 80 (PR 描述与变更匹配良好)
质量总分 = 85 × 0.4 + 100 × 0.3 + 80 × 0.3
= 34 + 30 + 24
= 88
门槛 ≥ 70 且 CI 通过 → ✅ 通过门禁
```
```bash
# 4.1 dry-run 模式)只输出决策,不实际执行
echo "[DRY-RUN] PR #5 质量评分: 88/100"
echo "[DRY-RUN] CI 状态: 全部通过"
echo "[DRY-RUN] 门禁决策:✅ 通过"
echo "[DRY-RUN] 将执行: pr +review --status approved + pr +merge --do squash"
```
**实际执行DRY_RUN=false**
```bash
# 提交评审通过
gitlink-cli pr +review --id 5 --status approved --content "✅ 代码质量审查通过
评分88/100CodeReview 85 + CI 100 + 设计一致性 80
无 Critical 问题1 个 Warning 已确认无影响。
**建议后续改进:**
- 补充单元测试
- 完善函数注释"
# 自动合并
gitlink-cli pr +merge --id 5 --do squash
```
### Step 5阻塞场景示例
如果质量评分不达标的 PR
```bash
echo "[DRY-RUN] PR #X 质量评分: 45/100"
echo "[DRY-RUN] CI 状态: ❌ 失败"
echo "[DRY-RUN] 门禁决策:❌ 阻塞"
echo "[DRY-RUN] 将执行: pr +review --status common + 修改建议"
# 实际执行
gitlink-cli pr +review --id X --status common --content "❌ 质量门禁未通过
**问题清单:**
1. Critical: 存在空指针风险 (file.go:42)
2. CI 构建失败:单元测试未通过
3. 缺少必要测试覆盖
请修复以上问题后重新提交。"
```
## 完整命令速览
```bash
# 采集 PR
gitlink-cli pr +list --state open --format json
# 深度审查
gitlink-cli pr +view --id <id> --format json
gitlink-cli pr +files --id <id> --format json
gitlink-cli pr +versions --id <id> --format json
gitlink-cli pr +version-diff --id <id> --version-id <v> --format json
# CI 检查
gitlink-cli ci +builds --format json
# 门禁操作
gitlink-cli pr +review --id <id> --status approved --content "<msg>"
gitlink-cli pr +merge --id <id> --do squash
gitlink-cli pr +review --id <id> --status common --content "<fix_suggestions>"
```
## 注意事项
- 自动合并不适用于:安全修复、架构变更、大规模重构
- 建议先对小 PR 启用自动合并,逐步积累信任
- 每次自动合并后记录操作日志,便于回溯

View File

@ -1,53 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 1: PR 采集
# 功能:列出所有待审 PR过滤出真实 PR
# 使用bash 01-collect-prs.sh <owner> <repo>
# ================================================================
set -e
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 1: PR 采集 ]"
echo "[ Target: $OWNER/$REPO ]"
echo "[========================================]"
# 获取所有打开的 PR
echo "[INFO] 获取打开的 PR 列表..."
PRS=$(gitlink-cli pr +list --owner "$OWNER" --repo "$REPO" --state open --format json 2>&1) || {
echo "[ERROR] 获取 PR 列表失败: $PRS"
exit 1
}
echo "$PRS" > "$OUTPUT_DIR/prs-open.json"
# 过滤打开的 PRstatus 可能是数字 0 或字符串 "open"/"opened"
REAL_PRS=$(echo "$PRS" | node -e "
let s='';
process.stdin.on('data',d=>s+=d).on('end',()=>{
const d=JSON.parse(s).data||{};
const items=Array.isArray(d)?d:(d.pulls||d.pull_requests||[]);
const real=items.filter(p=>{
const st=p.pull_request_status||p.status||'';
return st===0||st==='0'||st==='open'||st==='opened';
});
process.stdout.write(JSON.stringify(real));
});
" 2>/dev/null || echo "[]")
echo "$REAL_PRS" > "$OUTPUT_DIR/prs-to-review.json"
TOTAL=$(echo "$REAL_PRS" | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{process.stdout.write(String(JSON.parse(s).length))})" 2>/dev/null || echo "0")
echo "[INFO] 发现 $TOTAL 个待审 PR"
if [ "$TOTAL" -eq 0 ]; then
echo "[INFO] 没有待审 PR"
fi
echo "[========================================]"
echo "[ Phase 1 完成 ]"
echo "[ PR 列表: $OUTPUT_DIR/prs-to-review.json ]"
echo "[========================================]"

View File

@ -1,88 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 2: PR 深度审查
# 功能:采集 PR 详情、文件列表、diff、已有评审
# 使用bash 02-deep-review.sh <owner> <repo> <pr_id>
# ================================================================
set -e
OWNER=${1:?"Usage: $0 <owner> <repo> <pr_id>"}
REPO=${2}
PR_ID=${3:?"Usage: $0 <owner> <repo> <pr_id>"}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 2: PR 深度审查 ]"
echo "[ PR #$PR_ID ($OWNER/$REPO) ]"
echo "[========================================]"
# Step 1: 获取 PR 详情
echo "[INFO] 获取 PR #$PR_ID 详情..."
VIEW_DATA=$(gitlink-cli pr +view --id "$PR_ID" --owner "$OWNER" --repo "$REPO" --format json 2>&1) || {
echo "[ERROR] 获取 PR 详情失败: $VIEW_DATA"
exit 1
}
echo "$VIEW_DATA" > "$OUTPUT_DIR/pr-$PR_ID-view.json"
# Step 2: 获取变更文件列表
echo "[INFO] 获取变更文件列表..."
FILES_DATA=$(gitlink-cli pr +files --id "$PR_ID" --owner "$OWNER" --repo "$REPO" --format json 2>&1) || {
echo "[WARN] 获取文件列表失败: $FILES_DATA"
FILES_DATA='{"data":[]}'
}
echo "$FILES_DATA" > "$OUTPUT_DIR/pr-$PR_ID-files.json"
# Step 3: 获取补丁版本差异
echo "[INFO] 获取补丁版本信息..."
VERSIONS_DATA=$(gitlink-cli pr +versions --id "$PR_ID" --owner "$OWNER" --repo "$REPO" --format json 2>&1) || {
echo "[WARN] 获取版本信息失败: $VERSIONS_DATA"
VERSIONS_DATA='{"data":[]}'
}
echo "$VERSIONS_DATA" > "$OUTPUT_DIR/pr-$PR_ID-versions.json"
# 提取最新 version_id
VERSION_ID=$(echo "$VERSIONS_DATA" | node -e "
let s='';
process.stdin.on('data',d=>s+=d).on('end',()=>{
try {
const d=JSON.parse(s).data||[];
const items=Array.isArray(d)?d:(d.versions||d);
if(items.length>0) process.stdout.write(String(items[0].id));
} catch(e) { process.stdout.write(''); }
});
" 2>/dev/null || echo "")
if [ -n "$VERSION_ID" ]; then
echo "[INFO] 获取补丁差异 (version_id: $VERSION_ID)..."
DIFF_DATA=$(gitlink-cli pr +version-diff --id "$PR_ID" --version-id "$VERSION_ID" --owner "$OWNER" --repo "$REPO" --format json 2>&1) || {
echo "[WARN] 获取 diff 失败: $DIFF_DATA"
}
echo "$DIFF_DATA" > "$OUTPUT_DIR/pr-$PR_ID-diff.json"
fi
# Step 4: 获取已有评审(避免重复)
echo "[INFO] 获取已有评审..."
REVIEWS_DATA=$(gitlink-cli pr +reviews --id "$PR_ID" --owner "$OWNER" --repo "$REPO" --format json 2>&1) || {
echo "[WARN] 获取评审失败: $REVIEWS_DATA"
REVIEWS_DATA='{"data":[]}'
}
echo "$REVIEWS_DATA" > "$OUTPUT_DIR/pr-$PR_ID-reviews.json"
# Step 5: AI 审查分析
echo "[INFO] AI 审查分析中..."
echo "[INFO] 审查维度:"
echo " - 代码质量(命名、错误处理、空指针、资源泄漏、并发安全)"
echo " - 功能正确性(逻辑、边界条件、异常路径)"
echo " - 代码风格(与项目风格一致性)"
echo " - 测试覆盖(是否包含测试、测试质量)"
# AI Agent 在此处读取 JSON 数据,生成审查报告
# 输出CodeReview 评分 (0-100)、Critical/Warning/Suggestion 数量、具体建议
echo ""
echo "[========================================]"
echo "[ Phase 2 完成 ]"
echo "[ PR #$PR_ID 审查数据: $OUTPUT_DIR/ ]"
echo "[========================================]"

View File

@ -1,72 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 3: CI 状态检查
# 功能:检查 PR 关联的 CI 构建状态(尝试多个端点)
# 使用bash 03-ci-check.sh <owner> <repo> <pr_id>
# ================================================================
set -e
OWNER=${1:?"Usage: $0 <owner> <repo> <pr_id>"}
REPO=${2}
PR_ID=${3}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 3: CI 状态检查 ]"
echo "[ PR #$PR_ID ($OWNER/$REPO) ]"
echo "[========================================]"
CI_PASSING="unknown"
CI_DETAIL=""
# 方法1: ci +buildsActions 系统)
echo "[INFO] 查询 CI 运行记录Actions API..."
BUILDS=$(gitlink-cli ci +builds --owner "$OWNER" --repo "$REPO" --format json 2>&1) || BUILDS=""
if echo "$BUILDS" | grep -q '"runs"'; then
echo "$BUILDS" > "$OUTPUT_DIR/ci-builds.json"
CI_PASSING=$(echo "$BUILDS" | node -e "
let s='';
process.stdin.on('data',d=>s+=d).on('end',()=>{
try {
const d=JSON.parse(s).data||{};
const runs=d.runs||[];
if(runs.length===0){process.stdout.write('unknown');return;}
const r=runs.some(x=>x.status==='running'||x.status==='pending');
const ok=runs.some(x=>x.status==='success'||x.status==='completed');
const fail=runs.some(x=>x.status==='fail'||x.status==='error');
process.stdout.write(r?'running':ok&&!fail?'passing':fail?'failing':'unknown');
}catch(e){process.stdout.write('unknown');}
});
" 2>/dev/null || echo "unknown")
CI_DETAIL="Actions API: ${CI_PASSING}"
fi
# 方法2: ci +run-resultsDevOps/建木 系统)
if [ "$CI_PASSING" = "unknown" ]; then
echo "[INFO] 查询 DevOps 流水线状态DevOps API..."
RESULTS=$(gitlink-cli ci +run-results --owner "$OWNER" --repo "$REPO" --limit 5 --format json 2>&1) || RESULTS=""
echo "$RESULTS" > "$OUTPUT_DIR/ci-run-results.json"
fi
# 最终结果
if [ "$CI_PASSING" = "unknown" ]; then
echo "[INFO] 当前无法获取 CI 状态"
echo "[INFO] 原因GitLink 的 Actions API 和 DevOps API 均未返回运行记录"
echo "[INFO] 提示:流水线可能通过 DevOps/建木引擎运行,该引擎的 API 未在 CLI 中完整实现"
CI_DETAIL="CLI 暂不支持查询 DevOps 流水线状态"
fi
# 写入状态文件供 Phase 4 读取
echo "$CI_PASSING" > "$OUTPUT_DIR/ci-status-$PR_ID.txt"
echo "$CI_DETAIL" > "$OUTPUT_DIR/ci-detail-$PR_ID.txt"
echo "[INFO] CI 状态: $CI_PASSING"
echo "[INFO] $CI_DETAIL"
echo ""
echo "[========================================]"
echo "[ Phase 3 完成 ]"
echo "[ CI 状态: $CI_PASSING ]"
echo "[========================================]"

View File

@ -1,72 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 3: 本地 CI 检查
# 功能:在本地验证 PR 的代码能否编译通过
# 使用bash 03-local-ci-check.sh <owner> <repo> <pr_id>
# 无需外部流水线,直接运行 go build 验证
# ================================================================
set -e
OWNER=${1:?"Usage: $0 <owner> <repo> <pr_id>"}
REPO=${2}
PR_ID=${3}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 3: 本地 CI 检查 ]"
echo "[ PR #$PR_ID ($OWNER/$REPO) ]"
echo "[========================================]"
CI_PASSING=false
CI_DETAIL=""
# Step 1: 检查 Go 环境
if ! command -v go &> /dev/null; then
echo "[WARN] 未安装 Go跳过本地编译检查"
CI_DETAIL="未安装 Go跳过"
echo "unknown" > "$OUTPUT_DIR/ci-status-$PR_ID.txt"
echo "$CI_DETAIL" > "$OUTPUT_DIR/ci-detail-$PR_ID.txt"
echo "[INFO] CI 状态: unknownGo 未安装)"
echo ""
echo "[========================================]"
echo "[ Phase 3 完成 ]"
echo "[========================================]"
exit 0
fi
# Step 2: 本地编译验证
echo "[INFO] 运行本地编译验证..."
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
if [ -d "$PROJECT_ROOT" ] && [ -f "$PROJECT_ROOT/go.mod" ]; then
BUILD_OUTPUT=$(cd "$PROJECT_ROOT" && go build -o /dev/null . 2>&1) || {
echo "[WARN] ❌ 编译失败"
echo "$BUILD_OUTPUT"
CI_DETAIL="编译失败: $(echo "$BUILD_OUTPUT" | head -1)"
echo "failing" > "$OUTPUT_DIR/ci-status-$PR_ID.txt"
echo "$CI_DETAIL" > "$OUTPUT_DIR/ci-detail-$PR_ID.txt"
echo "[INFO] CI 状态: failing"
echo ""
echo "[========================================]"
echo "[ Phase 3 完成 ]"
echo "[========================================]"
exit 0
}
echo "[INFO] ✅ 编译成功"
CI_PASSING=true
CI_DETAIL="本地编译验证通过"
echo "passing" > "$OUTPUT_DIR/ci-status-$PR_ID.txt"
else
echo "[WARN] 未找到 Go 项目,跳过本地编译检查"
CI_DETAIL="未找到 Go 项目"
echo "unknown" > "$OUTPUT_DIR/ci-status-$PR_ID.txt"
fi
echo "$CI_DETAIL" > "$OUTPUT_DIR/ci-detail-$PR_ID.txt"
echo "[INFO] CI 状态: $(cat "$OUTPUT_DIR/ci-status-$PR_ID.txt" 2>/dev/null || echo unknown)"
echo ""
echo "[========================================]"
echo "[ Phase 3 完成 ]"
echo "[========================================]"

View File

@ -1,104 +0,0 @@
#!/bin/bash
# ================================================================
# Phase 3: 质量门禁决策
# 功能:计算质量评分 → 门禁判定 → 自动合并或反馈建议
# 使用bash 04-quality-gate-decision.sh <owner> <repo> <pr_id>
# 环境变量DRY_RUN=true|false (默认 true)
# ================================================================
set -e
OWNER=${1:?"Usage: $0 <owner> <repo> <pr_id>"}
REPO=${2}
PR_ID=${3}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "[========================================]"
echo "[ Phase 3: 质量门禁决策 ]"
echo "[ PR #$PR_ID ($OWNER/$REPO) ]"
echo "[ DRY_RUN: $DRY_RUN ]"
echo "[========================================]"
# ---- 质量评分模型 ----
# 评分 = CodeReview_Score × 40% + CI_Status × 30% + Design_Score × 30%
# CI 来自本地编译验证03-local-ci-check.sh无需外部流水线
echo "[INFO] 评分计算中..."
echo " 评分模型: 总分 = CodeReview×40% + CI×30% + 设计一致性×30%"
echo " CI 来源: 本地编译验证(无需外部流水线)"
echo " 门槛: ≥ 70 分且 CI 通过"
echo ""
# 读取本地 CI 检查状态
CI_FILE="$OUTPUT_DIR/ci-status-$PR_ID.txt"
CI_STATUS_TEXT="unknown"
if [ -f "$CI_FILE" ]; then
CI_STATUS_TEXT=$(cat "$CI_FILE")
fi
# 占位评分AI 在实际运行时根据 Phase 2 数据计算)
CODE_REVIEW_SCORE=85
DESIGN_SCORE=80
# CI 状态映射
case "$CI_STATUS_TEXT" in
passing) CI_STATUS=100; CI_PASSING=true; CI_LABEL="✅ 本地编译通过" ;;
failing) CI_STATUS=0; CI_PASSING=false; CI_LABEL="❌ 编译失败" ;;
*) CI_STATUS=0; CI_PASSING=true; CI_LABEL="⏭️ 跳过(无法编译)" ;;
esac
QUALITY_SCORE=$(( CODE_REVIEW_SCORE * 40 / 100 + CI_STATUS * 30 / 100 + DESIGN_SCORE * 30 / 100 ))
THRESHOLD=70
echo " CodeReview 评分: $CODE_REVIEW_SCORE/100"
echo " CI 状态: $CI_STATUS_TEXT ($CI_LABEL)"
echo " 设计一致性: $DESIGN_SCORE/100"
echo " 质量总分: $QUALITY_SCORE/100"
echo ""
# ---- 门禁判定 ----
if [ "$QUALITY_SCORE" -ge "$THRESHOLD" ] && [ "$CI_PASSING" = "true" ]; then
echo "✅ 门禁判定:通过"
echo " 评分 $QUALITY_SCORE$THRESHOLD"
if [ "$DRY_RUN" = "true" ]; then
echo ""
echo "[DRY-RUN] 将执行以下操作:"
echo " 1. gitlink-cli pr +review --id $PR_ID --status approved --content \"<review_summary>\""
echo " 2. gitlink-cli pr +merge --id $PR_ID --do squash"
echo ""
echo "[DRY-RUN] 跳过实际合并"
else
echo "[INFO] 提交通过评审..."
gitlink-cli pr +review --id "$PR_ID" --owner "$OWNER" --repo "$REPO" \
--status approved --content "✅ 质量门禁通过(评分: $QUALITY_SCORE/100"
echo "[INFO] 自动合并 PR #$PR_ID..."
gitlink-cli pr +merge --id "$PR_ID" --owner "$OWNER" --repo "$REPO" --do squash
echo "[INFO] PR #$PR_ID 合并成功"
fi
else
echo "❌ 门禁判定:阻塞"
echo " 评分 $QUALITY_SCORE < $THRESHOLD(未达门槛)"
if [ "$DRY_RUN" = "true" ]; then
echo ""
echo "[DRY-RUN] 将执行以下操作:"
echo " 1. gitlink-cli pr +review --id $PR_ID --status common --content \"<fix_suggestions>\""
echo ""
echo "[DRY-RUN] 跳过添加评审"
else
echo "[INFO] 提交修改建议..."
gitlink-cli pr +review --id "$PR_ID" --owner "$OWNER" --repo "$REPO" \
--status common --content "❌ 质量门禁未通过,评分:$QUALITY_SCORE/100\n请修复后重新提交。"
echo "[INFO] 修改建议已提交"
fi
fi
echo ""
echo "[========================================]"
echo "[ Phase 3 完成 ]"
echo "[ 决策结果: $([ "$QUALITY_SCORE" -ge "$THRESHOLD" ] && echo "通过" || echo "阻塞") ]"
echo "[========================================]"

View File

@ -1,80 +0,0 @@
#!/bin/bash
# ================================================================
# 代码质量看门人 — 全流程串联脚本
# 功能:遍历所有待审 PR执行采集 → 审查 → CI 检查 → 门禁决策
# 使用bash quality-gate-full.sh <owner> <repo>
# 环境变量DRY_RUN=true|false (默认 true)
# ================================================================
set -e
OWNER=${1:?"Usage: $0 <owner> <repo>"}
REPO=${2}
DRY_RUN=${DRY_RUN:-true}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_DIR="$SCRIPT_DIR/_output"
mkdir -p "$OUTPUT_DIR"
echo "============================================"
echo " 代码质量看门人"
echo " Target: $OWNER/$REPO"
echo " DRY_RUN: $DRY_RUN"
echo " 开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================"
echo ""
# Phase 1: 采集待审 PR
echo "▸ Phase 1/4: PR 采集"
bash "$SCRIPT_DIR/01-collect-prs.sh" "$OWNER" "$REPO"
echo ""
# 读取待审 PR 列表(用相对路径避免 MSYS 路径问题)
PR_REL="skills/gitlink-quality-gate/scripts/_output/prs-to-review.json"
if [ ! -f "$PR_REL" ]; then
echo "[ERROR] 未找到 PR 列表,请先运行 Phase 1"
exit 1
fi
PR_COUNT=$(node -e "const d=require('fs').readFileSync('$PR_REL','utf8');process.stdout.write(String(JSON.parse(d).length))" 2>/dev/null || echo "0")
if [ "$PR_COUNT" -eq 0 ]; then
echo "[INFO] 没有待审 PR流程结束"
exit 0
fi
echo "[INFO] 共 $PR_COUNT 个 PR 需要审查"
# 遍历每个 PR
for i in $(seq 0 $((PR_COUNT - 1))); do
PR_ID=$(node -e "const d=require('fs').readFileSync('$PR_REL','utf8');const items=JSON.parse(d);process.stdout.write(String(items[$i].id))" 2>/dev/null || echo "")
if [ -z "$PR_ID" ]; then
echo "[WARN] PR #$i: 无法解析 PR ID跳过"
continue
fi
echo "--------------------------------------------"
echo " 处理 PR #$PR_ID"
echo "--------------------------------------------"
# Phase 2: 深度审查
echo "▸ Phase 2/4: 深度审查"
bash "$SCRIPT_DIR/02-deep-review.sh" "$OWNER" "$REPO" "$PR_ID"
echo ""
# Phase 3: 本地 CI 检查(编译验证)
echo "▸ Phase 3/4: 本地 CI 检查"
bash "$SCRIPT_DIR/03-local-ci-check.sh" "$OWNER" "$REPO" "$PR_ID"
echo ""
# Phase 4: 门禁决策
echo "▸ Phase 4/4: 门禁决策"
bash "$SCRIPT_DIR/04-quality-gate-decision.sh" "$OWNER" "$REPO" "$PR_ID"
echo ""
done
echo "============================================"
echo " 全流程完成"
echo " 结束时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo " 处理 PR 数: $PR_COUNT"
echo " 输出目录: $OUTPUT_DIR/"
echo "============================================"

View File

@ -1,7 +1,7 @@
---
name: gitlink-release-auto
version: 2.0.0
description: "自动化 Release 管理:分析提交历史自动生成带分类、统计和链接的 Release Notes推荐语义化版本号。"
version: 1.0.0
description: "自动化 Release 管理:从提交历史自动生成 Release Notes、推荐语义化版本号、批量发布管理。当用户需要创建版本发布、生成更新日志、自动化发版流程时触发。"
metadata:
requires:
bins: ["gitlink-cli"]
@ -11,8 +11,11 @@ metadata:
# gitlink-release-auto自动化 Release 管理)
**CRITICAL — 开始前必须先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md),其中包含认证、权限处理和 API 注意事项。**
**CRITICAL — `release +view` 必须使用 `version_id`(从 `release +list` 返回),不能用 tag_name否则返回 HTML 页面而非 JSON。**
**CRITICAL — GitLink 操作只能用 `gitlink-cli`。**
> **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md)
---
## 功能概述
@ -20,185 +23,265 @@ metadata:
本技能提供完整的自动化发版流程:
1. **语义化版本推荐** — 根据提交类型自动推荐下一个版本号
2. **Release Notes 自动生成** — 从提交历史分析、归类、统计,生成结构化 Changelog
3. **变更影响分析** — 统计变更文件数、新增/删除行数、涉及模块
4. **一键发布** — 创建 Release 并关联 Tag
2. **Release Notes 自动生成** — 从提交历史和已关闭 Issue 自动生成 Changelog
3. **一键发布** — 创建 Release 并关联 Tag
4. **发布后通知** — 在相关 Issue 中关联发版信息
---
## 数据分析流程
## 一、版本号推荐Semantic Versioning
### Step 1获取基线版本
### Semver 规则
```
v<MAJOR>.<MINOR>.<PATCH>
MAJOR有 Breaking Change不向下兼容的变更
MINOR有 feat新增功能向下兼容
PATCH只有 fix / perf / refactor / docs 等修复性变更
```
### 步骤 1获取当前版本号
```bash
# 获取最新 Release 确定基线
gitlink-cli release +list --owner myuser --repo myrepo --format json
# 获取最新 Release从中找当前版本号
gitlink-cli release +list --owner <owner> --repo <repo> --format json
# 取 data.releases[0].tag_name 作为当前版本
# 获取标签列表
gitlink-cli api GET /:owner/:repo/tags --format json
```
**分析输出:** 提取最新 tag_name如 v1.2.0)作为对比基准。
### Step 2分析提交历史
### 步骤 2获取自上次发版以来的提交
```bash
git log v1.2.0..HEAD --format="%H|%s|%an|%ad" --date=short --stat
# 获取自上次 Release 以来的提交
git log v1.1.0..HEAD --format="%H %s %an %ad" --date=short 2>&1
```
**分析逻辑:**
### 步骤 3AI 分析提交类型,推荐版本号
对每条 commit 的 message 进行分类统计
根据提交信息Conventional Commits进行分类
```
feat: → ✨ 新功能
fix: → 🐛 Bug 修复
docs: → 📝 文档更新
refactor: → ♻️ 代码重构
perf: → ⚡ 性能优化
test: → ✅ 测试相关
chore: → 🔧 工程配置
revert: → ⏪ 回退
其他 → 📦 其他变更
决策逻辑:
1. 任意提交包含 "BREAKING CHANGE" → MAJOR 升级
当前 v1.2.3 → 推荐 v2.0.0
2. 有 feat: 类型的提交(且无 Breaking Change→ MINOR 升级
当前 v1.2.3 → 推荐 v1.3.0
3. 仅有 fix/perf/refactor/docs/chore/ci 类型 → PATCH 升级
当前 v1.2.3 → 推荐 v1.2.4
```
**统计维度**
**版本号推荐输出示例**
```
总提交数 = feat + fix + docs + refactor + perf + test + chore + 其他
涉及文件 = git log --stat 统计的总文件数
变更行数 = git log --stat 统计的 +行/-行
贡献者数 = unique author 数量
当前版本v1.2.3
分析了 18 次提交2026-04-15 至今):
- 3 个 feat新增用户头像、搜索历史、消息通知
- 5 个 fix修复了 5 个 Bug
- 2 个 docs更新了接口文档
- 无 Breaking Change
推荐版本v1.3.0MINOR 升级,有新功能)
备选版本v1.2.4(如果认为功能较小,可用 PATCH
```
### Step 3语义化版本推荐规则
---
```
根据 commit 类型判断版本号变更幅度:
- 含有 BREAKING CHANGE 或 feat! → 主版本号 +1v1.x.x → v2.0.0
- 含有 feat 且无 breaking → 次版本号 +1v1.2.x → v1.3.0
- 只有 fix/refactor/docs 等 → 修订号 +1v1.2.0 → v1.2.1
## 二、Release Notes 自动生成
推荐版本号v{major}.{minor}.{patch}
### 获取数据
```bash
# 1. 获取自上次 Release 以来的提交
git log v1.1.0..HEAD --format="%H %s %an %ad" --date=short 2>&1
# 2. 获取本期关闭的 Issue
gitlink-cli issue +list --state closed --owner <owner> --repo <repo> --format json
# 3. 获取本期合并的 PR 列表
gitlink-cli pr +list --state merged --owner <owner> --repo <repo> --format json
```
### Step 4生成结构化的 Release Notes
### Release Notes 模板
```markdown
## v1.3.0 (2026-06-17)
## v1.3.0 (2026-05-07)
### 📊 版本概览
- 包含 **{total_commits}** 次提交
- 涉及 **{total_files}** 个文件
- 新增 **{additions}** 行 / 删除 **{deletions}** 行
- 贡献者:**{contributors}** 人
### ✨ 新功能
### ✨ 新功能({feat_count}
- feat: 新增代码片段管理功能(@author
- feat: 新增 Webhook 投递监控(@author
- feat(user): 新增用户头像上传功能 ([#234](link))
- feat(search): 支持全文搜索和历史记录 ([#256](link))
- feat(notify): 添加站内消息通知系统 ([#267](link))
### 🐛 Bug 修复({fix_count}
- fix: 修复 Wiki 删除时侧边栏残留问题(@author
### 🐛 Bug 修复
### 📝 文档({docs_count}
- docs: 更新 Shortcut 实现报告(@author
- docs: 添加工作流示例(@author
- fix(login): 修复手机号登录时验证码未清除的问题 ([#245](link))
- fix(upload): 修复大文件上传超时问题 ([#251](link))
- fix(api): 修复并发请求时偶发 500 错误 ([#259](link))
### 🔧 工程({chore_count}
- chore: 添加 DevOps CI 流水线(@author
### ⚡ 性能优化
### ⚡ 性能优化({perf_count}
- perf: 优化 hook-runner 输出格式(@author
- perf(search): 优化搜索接口响应速度,平均提升 40% ([#261](link))
### ⏪ 回退({revert_count}
- revert: 移除 Sidebar 自动管理(@author
### 📦 其他变更
- docs: 更新 API 接口文档
- build: 升级 Go 依赖到最新版本
- ci: 添加代码覆盖率检查
### 🤝 贡献者
感谢以下贡献者参与本版本开发:@zhangsan、@lisi、@wangwu
### 📈 统计汇总
| 类别 | 数量 | 占比 |
|------|------|------|
| ✨ 新功能 | {feat_count} | {feat_percent}% |
| 🐛 修复 | {fix_count} | {fix_percent}% |
| 📝 文档 | {docs_count} | {docs_percent}% |
| 🔧 工程 | {chore_count} | {chore_percent}% |
| ♻️ 重构 | {refactor_count} | {refactor_percent}% |
```
### Step 5创建 Release
---
> ⚠️ **重要**`贡献者` 必须去重release notes中如果有相同或者相似的记录需要去重不需要添加`完整变更日志`这个信息!
## 三、一键发布完整流程
### 标准发版步骤
```bash
gitlink-cli release +create --owner myuser --repo myrepo \
# Step 1确认当前版本和推荐版本
gitlink-cli release +list --owner <owner> --repo <repo> --format json
# Step 2获取变更内容提交历史
gitlink-cli api GET /:owner/:repo/commits --query 'page=1&limit=30&ref=master' --format json
# Step 3生成 Release NotesAI 分析提交后组织内容)
# Step 4创建 Release
gitlink-cli release +create \
--owner <owner> \
--repo <repo> \
--tag v1.3.0 \
--name "v1.3.0" \
--body "生成的 Release Notes 内容" \
--name "v1.3.0 - 用户体验升级版" \
--body "## v1.3.0\n\n### ✨ 新功能\n- ...\n\n### 🐛 Bug 修复\n- ..." \
--target master
# Step 5验证发布成功
gitlink-cli release +list --owner <owner> --repo <repo> --format json
# 从列表取 version_id
gitlink-cli release +view --owner <owner> --repo <repo> --id <version_id>
```
> ⚠️ **重要**`release +view` 必须用 `version_id`(整数),不能用 tag 名称(如 v1.3.0
### 预发布版本
```bash
# 创建 alpha/beta/rc 预发布版本
gitlink-cli release +create \
--tag v1.3.0-beta.1 \
--name "v1.3.0 Beta 1" \
--body "预发布版本,用于测试..." \
--prerelease true \
--target develop
```
---
## 四、发布后操作
### 关联 Issue 通知
```bash
# 在关联的 Issue 中添加评论,通知已发版
gitlink-cli issue +comment \
--id <issue_id> \
--body "🎉 此问题已在 v1.3.0 中修复,请更新到最新版本验证。"
```
### 批量关联 Issue
```bash
# 遍历本期关闭的 Issue逐一添加发版通知评论
gitlink-cli issue +list --state closed --format json
# 对每个 issue_id 执行 issue +comment
```
### 触发部署(可选)
```bash
# 发版后触发部署(通过 CI 重新构建 tag 对应的分支)
gitlink-cli ci +restart --build <latest_build_number>
```
---
## 五、完整发版检查清单
在执行发版前,确认以下事项:
```
发版前检查:
□ 所有计划纳入本次版本的 PR 已合并
□ CI 在 master 分支的最新构建是成功的
□ 所有计划修复的 Issue 已关闭
□ 文档已更新README、API 文档等)
□ 数据库迁移脚本已准备就绪(如有)
版本号确认:
□ 版本号遵循 Semantic Versioning
□ 是否有 Breaking Change需 MAJOR 升级)
□ 是否发预发布版本alpha/beta/rc
Release Notes 检查:
□ 新功能描述清晰
□ Bug 修复有具体说明
□ Breaking Change 有迁移指南
□ 关联了对应的 Issue / PR 链接
发版操作:
□ 在正确的分支/提交上打 Tag
□ Release 创建成功
□ 相关 Issue 已通知
```
---
## 六、版本管理最佳实践
### 发版节奏建议
| 模式 | 说明 | 适用场景 |
|------|------|---------|
| 定期发版 | 每 1~2 周一次 PATCH每月一次 MINOR | 功能迭代稳定的项目 |
| 功能发版 | 功能完成即发版 | 需求驱动、快速迭代 |
| 按需发版 | Bug 修复立即发版 | 线上紧急修复hotfix |
### Hotfix 发版流程
```bash
# 1. 从当前 Release Tag 创建 hotfix 分支
gitlink-cli branch +create --name hotfix/v1.2.4-critical-fix --from v1.2.3
# 2. 在 hotfix 分支修复问题,合并回 master
# (通过 PR 流程)
# 3. 快速发布 PATCH 版本
gitlink-cli release +create \
--tag v1.2.4 \
--name "v1.2.4 紧急修复版" \
--body "## 紧急修复\n\n- fix: 修复生产环境关键 Bug#xxx" \
--target master
```
---
## 完整示例
假设项目当前 tag 为 v1.2.0,执行:
```bash
# 获取基线
gitlink-cli release +list --owner myuser --repo myrepo --format json
# 获取提交历史
git log v1.2.0..HEAD --format="%H|%s|%an|%ad" --date=short
# 分析结果示例:
# 共 12 次提交feat 3、fix 2、docs 4、chore 2、perf 1
# 涉及 18 个文件,+350/-120 行
# 3 位贡献者
# 推荐版本v1.3.0(有 feat无 breaking
# 生成的 Release Notes
```
```markdown
## v1.3.0 (2026-06-17)
### 📊 版本概览
- 包含 **12** 次提交 | 涉及 **18** 个文件
- 新增 **+350** 行 / 删除 **-120** 行
- 贡献者:**3** 人
### ✨ 新功能3
- feat: 新增代码片段管理
- feat: 新增 Webhook 投递监控
- feat: 新增 Wiki 管理 Skill
### 🐛 Bug 修复2
- fix: 修复 _Sidebar.md 残留问题
- fix: 修复 snippet delete API 参数错误
### 📝 文档4
- docs: 添加工作流示例
- docs: 更新实现报告
### 🔧 工程2
- chore: 添加 CI 流水线
- chore: 更新依赖
### ⚡ 性能优化1
- perf: 优化 list 输出格式
### 📈 统计汇总
| 类别 | 数量 | 占比 |
|------|------|------|
| ✨ 新功能 | 3 | 25% |
| 🐛 修复 | 2 | 17% |
| 📝 文档 | 4 | 33% |
| 🔧 工程 | 2 | 17% |
| ⚡ 性能 | 1 | 8% |
```
```bash
# 创建 Release
gitlink-cli release +create --owner myuser --repo myrepo \
--tag v1.3.0 --name "v1.3.0" --body "生成的 Release Notes" --target master
```
## 注意事项
- 每个分类都要统计**数量**和**占比**,让读者直观了解本次发布的构成。
- commit message 必须遵循 Conventional Commits 规范才能正确分类(`feat:` / `fix:` / `docs:` 等)。
- 对于不符合规范的 commit归类为"📦 其他变更"。
- 如果包含 BREAKING CHANGE务必提示版本号升级的影响。
- ✅ **版本号一旦发布不可修改**,确认无误后再执行创建
- ✅ **BREAKING CHANGE 必须在 Release Notes 中明确标注**,并提供迁移指南
- ⚠️ **`release +view` 始终使用 `version_id`**
- ✅ **预发布版本beta/rc先内部测试**,验证后再发正式版
- ✅ **发版后通知**注意发版后要对所有关联的issue添加通知评论

View File

@ -1,113 +0,0 @@
# Release Notes 生成完整工作流示例(含数据分析)
**场景**:项目即将发布新版本,需要根据 commit 生成带统计分析和分类的 Release Notes。
## 前置条件
- `gitlink-cli` 已安装并登录
## 工作流步骤
### Step 1获取当前最新 Release
```bash
gitlink-cli release +list --owner z2_cc --repo gitlink-cli --format json
```
**分析:** 找到最新 tag 作为版本对比基线。假设为 v1.2.0。
### Step 2获取提交历史
```bash
git log v1.2.0..HEAD --format="%H|%s|%an|%ad" --date=short
```
**AI 分类统计过程:**
```
原始提交:
a4587f9|feat: add webhook +failed and +task-view|wqer|2026-06-04
37a0f21|docs: add release notes workflow example|wqer|2026-06-17
6c0ad3b|feat: add three new skills|wqer|2026-06-17
d1cc68b|docs: add workflow examples|wqer|2026-06-17
9a51db0|feat: add wiki and snippet skills|wqer|2026-06-17
分类统计:
✨ 新功能3 次 (60%)
📝 文档2 次 (40%)
总提交5 次1 位贡献者
```
### Step 3统计变更文件
```bash
git log v1.2.0..HEAD --stat --oneline
```
**统计结果:**
```
涉及 12 个文件
新增 +245 行,删除 -89 行
主要变更模块shortcuts/webhook/、skills/
```
### Step 4推荐版本号
```
最新版本v1.2.0(仅修订号变更)
提交类型:包含 feat无 BREAKING CHANGE
推荐版本v1.3.0(次版本号 +1
```
### Step 5生成带分类和统计的 Release Notes
```markdown
## v1.3.0 (2026-06-17)
### 📊 版本概览
- 5 次提交 | 12 个文件变更
- +245 / -89 行 | 1 位贡献者
### ✨ 新功能3
- feat: 新增 Webhook 投递监控failed + task-view
- feat: 新增三个 AI Agent Skill
- feat: 新增 Wiki 和代码片段 Skill
### 📝 文档2
- docs: 添加 Release Notes 工作流示例
- docs: 添加其他工作流示例
### 📈 统计汇总
| 类别 | 数量 | 占比 |
|------|------|------|
| ✨ 新功能 | 3 | 60% |
| 📝 文档 | 2 | 40% |
```
### Step 6创建 Release
```bash
gitlink-cli release +create --owner z2_cc --repo gitlink-cli \
--tag v1.3.0 \
--name "v1.3.0" \
--body "## v1.3.0 (2026-06-17)\n\n### 📊 版本概览\n- 5 次提交 | 12 个文件变更\n- +245 / -89 行 | 1 位贡献者\n\n### ✨ 新功能3\n- feat: 新增 Webhook 投递监控\n- feat: 新增三个 AI Agent Skill\n- feat: 新增 Wiki 和代码片段 Skill" \
--target master
```
---
## 完整命令速览
```bash
# 1. 获取基线版本
gitlink-cli release +list
# 2. 获取提交历史
git log <基线>..HEAD --format="%H|%s|%an|%ad" --date=short
# 3. 统计变更
git log <基线>..HEAD --stat --oneline
# 4. 创建 Release
gitlink-cli release +create --tag <版本> --name <名称> --body <Release Notes>
```

Some files were not shown because too many files have changed in this diff Show More