From 8526b6bed6ad00c8a70a72ca218f8dc14d268def Mon Sep 17 00:00:00 2001 From: Surponess Date: Mon, 6 Jul 2026 11:16:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=BC=94=E7=A4=BAdemo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devops/自动构建部署.yml | 12 + .gitignore | 6 +- demo/Dockerfile | 29 ++ demo/README.md | 91 ++++ demo/SHOWCASE.md | 96 ++++ demo/build-demo.sh | 13 + demo/live-demo-guide.md | 146 ++++++ demo/live-demo.sh | 59 +++ demo/pr-guard-architecture.md | 118 +++++ demo/pr-guard-workflow.sh | 76 +++ demo/research-insight-guide.md | 157 +++++++ ...search-insight-report-whale_gitlink-cli.md | 87 ++++ demo/research-insight-verification.md | 104 +++++ demo/research-insight-workflow.sh | 104 +++++ demo/snippet-live-demo.sh | 94 ++++ demo/web/README.md | 56 +++ demo/web/index.html | 437 ++++++++++++++++++ demo/web/server.py | 313 +++++++++++++ gitlink-cli.exe | Bin 18441216 -> 18441216 bytes 19 files changed, 1997 insertions(+), 1 deletion(-) create mode 100644 demo/Dockerfile create mode 100644 demo/README.md create mode 100644 demo/SHOWCASE.md create mode 100644 demo/build-demo.sh create mode 100644 demo/live-demo-guide.md create mode 100644 demo/live-demo.sh create mode 100644 demo/pr-guard-architecture.md create mode 100644 demo/pr-guard-workflow.sh create mode 100644 demo/research-insight-guide.md create mode 100644 demo/research-insight-report-whale_gitlink-cli.md create mode 100644 demo/research-insight-verification.md create mode 100644 demo/research-insight-workflow.sh create mode 100644 demo/snippet-live-demo.sh create mode 100644 demo/web/README.md create mode 100644 demo/web/index.html create mode 100644 demo/web/server.py diff --git a/.devops/自动构建部署.yml b/.devops/自动构建部署.yml index 5a416d9..369e951 100644 --- a/.devops/自动构建部署.yml +++ b/.devops/自动构建部署.yml @@ -23,8 +23,20 @@ workflow: ssh_cmd: '"if [ -d /root/gitlink-cli/.git ]; then cd /root/gitlink-cli && git fetch origin && git checkout master && git reset --hard origin/master; else rm -rf /root/gitlink-cli && git clone https://gitlink.org.cn/whale_hihihi/gitlink-cli.git /root/gitlink-cli && cd /root/gitlink-cli && git checkout master; fi && docker stop gitlink-cli 2>/dev/null; docker rm gitlink-cli 2>/dev/null; docker rmi gitlink-cli:latest 2>/dev/null; docker build --no-cache -t gitlink-cli:latest . && docker run -d --name gitlink-cli gitlink-cli:latest && echo Deploy success"' needs: - start + - ref: ssh_cmd_1 + name: 构建并部署demo网页(8000) + task: ssh_cmd@1.1.1 + input: + ssh_pass: ((deploy_server.password)) + ssh_ip: '"121.41.222.73"' + ssh_port: '"22"' + ssh_user: '"root"' + ssh_cmd: '"cd /root/gitlink-cli && docker stop gitlink-cli-demo 2>/dev/null; docker rm gitlink-cli-demo 2>/dev/null; docker rmi gitlink-cli-demo:latest 2>/dev/null; docker build --no-cache -f demo/Dockerfile -t gitlink-cli-demo:latest . && docker run -d --name gitlink-cli-demo -p 8000:8000 --restart unless-stopped gitlink-cli-demo:latest && echo Demo deploy success at http://121.41.222.73:8000"' + needs: + - ssh_cmd_0 - ref: end name: 结束 task: end needs: - ssh_cmd_0 + - ssh_cmd_1 diff --git a/.gitignore b/.gitignore index 13c432e..49b26ae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ docs/ -doc/ \ No newline at end of file +doc/ +# Python(demo 网页后端) +__pycache__/ +*.pyc +demo/bin/ \ No newline at end of file diff --git a/demo/Dockerfile b/demo/Dockerfile new file mode 100644 index 0000000..6ab5bda --- /dev/null +++ b/demo/Dockerfile @@ -0,0 +1,29 @@ +# demo/Dockerfile — GitLink CLI 演示网页后端 +# 多阶段:Go 编译 Linux 二进制 → Python 运行时跑 server.py +# 构建上下文 = 仓库根(gitlink-cli/): docker build -f demo/Dockerfile -t gitlink-cli-demo . + +# ---------- Stage 1: 编译 gitlink-cli(Linux) ---------- +FROM golang:1.26-alpine AS builder +ENV GOPROXY=https://goproxy.cn,direct +ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64 +WORKDIR /src +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN go build -ldflags="-s -w" -o /out/gitlink-cli . + +# ---------- Stage 2: Python 运行时 ---------- +FROM python:3.11-alpine +RUN apk add --no-cache git ca-certificates +WORKDIR /app +# 二进制 +COPY --from=builder /out/gitlink-cli /usr/local/bin/gitlink-cli +# 演示网页 + Skills(server.py 要读 SKILL.md) +COPY demo/ /app/demo/ +COPY skills/ /app/skills/ +ENV HOST=0.0.0.0 +ENV PORT=8000 +ENV GITLINK_BIN=/usr/local/bin/gitlink-cli +EXPOSE 8000 +WORKDIR /app/demo/web +CMD ["python3", "server.py"] diff --git a/demo/README.md b/demo/README.md new file mode 100644 index 0000000..e6da6be --- /dev/null +++ b/demo/README.md @@ -0,0 +1,91 @@ +# GitLink CLI · 演示网页(demo/) + +> 一个**可交互演示站**,展示子任务一~四全部成果:25 域命令浏览器、48 Skill 卡片墙、pr-guard 工作流、科研四维画像。 +> 后端 `web/server.py`(Python 标准库,零依赖)真跑 `gitlink-cli`;**访客自带 token,零凭据上云**。 + +## 目录结构 + +``` +demo/ +├── web/ # 演示网页(核心) +│ ├── server.py # Python 后端(/api/run /api/skill /api/analyze) +│ ├── index.html # 前端单页(Tailwind+Chart.js CDN) +│ └── README.md # 网页本地启动说明 +├── Dockerfile # demo 部署镜像(Go 编译 + Python 运行时) +├── build-demo.sh # 本地一键产 Linux 二进制(测 Dockerfile 用) +├── research-insight-workflow.sh # 任务四:科研画像端到端脚本 +├── pr-guard-workflow.sh # 任务三:质量看门人脚本 +├── live-demo.sh / snippet-live-demo.sh +└── *.md # 各任务指南 + 验证记录 + 报告原件 +``` + +--- + +## 一、本地跑(Windows / Linux / macOS) + +```bash +# 1. 编译 CLI(仓库根) +cd gitlink-cli # 含 go.mod 的仓库根 +go build -o gitlink-cli . # Windows 产出 gitlink-cli.exe + +# 2. 启动后端 +cd demo/web +python server.py # → http://0.0.0.0:8000 + +# 3. 浏览器开 http://localhost:8000 +# 顶栏粘自己的 GitLink token → 平台命令真跑;snippet 等本地命令免 token +``` + +> 二进制自动探测:`GITLINK_BIN` > 仓库根 `gitlink-cli[.exe]` > PATH。 +> 端口/主机:`PORT=9000 HOST=127.0.0.1 python server.py`。 + +--- + +## 二、云端部署(用你们已有服务器 121.41.222.73) + +已配置好「**push 即上线**」:`.devops/自动构建部署.yml` 在原有 CLI 部署之后,**追加一步**构建并运行 demo 容器: + +``` +docker build -f demo/Dockerfile -t gitlink-cli-demo . +docker run -d --name gitlink-cli-demo -p 8000:8000 --restart unless-stopped gitlink-cli-demo +``` + +**你只需**: +1. 把本目录提交并 push 到 `whale_hihihi/gitlink-cli` master → CI 自动跑 → demo 上线。 +2. 在服务器安全组/防火墙**开放 8000 端口**(阿里云安全组加一条入方向 TCP 8000)。 +3. 访问 `http://121.41.222.73:8000`。 + +> 手动部署(不走 CI):SSH 到服务器,`cd /root/gitlink-cli && docker build -f demo/Dockerfile -t gitlink-cli-demo . && docker run -d --name gitlink-cli-demo -p 8000:8000 --restart unless-stopped gitlink-cli-demo`。 + +### 镜像里有什么(demo/Dockerfile 多阶段) +- Stage1 `golang:1.26-alpine`:`CGO_ENABLED=0 GOOS=linux go build` 产 Linux 二进制。 +- Stage2 `python:3.11-alpine`:装 `git`/`ca-certificates`,放二进制到 `/usr/local/bin/gitlink-cli`,拷 `demo/` 和 `skills/`,`ENV PORT=8000`,`CMD python3 demo/web/server.py`。 + +--- + +## 三、安全模型(为什么能放心公网开放) + +| 点 | 做法 | +|----|------| +| 团队 token | **不烘焙**进镜像/代码。镜像里没有任何 GitLink 凭据。 | +| 访客 token | 只存在访客自己的浏览器 localStorage,按请求传后端 → 注入子进程 `GITLINK_TOKEN` → 用完即弃,**不落盘、不写日志**。 | +| 命令注入 | 后端白名单(仅 30 个 gitlink-cli 顶层域)+ subprocess 列表参数(不经 shell)+ 30s 超时。 | +| 写操作 | CLI 写操作本就要 `--dry-run`/确认;演示页默认只点只读命令。 | + +→ 公网开放的安全风险≈0:泄露的至多是访客自己输错的那一次请求。 + +--- + +## 四、访客怎么用(写进 PPT/答辩) + +1. 打开 `http://121.41.222.73:8000`。 +2. 顶栏粘自己的 GitLink 个人访问令牌(GitLink → 个人中心 → 个人令牌)。 +3. 点「命令域」里任意动词 → 终端真跑;或点 Skill 卡片读 SKILL.md;或科研区「实拉分析」任一仓库。 + +--- + +## 五、其它 PaaS 部署(可选,不占你们服务器) + +也可部署到 Render / Railway / Koyeb 等(需能跑 Docker): +- 用 `demo/Dockerfile`,暴露端口环境变量 `PORT`(已支持)。 +- 这些平台默认按其给的端口注入 `PORT`,server.py 已读 `PORT` 环境变量,无需改。 diff --git a/demo/SHOWCASE.md b/demo/SHOWCASE.md new file mode 100644 index 0000000..219015d --- /dev/null +++ b/demo/SHOWCASE.md @@ -0,0 +1,96 @@ +# Skills 功能验收演示文稿 + +> 用法:照此 5 分钟流程演示。**Demo 1 可现场实跑**(零依赖、最稳),其余讲解设计。 +> 配套:`snippet-live-demo.sh`(实演脚本)、`../Skills工作总结.md`(完整成果) + +--- + +## 演示总览(5 分钟) + +| 环节 | 时长 | 形式 | 目的 | +|------|:----:|------|------| +| 开场:Skills 是什么 | 30s | 口述 + 成果速览 | 讲清价值定位 | +| **Demo 1 · snippet 实演** | 1.5min | **跑脚本** | 证明 Skill 真能驱动 CLI | +| Demo 2 · onboarding 设计 | 1.5min | 打开 SKILL.md 讲 | 展示 AI 工作流设计深度 | +| Demo 3 · digest/todo 体验优化 | 1min | 讲设计 + 分工 | 展示体验优化与去重思考 | +| 收尾:成果 + 验证 | 30s | 数字 | 强化贡献 | + +--- + +## 开场(30 秒) + +> 一句话:**Skills 是写给 AI 的「菜谱」**——告诉 AI「什么场景、按什么顺序、调哪些 gitlink-cli 命令」。我们把 gitlink-cli 从「开发者工具」升级为「AI 可驱动的平台」。 +> +> 本次新增 **5 个 Skill** + 补全 **28 个 examples** + snippet **7 命令端到端实测通过**。 + +--- + +## Demo 1 · snippet 现场实演(核心,必演) + +```bash +bash demo/snippet-live-demo.sh +``` + +**脚本会演示的闭环**(每个场景都展示「🧑用户提问 → 🤖AI 读 SKILL.md 决策 → 执行命令 → 输出」): + +| 场景 | 命令 | SKILL.md 规则 | +|------|------|--------------| +| 保存代码 | `snippet +create` | --title 必填、--tags 逗号分隔 | +| 浏览 | `snippet +list` | 可按 tag/language 过滤 | +| 检索 | `snippet +search` | 全文匹配 | +| 详情 | `snippet +view` | 按 id | +| 导出 | `snippet +export` | -o 写文件 | +| 更新 | `snippet +update` | 至少一个字段 | +| 删除 | `snippet +delete` | 不可逆,先确认 | + +**讲解要点**:注意每个场景 AI 都先「读 SKILL.md 决策」再执行——这就是 Skills 的核心价值,**AI 不是瞎调命令,而是按菜谱编排**。输出严格符合 `{"ok":true,"data":{...}}` 格式。 + +--- + +## Demo 2 · onboarding 设计深度(展示 B 类工作流) + +**操作**:打开 `gitlink-cli/gitlink-cli/skills/gitlink-onboarding/SKILL.md` + +**重点讲三处**(评分重点): + +1. **5 维度友好度评估表**(决策规则章节)——把「哪个 Issue 适合新人」从主观判断变成可量化打分:标题清晰度 / 描述完整度 / 代码定位 / 改动范围 / 难度标签。 +2. **4 个工作流**——项目概览 → 找任务 → 生成引导评论 → 贡献全流程(Fork→Branch→PR)。 +3. **引导评论输出模板**——AI 能自动生成「欢迎贡献 + 代码定位 + 修改步骤」的个性化评论。 + +> 一句话:A 类(命令包装)做不到「智能推荐 + 生成评论」,所以选 B 类(AI 工作流)。 + +--- + +## Demo 3 · digest / todo 体验优化(展示第二批 + 去重思考) + +| Skill | 解决的痛点 | 与团队已有 Skill 的关系 | +|-------|-----------|----------------------| +| `gitlink-digest` | 信息太分散,看动态要挨个刷 | 与团队 `notification-digest` **分工**:它做通知中心,我做项目全景日报(Issue+PR+CI+活跃度) | +| `gitlink-todo` | 没有「我的」视角,不知哪些在等我 | 团队**无对应**,真缺口 | + +**去重思考(加分点)**:曾设计「僵尸唤醒 stale」,核查发现团队已有完整的 `gitlink-stale-issue-manager`(563 行),为避免重复造已删除——**体现对项目整体的理解和工程素养**。 + +--- + +## 收尾:成果 + 验证(30 秒) + +| 指标 | 数据 | +|------|------| +| 新增 Skill | **5 个**(onboarding / auth / snippet / digest / todo) | +| 补充 examples | **28 个**(23 个补已有 Skill + 5 个新增自带) | +| 端到端实测 | snippet 全 7 命令通过 | +| 命令可调用性 | 新增 Skill 全用已注册命令域,可真实调用 | + +> 演示结束。完整设计详见 `Skills工作总结.md`。 + +--- + +## 答辩 Q&A 预备 + +| 可能的提问 | 回答要点 | +|-----------|---------| +| 工作边界? | 新增 5 个 Skill + 补 23 个 examples;团队原有 42 个(见总结第二节) | +| 怎么证明 Skill 真能用? | 刚跑的 snippet 7 命令闭环;其余 4 个登录后可按 SKILL.md 工作流验证 | +| 为什么 onboarding 选 B 类? | 需智能推荐 + 生成评论,A 类命令包装做不到 | +| digest 和团队 notification-digest 重复吗? | 不重复,分工明确:通知中心 vs 项目全景日报 | +| Skill 遵循什么规范? | 项目模板:YAML frontmatter + CRITICAL 三连 + 引用 gitlink-shared | diff --git a/demo/build-demo.sh b/demo/build-demo.sh new file mode 100644 index 0000000..acebfa7 --- /dev/null +++ b/demo/build-demo.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# 一键构建 demo 所需的 Linux gitlink-cli 二进制(本地测试 Dockerfile 用) +# 用法:bash demo/build-demo.sh → 产物 demo/bin/gitlink-cli +set -e +DIR="$(cd "$(dirname "$0")" && pwd)" +ROOT="$(cd "$DIR/.." && pwd)" # 仓库根 +OUT="$DIR/bin" +mkdir -p "$OUT" +echo "→ 在 $ROOT 编译 Linux amd64 二进制..." +( cd "$ROOT" && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o "$OUT/gitlink-cli" . ) +echo "✓ 产出:$OUT/gitlink-cli" +echo " 本地测容器:docker build -f $DIR/Dockerfile -t gitlink-cli-demo '$ROOT'" +echo " docker run --rm -p 8000:8000 gitlink-cli-demo" diff --git a/demo/live-demo-guide.md b/demo/live-demo-guide.md new file mode 100644 index 0000000..f72a45f --- /dev/null +++ b/demo/live-demo-guide.md @@ -0,0 +1,146 @@ +# 4 个 Skill 登录实演指南(onboarding / digest / todo / auth) + +> 用法:登录后,**在 Claude Code 里用自然语言触发**,让真 AI 读 SKILL.md 自主编排 —— 这是最强的实演证据。 +> 配套:`live-demo.sh`(辅助采集脚本,不想手敲命令时用)。 + +--- + +## 〇、前置准备 + +1. **登录**:`gitlink-cli auth login`(或 `--token`),用 `gitlink-cli auth status` 确认已登录 +2. **准备测试仓库**:用一个你自己的/有权限的公开仓库作为演示对象(避免在团队主仓库留痕) +3. **开着 Claude Code**:在本仓库目录下启动,让 AI 能读到 `skills/*/SKILL.md` +4. **安全原则**:只读命令随便跑;写操作(评论/关闭)让 AI 先 `--dry-run` 或确认 + +--- + +## 〇〇、推荐演示方式:自然语言触发真 AI(最有说服力) + +> 不要告诉 AI 用哪个命令,只描述需求。看它是否**自主读 SKILL.md → 调对命令 → 输出符合模板**。 +> 这是"Skills 让 AI 能驱动 CLI"的活证据,比手敲命令强得多。 + +每个 Skill 下面都给:**① 触发语**(你对 AI 说这句)→ **② 预期 AI 行为** → **③ 手动备选**(想自己跑时)→ **④ 讲解要点**。 + +--- + +## 一、auth 实演(最简单,开场暖身) + +**① 触发语**: +> "检查一下我的 gitlink 登录状态" + +**② 预期 AI 行为**:读 `auth/SKILL.md` → 调 `gitlink-cli auth status` → 报告登录用户、Token 有效期、存储位置。 + +**③ 手动备选**: +```bash +gitlink-cli auth status +gitlink-cli auth login --token # 如需演示登录流程 +``` + +**④ 讲解要点**: +- auth Skill 与 `gitlink-shared` 分工:shared 讲认证原理,auth 讲具体命令操作 +- 决策树:遇到 401 → 引导 `auth login`;403 → 查权限;CI 环境 → 用 `--token` +- 演示 `logout` 后提醒:会清凭证,需重新登录 + +--- + +## 二、onboarding 实演(核心亮点:5 维度评估) + +**① 触发语**: +> "我想参与 / 这个项目,帮我找几个适合新手的任务" + +**② 预期 AI 行为**:读 `onboarding/SKILL.md` → +1. `search +issues --keyword "good first issue" --category opened`(找新手 Issue) +2. `repo +info` + `repo +readme`(项目概览) +3. 对候选 Issue 做 **5 维度友好度评估**(标题/描述/定位/范围/难度) +4. 输出「推荐新手任务」清单 + 可选生成引导评论 + +**③ 手动备选**: +```bash +gitlink-cli search +issues --owner --repo --keyword "good first issue" --category opened +gitlink-cli repo +info --owner --repo +gitlink-cli repo +readme --owner --repo +``` + +**④ 讲解要点**: +- **5 维度评估表**是设计亮点:把"哪个 Issue 适合新人"从主观判断变成可量化打分(指着 AI 输出的评分讲) +- 引导评论模板:AI 能生成「欢迎贡献 + 代码定位 + 修改步骤」个性化评论(写操作,会先确认) +- 若无 good-first-issue 标签:AI 应从开放 Issue 推荐最简单的(决策规则) + +--- + +## 三、digest 实演(亮点:跨源聚合成简报) + +**① 触发语**: +> "给我一份 / 的项目简报,今天有什么动态" + +**② 预期 AI 行为**:读 `digest/SKILL.md` → 并行采集 → 聚合分类 → +1. `issue +list --state open` + `pr +list`(Issue/PR 动态) +2. `ci +builds`(CI 状态) +3. `api GET "users//messages.json"`(通知) +4. 按 🔴需关注 / 🟢新增 / 🔵进行中 / 📊指标 分类,输出 Markdown 简报 + +**③ 手动备选**: +```bash +gitlink-cli issue +list --state open --format json +gitlink-cli pr +list --format json +gitlink-cli ci +builds --owner --repo --format json +gitlink-cli api GET "users//messages.json" +``` + +**④ 讲解要点**: +- **跨源聚合**是亮点:一份简报汇总 Issue/PR/CI/通知,不用挨个刷 +- 与团队 `notification-digest` 分工:它做通知中心(标记已读),digest 做项目全景(不做标记已读)—— 体现去重思考 +- 纯只读,安全可随时跑 + +--- + +## 四、todo 实演(亮点:补上「我的」视角) + +**① 触发语**: +> "我的待办有哪些?哪些 Issue/PR 在等我处理" + +**② 预期 AI 行为**:读 `todo/SKILL.md` → +1. `api GET "users/me"`(识别身份) +2. `search +issues --assignee --category opened`(分配我的) +3. `api GET "users//messages.json"`(@我的) +4. `pr +list`(我的 PR 状态) +5. 按紧急度(@我 > 待 review > 指派)排序,输出待办清单 + +**③ 手动备选**: +```bash +gitlink-cli api GET "users/me" --format json +gitlink-cli search +issues --assignee --category opened +gitlink-cli api GET "users//messages.json" +``` + +**④ 讲解要点**: +- **「我的」视角**是 gitlink 最缺的:跨 Issue/PR 汇总个人待办 +- 紧急度排序逻辑:@我且停留 >24h → 🔴紧急;待 review 的 PR → 🟡本周 +- 团队无对应 Skill,是真正的新增价值 + +--- + +## 五、验收串场词(5 分钟版) + +``` +开场(30s):Skills 让 AI 能驱动 gitlink-cli。先看 snippet 实演(跑 snippet-live-demo.sh)。 + +转场:snippet 是本地功能。接下来演示需要平台 API 的 4 个 Skill, + 我用自然语言提问,看 AI 是否自主读 SKILL.md 编排命令。 + +① auth(30s):「检查登录状态」→ AI 调 auth status。 +② onboarding(1.5min):「找新手任务」→ AI 5 维度评估出推荐清单。(重点讲评估表) +③ digest(1.5min):「给我项目简报」→ AI 跨源聚合出报告。(重点讲与团队分工) +④ todo(1min):「我的待办」→ AI 汇总排序。(重点讲个人视角是缺口) + +收尾(30s):5 个新增 Skill 都能被 AI 正确调用,snippet 7 命令实测通过。 +``` + +--- + +## 六、安全清单(实演前确认) + +- [ ] 用**测试仓库**演示,不用团队主仓库 +- [ ] 写操作(onboarding 引导评论、issue close)让 AI **先确认 / --dry-run** +- [ ] 演示完 `auth logout` 的话,记得重新登录 +- [ ] 只读命令(list/view/search/info/messages)可放心反复跑 diff --git a/demo/live-demo.sh b/demo/live-demo.sh new file mode 100644 index 0000000..04d641b --- /dev/null +++ b/demo/live-demo.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# ============================================================ +# 4 个 Skill 登录实演 · 辅助采集脚本 +# 作用:把每个 Skill 的「只读采集命令」串起来自动跑,展示真实数据 +# 分析(评估/聚合/排序)部分由 AI 在 Claude Code 里做——那才是亮点 +# 用法:bash demo/live-demo.sh [your-username] +# 例:bash demo/live-demo.sh myorg myproject zhangsan +# 前置:先 gitlink-cli auth login +# ============================================================ + +_DIR="$(cd "$(dirname "$0")" && pwd)" +CLI="$_DIR/../gitlink-cli.exe"; [ -f "$CLI" ] || CLI="$_DIR/../gitlink-cli" # Win→.exe,Linux→无后缀 +OWNER="${1:-}"; REPO="${2:-}"; ME="${3:-$OWNER}" + +G='\033[0;32m'; Y='\033[1;33m'; C='\033[0;36m'; R='\033[0;31m'; B='\033[1m'; N='\033[0m' +banner() { echo -e "\n${B}══════════════════════════════════════════════════════${N}"; echo -e "${B} $1${N}"; echo -e "${B}══════════════════════════════════════════════════════${N}"; } +section() { echo -e "\n${C}━━━ $1 ━━━${N}"; } +run() { echo -e "${Y}❯ $1${N}"; eval "$1" 2>&1 | head -16; echo; } + +# ---------- 前置检查 ---------- +banner "4 Skill 登录实演 · 辅助采集" +[ -f "$CLI" ] || { echo -e "${R}✗ 找不到 gitlink-cli${N}"; exit 1; } +if [ -z "$OWNER" ] || [ -z "$REPO" ]; then + echo -e "${R}用法: bash $0 [your-username]${N}" + echo -e "${R}例 : bash $0 myorg myproject zhangsan${N}"; exit 1 +fi +echo -e "${G}✓${N} 目标仓库: ${B}$OWNER/$REPO${N},当前用户: ${B}$ME${N}" +echo -e "${C}提示:本脚本只跑只读采集命令;分析(评估/聚合/排序)请在 Claude Code 里让 AI 做${N}" + +# ---------- 0. auth:登录状态 ---------- +section "auth · 登录状态" +run "\"$CLI\" auth status" + +# ---------- 1. onboarding:找新手任务 ---------- +section "onboarding · 新手 Issue + 项目概览(供 AI 做 5 维度评估)" +run "\"$CLI\" search +issues --owner $OWNER --repo $REPO --keyword 'good first issue' --category opened --format json" +run "\"$CLI\" repo +info --owner $OWNER --repo $REPO --format json" + +# ---------- 2. digest:多源数据(供 AI 聚合成简报)---------- +section "digest · Issue / PR / CI / 通知(供 AI 跨源聚合)" +run "\"$CLI\" issue +list --owner $OWNER --repo $REPO --state open --format json" +run "\"$CLI\" pr +list --owner $OWNER --repo $REPO --format json" +run "\"$CLI\" ci +builds --owner $OWNER --repo $REPO --format json" +run "\"$CLI\" api GET \"users/$ME/messages.json\"" + +# ---------- 3. todo:个人待办数据(供 AI 排序)---------- +section "todo · 分配给我的 Issue + @我消息(供 AI 排序成待办)" +run "\"$CLI\" api GET \"users/me\" --format json" +run "\"$CLI\" search +issues --assignee $ME --category opened --format json" +run "\"$CLI\" api GET \"users/$ME/messages.json\"" + +# ---------- 总结 ---------- +banner "采集完成" +echo -e "${B}接下来${N}:在 Claude Code 里用自然语言触发,让 AI 读对应 SKILL.md 分析以上数据:" +echo -e " • ${C}「找适合新手的任务」${N} → onboarding 的 5 维度评估" +echo -e " • ${C}「给我项目简报」${N} → digest 的跨源聚合" +echo -e " • ${C}「我的待办有哪些」${N} → todo 的紧急度排序" +echo -e "\n详见 ${Y}live-demo-guide.md${N}" +read -p "按回车键继续..." diff --git a/demo/pr-guard-architecture.md b/demo/pr-guard-architecture.md new file mode 100644 index 0000000..8445770 --- /dev/null +++ b/demo/pr-guard-architecture.md @@ -0,0 +1,118 @@ +# 代码质量看门人 · 工作流说明与架构(子任务三) + +> 端到端自动化工作流:PR 提交后自动跑完「采集 → AI Review → CI → 评论 → 质量判定/合并」。 +> 对应 Skill:`skills/gitlink-pr-guard/SKILL.md`;可复现脚本:`demo/pr-guard-workflow.sh`。 + +--- + +## 一、工作流架构图 + +``` + ┌─────────────────────────────────────────────┐ + │ 触发:PR 提交 / 更新 │ + │ (或用户:帮我把关 PR #) │ + └──────────────────────┬──────────────────────┘ + ▼ + ┌─────────────────────────────────────────────┐ + │ Step 1 采集 PR 变更 │ + │ pr +view → pr +files → pr +diff --stat │ + │ 产出:PR 详情 / 变更文件 / diff 统计 │ + └──────────────────────┬──────────────────────┘ + ▼ + ┌─────────────────────────────────────────────┐ + │ Step 2 AI Review(复用 code-review 逻辑) │ + │ 逐文件分析 diff → 分级找问题 │ + │ 🔴 Critical / 🟡 Warning / 🔵 Suggestion │ + └──────────────────────┬──────────────────────┘ + ▼ + ┌─────────────────────────────────────────────┐ + │ Step 3 CI 检查 │ + │ ci +builds → 匹配分支最新构建 → 状态 │ + │ success / failure / pending │ + └──────────────────────┬──────────────────────┘ + ▼ + ┌─────────────────────────────────────────────┐ + │ Step 4 发布质量看门人报告 │ + │ api POST .../pulls/:id/reviews │ + │ 报告:判定 + 问题清单 + CI + 处置建议 │ + └──────────────────────┬──────────────────────┘ + ▼ + ┌─────────────────────────────────────────────┐ + │ Step 5 质量判定(门禁规则) │ + │ ┌─────────────────────────────────────┐ │ + │ │ 0 Critical + CI success → ✅ 合并 │ │ + │ │ 有 Critical → 🔴 请求修改 │ │ + │ │ CI failure → 🔴 请求修改 │ │ + │ └─────────────────────────────────────┘ │ + │ 达标+确认 → pr +merge │ + └─────────────────────────────────────────────┘ +``` + +--- + +## 二、串联的 CLI 命令 / Skill(满足"≥3 步") + +| Step | 命令域 | 具体调用 | 类型 | +|:----:|:------:|---------|:----:| +| 1 | pr | `pr +view` / `+files` / `+diff` | 采集 | +| 2 | code-review | Review 分析逻辑(分级找问题) | AI 分析 | +| 3 | ci | `ci +builds` / `+log` | 采集 | +| 4 | api | `POST .../pulls/:id/reviews` | 写(评论) | +| 5 | pr | `pr +merge`(达标确认后) | 写(合并) | + +> **共串联 4 个命令域 + 5 个步骤 + 2 处写操作**,远超任务三"≥3 步"要求。 + +--- + +## 三、与子任务二的区别(关键) + +| 维度 | 子任务二 Skill(如 code-review) | 子任务三 本工作流(pr-guard) | +|------|--------------------------------|-----------------------------| +| **交付单位** | 单个 Skill | 串联多步的**完整解决方案** | +| **职责** | 只做 Review | Review + CI + 评论 + 合并决策 | +| **触发** | 用户要 Review | PR 提交自动跑完整流水线 | +| **决策** | 输出意见 | **质量门禁判定(通过/拒绝/合并)** | + +> code-review 是"审查员",pr-guard 是"看门人"——后者在前者基础上加了 CI 维度和合并决策,形成完整门禁。 + +--- + +## 四、可复现性(对应交付要求) + +| 要求 | 满足方式 | +|------|---------| +| 串联 ≥3 步 CLI/Skill | 5 步、4 域 ✅ | +| 含自定义 Skill 兼容 Agent | `gitlink-pr-guard` SKILL.md(Claude Code 可读)✅ | +| 可复现执行脚本 | `demo/pr-guard-workflow.sh`(参数化)✅ | +| 真实 GitLink 项目演示 | 登录后对真实 PR 运行(见下) | +| 工作流说明 + 架构图 | 本文档 ✅ | + +--- + +## 五、真实演示步骤(登录后) + +```bash +# 1. 登录 +gitlink-cli auth login + +# 2. 找一个真实 PR +gitlink-cli pr +list --owner --repo --state open + +# 3. 跑质量看门人流水线(脚本采集,AI 在 Claude Code 做 Step2 分析) +bash demo/pr-guard-workflow.sh + +# 或在 Claude Code 里自然语言触发: +# "读 skills/gitlink-pr-guard/SKILL.md,帮我把关 / 的 PR #42" +``` + +**预期 AI 行为**:读 pr-guard SKILL.md → 按工作流跑 5 步 → 输出质量看门人报告 + 判定(通过/拒绝)+ 合并建议。 + +--- + +## 六、交付清单 + +- [x] `skills/gitlink-pr-guard/SKILL.md` — 工作流定义 + 门禁规则 + 报告模板 +- [x] `demo/pr-guard-workflow.sh` — 可复现脚本(5 步串联) +- [x] `demo/pr-guard-architecture.md` — 本文档(说明 + 架构图) +- [ ] 真实项目演示(登录后运行 + 截图/录屏) +- [ ] 报告(暂缓,后续按统一策略补《新需求构思》《变更影响测试》) diff --git a/demo/pr-guard-workflow.sh b/demo/pr-guard-workflow.sh new file mode 100644 index 0000000..48398b9 --- /dev/null +++ b/demo/pr-guard-workflow.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# ============================================================ +# 代码质量看门人 · 端到端工作流脚本(子任务三) +# 串联 5 步:采集 PR → AI Review → CI 检查 → 汇总评论 → 质量判定 +# 用法:bash demo/pr-guard-workflow.sh +# 例:bash demo/pr-guard-workflow.sh myorg myproject 42 +# 前置:gitlink-cli auth login(涉及平台 API) +# 说明:采集命令真实执行;Review 分析由 AI Agent(读 pr-guard/SKILL.md)完成 +# ============================================================ + +_DIR="$(cd "$(dirname "$0")" && pwd)" +CLI="$_DIR/../gitlink-cli.exe"; [ -f "$CLI" ] || CLI="$_DIR/../gitlink-cli" # Win→.exe,Linux→无后缀 +OWNER="${1:-}"; REPO="${2:-}"; PR_ID="${3:-}" + +G='\033[0;32m'; Y='\033[1;33m'; C='\033[0;36m'; R='\033[0;31m'; B='\033[1m'; N='\033[0m' +banner() { echo -e "\n${B}══════════════════════════════════════════════════════${N}"; echo -e "${B} $1${N}"; echo -e "${B}══════════════════════════════════════════════════════${N}"; } +step() { echo -e "\n${C}━━━ Step $1 ━━━ ${B}$2${N}"; } +ai() { echo -e "🤖 ${G}AI(读 pr-guard/SKILL.md 后):${N} $1"; } +run() { echo -e "${Y}❯ $1${N}"; eval "$1" 2>&1 | head -16; echo; } + +# ---------- 前置检查 ---------- +banner "代码质量看门人 · PR #${PR_ID:-?} 质量流水线" +[ -f "$CLI" ] || { echo -e "${R}✗ 找不到 gitlink-cli${N}"; exit 1; } +if [ -z "$OWNER" ] || [ -z "$REPO" ] || [ -z "$PR_ID" ]; then + echo -e "${R}用法: bash $0 ${N}" + echo -e "${R}例 : bash $0 myorg myproject 42${N}"; exit 1 +fi +echo -e "${G}✓${N} 目标: ${B}$OWNER/$REPO${N} PR #${B}$PR_ID${N}" + +# ---------- Step 1:采集 PR 变更 ---------- +step 1 "采集 PR 变更(pr +view / +files / +diff)" +ai "先拉 PR 详情、变更文件、diff 统计,作为审查输入。" +run "\"$CLI\" pr +view --id $PR_ID --format json" +run "\"$CLI\" pr +files --id $PR_ID --format json" +run "\"$CLI\" pr +diff --id $PR_ID --stat" + +# ---------- Step 2:AI Review(复用 code-review 逻辑)---------- +step 2 "AI Review(按 code-review 分级找问题)" +ai "逐文件分析 diff,按安全红线/错误处理/规范分级。这一步由 AI Agent 完成(读 code-review/SKILL.md)。" +echo -e " ${C}分级框架${N}:" +echo -e " 🔴 Critical:硬编码密钥 / SQL·命令注入 / 路径遍历(安全红线,阻断合并)" +echo -e " 🟡 Warning :错误处理缺失 / 边界条件 / 明文敏感信息" +echo -e " 🔵 Suggestion:命名 / 性能 / 可配置化" +echo -e " ${C}Agent 在此输出分级清单(示例见 SKILL.md 输出模板)${N}" + +# ---------- Step 3:CI 检查 ---------- +step 3 "CI 检查(ci +builds)" +ai "查 PR 对应分支的最新构建状态,作为门禁第二维。" +run "\"$CLI\" ci +builds --owner $OWNER --repo $REPO --format json" +echo -e " ${C}判定:从返回按 source_branch 匹配最新构建 → success / failure / pending${N}" + +# ---------- Step 4:发布汇总评论 ---------- +step 4 "发布质量看门人报告(api POST .../reviews)" +ai "把 Review 意见 + CI 状态 + 质量判定组装成报告,评论到 PR。" +echo -e "${Y}❯ gitlink-cli api POST /$OWNER/$REPO/pulls/$PR_ID/reviews --body '<报告>'${N}" +echo -e " ${C}报告含${N}:质量判定 + Critical/Warning 清单 + CI 状态 + 处置建议" +echo -e " ${C}[实演时此处真实发送;脚本演示仅展示结构]${N}" + +# ---------- Step 5:质量判定 ---------- +step 5 "质量判定(门禁规则 → 合并 / 请求修改)" +ai "按门禁规则决策。注意:合并是写操作,默认只建议,确认后才执行。" +echo -e " ${C}门禁规则${N}:" +echo -e " 0 Critical + CI success → ✅ 通过,建议合并" +echo -e " 有 Critical 任一 → 🔴 拒绝,请求修改" +echo -e " CI failure → 🔴 拒绝,附 CI 日志" +echo -e " 仅 Warning/Suggestion → 🟡 通过(带建议)" +echo "" +echo -e " ${G}若判定通过 + 用户确认 →${N} ${Y}gitlink-cli pr +merge --id $PR_ID --method squash${N}" + +# ---------- 总结 ---------- +banner "流水线完成" +echo -e "${B}代码质量看门人${N} 串联了 ${B}5 步${N},覆盖 ${B}4 个 CLI 域${N}:" +echo -e " pr(采集/合并)+ code-review(Review)+ ci(构建)+ api(评论)" +echo -e "\n${C}真实演示${N}:登录后对本仓库一个真实 PR 跑此脚本,由 AI 完成 Step 2 分析。" +echo -e "详见 ${Y}pr-guard-architecture.md${N}(工作流说明 + 架构图)" +read -p "按回车键继续..." diff --git a/demo/research-insight-guide.md b/demo/research-insight-guide.md new file mode 100644 index 0000000..a4ec8e9 --- /dev/null +++ b/demo/research-insight-guide.md @@ -0,0 +1,157 @@ +# 科研仓库画像 · 使用指南(子任务四) + +> 把 GitLink 上的开源科研项目,转化成**可评估、可引用、可复现**的科研画像。 +> 对应 Skill:`skills/gitlink-research-insight/SKILL.md`;脚本:`demo/research-insight-workflow.sh`。 +> 定位:科研辅助(加分项),面向科研工作者/课题组,无需 Go,Markdown + CLI。 + +--- + +## 一、它能做什么 + +科研工作者面对 GitLink 上的一个开源科研项目,常问三个问题: +1. **能不能复现?**(别人的实验我跑得出同样结果吗) +2. **能不能引用?**(写论文能引这个项目/代码吗,引哪个版本) +3. **能不能合作?**(项目活跃吗,核心圈开放吗) + +本工具用 gitlink-cli 采集仓库数据,从**可复现性 / 活跃度 / 引用价值 / 协作健康**四个维度评估,并生成**贡献者协作知识图谱**,产出一份《科研仓库画像报告》。 + +--- + +## 二、快速使用 + +```bash +# 1. 登录 +gitlink-cli auth login + +# 2. 对一个科研仓库跑画像(脚本采集,AI 评分) +bash demo/research-insight-workflow.sh + +# 或在 Claude Code 里自然语言触发: +# "读 skills/gitlink-research-insight/SKILL.md,帮我评估 / 这个科研项目值不值得引用和复现" +``` + +--- + +## 三、工作流架构 + +``` + ┌──────────────────────────────────────┐ + │ 输入:一个 GitLink 科研仓库 │ + └──────────────────┬───────────────────┘ + ▼ + ┌──────────────────────────────────────┐ + │ Step 0 fork 检测(避免给 fork 错评) │ + │ repo +info → fork_info │ + └──────────────────┬───────────────────┘ + ▼ + ┌──────────────────────────────────────┐ + │ Step 1 数据采集(只读) │ + │ repo +info/languages/contributors │ + │ issue +list / pr +list │ + │ file +get LICENSE/CI / release +list │ + │ git clone 兜底(repo +commits 不存在)│ + └──────────────────┬───────────────────┘ + ▼ + ┌──────────────────────────────────────┐ + │ Step 2 四维科研评分 │ + │ 🔁 可复现性 📈 活跃度 │ + │ 📑 引用价值 🤝 协作健康 │ + └──────────────────┬───────────────────┘ + ▼ + ┌──────────────────────────────────────┐ + │ Step 3 协作知识图谱(mermaid) │ + │ 贡献者协作网络 + 巴士因子 │ + └──────────────────┬───────────────────┘ + ▼ + ┌──────────────────────────────────────┐ + │ Step 4 科研仓库画像报告 │ + │ 定性 + 综合评分 + 四维详情 + 建议 │ + └──────────────────────────────────────┘ +``` + +--- + +## 四、四维评分体系(科研创新点) + +### 🔁 可复现性(满分 10,科研最核心) +| 检查项 | 分值 | 判定方法 | +|--------|:---:|---------| +| CI 配置 | +2 | `.gitea/workflows` 或 `.github/workflows` 存在 | +| 依赖锁定 | +2 | `go.sum` / `package-lock.json` / `requirements.txt` | +| 数据/数据说明 | +2 | README 提及数据集,或有 `data/` | +| 运行文档 | +2 | README 有安装/运行/环境说明 | +| 版本归档 | +2 | 有 release/tag(可引用固定版本) | + +### 📈 活跃度 +近 3 月提交频率 + Issue/PR 活跃 + 贡献者趋势 + +### 📑 引用价值 +LICENSE + 版本归档 + 文档完整 + 星标/关注 + +### 🤝 协作健康 +Issue 响应时长 + PR 合并率 + **巴士因子**(核心贡献者提交占比,越分散越健康) + +> **与 gitlink-health 区别**:health 看"工程维护好不好",本工具看"科研上值不值得用"(可复现/引用/合作)。 + +--- + +## 五、报告样例(填好的示例) + +```markdown +# 🔬 科研仓库画像 — someresearch/awesome-paper-code + +> 一句话定性:这是一个活跃维护的 NLP 科研项目,适合引用与复现。 + +## 📊 综合评分:⭐ 8.5/10 +| 维度 | 得分 | 评价 | +|------|:---:|------| +| 🔁 可复现性 | 8/10 | CI+依赖锁定+数据说明齐全,可复现 | +| 📈 活跃度 | 9/10 | 近3月持续提交,活跃 | +| 📑 引用价值 | 9/10 | MIT 协议 + v2.1 版本,适合引用 | +| 🤝 协作健康 | 8/10 | 巴士因子健康(核心占 45%) | + +## 🔁 可复现性详情 +- CI:✅ GitHub Actions +- 依赖锁定:✅ requirements.txt +- 数据说明:✅ README 有数据集下载指引 +- 版本归档:✅ 最新 v2.1 + +## 💡 给科研工作者的建议 +1. 引用:建议引 v2.1(MIT 协议) +2. 复现:按 README + CI 可复现 +3. 合作:协作网络开放,可联系 @核心贡献者 +``` + +--- + +## 六、真实仓库验证步骤(交付要求) + +```bash +# 1. 选一个 GitLink 上的科研类仓库(有 LICENSE/CI/数据 的最佳) +# 2. 跑画像脚本 +bash demo/research-insight-workflow.sh <科研仓库owner> <科研仓库> + +# 3. 在 Claude Code 让 AI 读 SKILL.md 完成评分,产出报告 +# 4. 截图/录屏报告 → 作为演示成果 +``` + +--- + +## 七、与子任务二/三的关系 + +| 子任务 | 视角 | 本任务复用 | +|--------|------|-----------| +| 任务二 health | 工程健康度 | 复用其指标采集 + 加科研维度 | +| 任务三 pr-guard | 端到端工作流 | 复用"多步串联 + Skill + 脚本"模式 | +| **任务四 本工具** | 科研价值 | 综合复用,加可复现性/引用/知识图谱 | + +--- + +## 八、交付清单 + +- [x] `skills/gitlink-research-insight/SKILL.md` — 科研洞悉 Skill(自定义,遵循规范) +- [x] `demo/research-insight-workflow.sh` — 可复现脚本(5 步:fork 检测 + 采集 + 评分 + 图谱 + 报告) +- [x] `demo/research-insight-guide.md` — 本文档(完整中文 + 架构 + 报告样例) +- [x] 真实科研仓库验证 — 已对 `whale_hihihi/gitlink-cli` 跑通,见 `demo/research-insight-verification.md` + 报告 `demo/research-insight-report-whale_gitlink-cli.md` +- [x] 命令缺陷修复 — SKILL.md 与脚本原用的 `repo +commits`/`+raw`/`+tags` 三条不存在命令,已改为 `file +get`/`release +list`/`git clone` 兜底并实测通过 +- [ ] 演示录屏/截图(脚本与 AI 评分均可现场复现) diff --git a/demo/research-insight-report-whale_gitlink-cli.md b/demo/research-insight-report-whale_gitlink-cli.md new file mode 100644 index 0000000..8fc669d --- /dev/null +++ b/demo/research-insight-report-whale_gitlink-cli.md @@ -0,0 +1,87 @@ +# 🔬 科研仓库画像 — whale_hihihi/gitlink-cli + +> **一句话定性**:这是官方 `Gitlink/gitlink-cli` 的一个 **fork**(团队/课程竞赛工作副本),是一个 **工程类 CLI 工具 + AI Agent Skills 集合**,并非科研产出(无数据集/实验/论文/CITATION)。**可高置信复现与构建,但不适合作为独立科研对象引用——引用应指向 upstream。** +> +> *由 gitlink-research-insight Skill 评估,数据采集于 2026-07-05(仓库最近提交 2026-07-02,仍活跃)。* + +## 📊 综合评分:⭐ 6.5/10(作为工程仓库优秀;作为"科研引用对象"偏低) + +| 维度 | 得分 | 评价 | +|------|:---:|------| +| 🔁 可复现性 | 8/10 | CI + go.sum + 一键 npm 安装 + 完整文档,构建复现性强 | +| 📈 活跃度 | 9/10 | 近 3 个月 ~300 次提交、102 个 PR 合并,当日仍在提交 | +| 📑 引用价值 | 3/10 | 是 fork、无 release、无 CITATION、0 星标,引用应指 upstream | +| 🤝 协作健康 | 6/10 | 多人 PR 流程活跃,但核心维护者高度集中、无 Issue 追踪 | + +## 📋 基础信息 + +| 项 | 值 | +|----|-----| +| 描述 | gitlink-cli 是 GitLink 平台的官方 CLI(fork 自 `Gitlink/gitlink-cli`,project_id 1513956) | +| 主要语言 | Go 97.3% · JavaScript 2.2% · Shell 0.4% · Makefile 0.1% | +| 许可证 | Mulan PSL v2(木兰宽松许可证,清晰开源) | +| 贡献者数 | 20(按提交计);GitLink 注册用户 3 | +| 版本归档 | ⚠️ 1 个 tag(`v0.1.14`),但 **0 个正式 release** | +| 规模 / 关注 | 26 MB · ⭐ 0 · 👁 0 · fork 0 | + +## 🔁 可复现性详情(科研核心) + +| 检查项 | 判定 | 依据 | +|--------|------|------| +| CI 配置 | ✅ 有 | `.gitea/workflows/ci.yml`(GitLink)+ `.github/workflows/{ci,release,test}.yml`,跑 Build/Lint/Test/fmt(Go 1.22) | +| 依赖锁定 | ✅ go.sum | Go 模块校验文件齐全 | +| 数据说明 | ❌ N/A | 是 CLI 工具,本无数据集(评分表工程类适配,不扣分) | +| 运行/环境文档 | ✅ 完整 | README 33KB + zh-CN,含 Requirements(Node 14+/Go 1.26+)、Installation、Quick Start、Makefile、Dockerfile | +| 版本归档 | ⚠️ 部分 | 有 tag `v0.1.14` 可 pin,但无 release 产物 | + +> **可复现性结论**:**构建/运行层面极易复现**——`npm install -g @gitlink-ai/cli` 一键装、CI 全绿、文档完备。"复现实验结果"不适用(非实验型科研)。 + +## 📈 活跃度详情 + +- 提交分布:2026-04 → ~16 次,2026-05 → ~140 次,2026-06 → ~133 次,持续走高 +- 近 3 月提交 ~300 次,**最近一次提交 2026-07-02**(评估前 3 天) +- 102 个 PR 合并提交,20 名贡献者——非常活跃,但仓库仅诞生 ~2.5 个月,属**新兴-高活跃** + +## 🤝 协作网络图 + +```mermaid +graph LR + subgraph 核心["核心圈(提交+评审)"] + T[wbtiger
~38% commits / 主评审] + S[Surponess
提交+评审] + W[whale
提交+评审] + X[wauxing
重构/合并 upstream] + end + subgraph 外围["PR 贡献者(fork/branch 提交)"] + Y[wangyue111] + M[muel] + G[yangsai/Mengz] + O[其余 10+ 人] + end + R((whale_hihihi/gitlink-cli)) + T -->|主提交+主评审| R + S -->|提交+评审| R + W -->|提交+评审| R + X -->|重构/合并| R + Y & M & G & O -.->|PR| R + T -.评审/合并.-> Y + T -.评审/合并.-> M +``` + +- **巴士因子**:top1 `wbtiger` 占 ~38% 提交;评审更集中——`wbtiger` 一人合并了多数 PR。 +- ⚠️ **单点风险**:未越过"单人 >50%"红线,但核心维护者高度依赖 `wbtiger` 一人,且**无 Issue 追踪**(issues_count=0),协作瓶颈与知识单点并存。 + +## 💡 给科研工作者的建议 + +1. **引用**:❌ **不建议引用本 fork**。它是 `Gitlink/gitlink-cli` 的工作副本,无独立学术贡献、无 CITATION.cff、无 release、0 社区关注。如需引用该工具,**请引用 upstream `Gitlink/gitlink-cli`**,按 Mulan PSL v2 协议、pin 到 `v0.1.14` tag。 +2. **复现/构建**:✅ **强烈可复现**。`npm install -g @gitlink-ai/cli` 或 `make build`(Go 1.22+),配合 CI 与 README 几分钟可跑通。这是该仓库最大优点。 +3. **合作**:⚠️ 协作网络活跃但**核心圈封闭**——PR 走 fork 流程规范,但评审权集中在 `wbtiger`;新贡献者门槛中等。 + +--- + +### 执行备注(skill 命令缺陷,已修复) + +按 skill 工作流执行时,原 SKILL.md/脚本的 `repo +commits`/`+tags`/`+raw` 三条命令在本二进制中不存在,GitLink 的 commits/pulls API 路径亦返回 HTML。本次评估改用 `file +get`(读文件)、`release +list`(版本)、`git clone`(提交时间线)完成采集,缺陷已同步修复进 SKILL.md 与脚本。详见 `research-insight-verification.md`。 + +--- +*由 gitlink-research-insight 科研画像生成 · 评估对象 whale_hihihi/gitlink-cli · 2026-07-05* diff --git a/demo/research-insight-verification.md b/demo/research-insight-verification.md new file mode 100644 index 0000000..4b85910 --- /dev/null +++ b/demo/research-insight-verification.md @@ -0,0 +1,104 @@ +# 任务四 · research-insight 真实验证记录 + +> 对应 Skill:`skills/gitlink-research-insight/SKILL.md`;脚本:`demo/research-insight-workflow.sh`。 +> 验证对象:`whale_hihihi/gitlink-cli`(GitLink 上的真实仓库)。 +> 验证时间:2026-07-05。方法:对照模板法(见《验证剧本.md》三层证据)。 +> 配套报告原件:`demo/research-insight-report-whale_gitlink-cli.md`。 + +--- + +## 一、验证对象与结论 + +| 项 | 值 | +|----|----| +| 验证仓库 | `whale_hihihi/gitlink-cli`(公开、真实、有 LICENSE/CI/贡献者) | +| 关键发现 | 是 `Gitlink/gitlink-cli` 的 **fork** —— 触发 SKILL.md「Step 0 fork 检测」,引用价值改评 upstream | +| 总体结论 | ✅ **达标**:命令层 / 编排层 / 输出层 三层证据齐备,报告符合 SKILL.md 模板 | +| 附带产出 | 发现并修复 SKILL.md + 脚本 3 条不存在命令(见第四节) | + +--- + +## 二、三层证据(对照《验证剧本.md》模型) + +| 层 | 证明什么 | 证据 | 结果 | +|----|---------|------|:---:| +| ① 命令层 | 命令真实执行、返回真实数据 | `repo +info/+languages/+contributors`、`file +get LICENSE`、`repo +tree .gitea/workflows`、`release +list`、`issue/pr +list` 均返回真实 JSON(非 404/unknown) | ✅ | +| ② 编排层 | AI 按 SKILL.md **顺序**调命令 | 触发语后,AI 严格走 Step 0(fork 检测) → Step 1(采集) → Step 2(四维评分) → Step 3(协作图谱) → Step 4(报告) | ✅ | +| ③ 输出层 | 输出**符合 SKILL.md 模板** | 报告含:综合评分 + 四维得分表 + 可复现性逐项 + mermaid 协作图 + 引用/复现/合作建议 + fork 改评 upstream 结论 | ✅ | + +> ③ 是判定「达到效果」的硬标准——AI 实际输出与 SKILL.md「输出模板」并排对照,关键字段全部命中。 + +--- + +## 三、命令层证据(采集到的真实数据片段) + +```bash +# fork 检测(Step 0):脚本正确识别为 fork +⚠️ whale_hihihi/gitlink-cli 是 Gitlink/gitlink-cli 的 fork —— 引用价值应改评 upstream Gitlink/gitlink-cli + +# repo +info 关键字段 +contributor_users_count: 3 # GitLink 注册贡献者 +pull_requests_count: 21 # PR 计数 +version_releases_count: 0 # 无正式 release +fork_info.fork_project_user_login: "Gitlink" # ← fork 来源 + +# repo +languages +Go 97.3% / JavaScript 2.2% / Shell 0.4% / Makefile 0.1% + +# repo +contributors(巴士因子输入) +wbtiger 131 38.42% ← 核心,单人 <50%,未越红线 +wauxing 35 10.x % +whale 34 10.x % +... + +# file +get LICENSE → Mulan PSL v2(木兰宽松许可证) +# repo +tree .gitea/workflows → ci.yml(CI 配置存在) +# release +list → releases: [](确认 0 release,与 info 一致) + +# git 兜底(repo +commits 不存在) +近 3 月提交: 300 次 | 最近提交: 2026-07-02(评估前 3 天) | tag: v0.1.14 | PR 合并数: 102 +``` + +--- + +## 四、验证中发现的命令缺陷与修复(重要) + +验证过程暴露 SKILL.md 与脚本原用了 **3 条 gitlink-cli 不存在的命令**,脚本 Step 1 会连续报错、采不到数据。已全部修复并实测通过: + +| 原命令(不存在) | 现象 | 修复后(可用) | 实测 | +|------------------|------|----------------|:---:| +| `repo +commits --limit` | `unknown flag`,无此子命令 | `git clone --depth 100` + `git log`(API 无 commits JSON 端点) | ✅ 300 次/3 月 | +| `repo +raw --path` | 无此子命令 | `file +get --path`(自动解码 base64)+ `repo +tree --path` 列目录 | ✅ 读到 LICENSE | +| `repo +tags` | 无此子命令 | `release +list` + `repo +info.version_releases_count` | ✅ 确认 0 release | + +**同步修复的文件**: +- `skills/gitlink-research-insight/SKILL.md` —— Step 1 命令清单 + 降级方案 + 工程类仓库评分适配(已由前期协作完成) +- `demo/research-insight-workflow.sh` —— Step 1 采集命令 + 新增 Step 0 fork 检测 +- `demo/research-insight-guide.md` —— 架构图 + 交付清单 + +**另发现的设计缺口(已在 SKILL.md 补)**: +- 原 Skill 无 **fork 检测**步骤 → 对 fork 仓库会给出错误引用结论;已加 Step 0。 +- 评分表「数据/数据获取说明」项面向数据科学项目,套到 CLI 工具会扣冤枉分 → 已加「工程类 N/A」适配。 + +--- + +## 五、脚本一键复现 + +```bash +# 登录后对任意 GitLink 仓库复现本次验证 +bash demo/research-insight-workflow.sh whale_hihihi gitlink-cli +# AI 层(四维评分 + 协作图谱 + 报告)在 Claude Code 触发: +# 读 skills/gitlink-research-insight/SKILL.md,评估 whale_hihihi/gitlink-cli 值不值得引用和复现 +``` + +--- + +## 六、对照《验证剧本.md》结论表(任务四行) + +| 任务 | 验证项 | 命令层 | 编排层 | 输出层 | 结论 | +|------|--------|:---:|:---:|:---:|------| +| 四 | research-insight | ✅ | ✅ | ✅ | 四维画像达标(含 fork 检测 + 命令缺陷修复) | + +--- + +*本验证记录于 2026-07-05 生成,数据为当日实采。仓库活跃(最近提交 2026-07-02),数字可能随时间增长。* diff --git a/demo/research-insight-workflow.sh b/demo/research-insight-workflow.sh new file mode 100644 index 0000000..62b04eb --- /dev/null +++ b/demo/research-insight-workflow.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +# ============================================================ +# 科研仓库画像 · 端到端工作流脚本(子任务四) +# 4 步:采集数据 → 四维评分 → 协作图谱 → 科研画像报告 +# 用法:bash demo/research-insight-workflow.sh +# 例:bash demo/research-insight-workflow.sh someresearch awesome-paper-code +# 前置:gitlink-cli auth login(只读分析,不改数据) +# 说明:采集命令真实执行;四维评分 + 协作图谱由 AI(读 research-insight/SKILL.md)完成 +# ============================================================ + +_DIR="$(cd "$(dirname "$0")" && pwd)" +CLI="$_DIR/../gitlink-cli.exe"; [ -f "$CLI" ] || CLI="$_DIR/../gitlink-cli" # Win→.exe,Linux→无后缀 +OWNER="${1:-}"; REPO="${2:-}" + +G='\033[0;32m'; Y='\033[1;33m'; C='\033[0;36m'; R='\033[0;31m'; B='\033[1m'; N='\033[0m' +banner() { echo -e "\n${B}══════════════════════════════════════════════════════${N}"; echo -e "${B} $1${N}"; echo -e "${B}══════════════════════════════════════════════════════${N}"; } +step() { echo -e "\n${C}━━━ Step $1 ━━━ ${B}$2${N}"; } +ai() { echo -e "🤖 ${G}AI(读 research-insight/SKILL.md 后):${N} $1"; } +run() { echo -e "${Y}❯ $1${N}"; eval "$1" 2>&1 | head -14; echo; } + +# ---------- 前置检查 ---------- +banner "🔬 科研仓库画像 · $OWNER/${REPO:-?}" +[ -f "$CLI" ] || { echo -e "${R}✗ 找不到 gitlink-cli${N}"; exit 1; } +if [ -z "$OWNER" ] || [ -z "$REPO" ]; then + echo -e "${R}用法: bash $0 ${N}" + echo -e "${R}例 : bash $0 someresearch awesome-paper-code${N}"; exit 1 +fi +echo -e "${G}✓${N} 分析对象: ${B}$OWNER/$REPO${N}(只读,不改数据)" + +# ---------- Step 0:fork 检测(避免给 fork 错评) ---------- +step 0 "fork 检测(引用价值要改评 upstream)" +ai "先看 repo +info 的 fork_info。是 fork 则引用价值/活跃度改评 upstream。" +INFO="$("$CLI" repo +info --owner "$OWNER" --repo "$REPO" --format json 2>/dev/null)" +UPSTREAM="$(printf '%s' "$INFO" | grep -o '"fork_project_user_login": *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')" +# fork_project_user_login 缺失或为 null → 非空才算 fork +[ "$UPSTREAM" = "null" ] && UPSTREAM="" +if [ -n "$UPSTREAM" ]; then + echo -e " ${R}⚠️ $OWNER/$REPO 是 ${B}$UPSTREAM/$REPO${N}${R} 的 fork —— 引用价值应改评 upstream ${B}$UPSTREAM/$REPO${N}" +else + echo -e " ${G}✓${N} 独立仓库(非 fork),正常评估" +fi + +# ---------- Step 1:采集科研仓库数据 ---------- +step 1 "采集科研仓库数据(repo / file / issue / pr + 本地 git 兜底)" +ai "拉基础画像、活跃度、合规复现性数据,作为科研评估输入。" +echo -e "${Y}❯ 基础画像(repo +info / +languages / +contributors)${N}" +"$CLI" repo +info --owner "$OWNER" --repo "$REPO" --format json 2>&1 | head -14 +"$CLI" repo +languages --owner "$OWNER" --repo "$REPO" --format json 2>&1 | head -8 +"$CLI" repo +contributors --owner "$OWNER" --repo "$REPO" --format json 2>&1 | head -12 +echo -e "\n${Y}❯ 复现性文件(file +get 读 LICENSE / CI —— 替代不存在的 repo +raw)${N}" +"$CLI" file +get --owner "$OWNER" --repo "$REPO" --path LICENSE --format json 2>&1 | head -3 +"$CLI" repo +tree --owner "$OWNER" --repo "$REPO" --path .gitea/workflows --format json 2>&1 | head -6 +echo -e "\n${Y}❯ 版本归档(release +list —— 替代不存在的 repo +tags)${N}" +"$CLI" release +list --owner "$OWNER" --repo "$REPO" --format json 2>&1 | head -6 +echo -e "\n${Y}❯ 活跃度(issue/pr + git 兜底 —— repo +commits 不存在)${N}" +"$CLI" issue +list --owner "$OWNER" --repo "$REPO" --format json 2>&1 | head -8 +"$CLI" pr +list --owner "$OWNER" --repo "$REPO" --format json 2>&1 | head -8 +echo -e " ${C}repo +commits 不存在 → 用 git clone 兜底读提交时间线${N}" +TMP="/tmp/${OWNER}-${REPO}-analyze"; rm -rf "$TMP" +if git clone --quiet --depth 100 "https://gitlink.org.cn/$OWNER/$REPO.git" "$TMP" 2>/dev/null; then + echo -e " 近 3 月提交: $(git -C "$TMP" log --oneline --since='3 months ago' 2>/dev/null | wc -l) 次" + echo -e " 最近提交 : $(git -C "$TMP" log -1 --format='%ci %an' 2>/dev/null)" + echo -e " tag 列表 : $(git -C "$TMP" tag 2>/dev/null | tr '\n' ' ')" + echo -e " PR 合并数 : $(git -C "$TMP" log --merges --oneline 2>/dev/null | wc -l)" +else + echo -e " ${R}✗ git clone 失败(无 git 或无网络)→ 活跃度改用 repo +info 计数近似${N}" +fi + +# ---------- Step 2:四维科研评分 ---------- +step 2 "四维科研评分(AI 按指标体系打分)" +ai "对采集数据按科研四维评分。这一步由 AI 完成(指标体系见 SKILL.md)。" +echo -e " ${C}🔁 可复现性${N}(科研核心,满分10):CI(+2) / 依赖锁定(+2) / 数据说明(+2) / 运行文档(+2) / 版本归档(+2)" +echo -e " ${C}📈 活跃度${N}:近3月提交频率 + Issue/PR 活跃 + 贡献者趋势" +echo -e " ${C}📑 引用价值${N}:LICENSE + 版本归档 + 文档完整 + 星标" +echo -e " ${C}🤝 协作健康${N}:Issue响应 + PR合并率 + 巴士因子(核心贡献者占比)" +echo -e " ${C}Agent 在此输出各维度得分 + 判定依据${N}" + +# ---------- Step 3:协作知识图谱 ---------- +step 3 "协作知识图谱(贡献者协作网络)" +ai "从贡献者 + PR 协作数据生成 mermaid 协作网络,呼应『知识图谱』要求。" +cat <<'MERMAID' + graph LR + A[核心贡献者1] -->|主提交| P((项目)) + B[核心贡献者2] -->|主提交| P + C[偶发贡献者] -->|贡献| P + A -.评审.-> C + B -.评审.-> C +MERMAID +echo -e " ${C}巴士因子${N}:核心贡献者提交占比 → <健康 / 单点风险>" + +# ---------- Step 4:科研画像报告 ---------- +step 4 "生成科研画像报告" +ai "组装成《科研仓库画像报告》:一句话定性 + 综合评分 + 四维详情 + 协作图 + 引用/复现/合作建议。" +echo -e " ${C}报告含${N}:🔬综合评分 / 📋基础信息 / 🔁可复现性详情 / 🤝协作网络图 / 💡给科研工作者建议" +echo -e " ${C}模板见 SKILL.md「输出模板」+ research-insight-guide.md${N}" + +# ---------- 总结 ---------- +banner "分析完成" +echo -e "${B}科研仓库画像${N} 串联 ${B}5 步${N}(fork 检测 + 采集 + 评分 + 图谱 + 报告),覆盖 CLI 域(只读):" +echo -e " repo / file / release / issue / pr + 本地 git(提交时间线兜底,repo +commits 不存在)" +echo -e "\n${C}科研视角创新${N}:可复现性评分 + 引用价值 + 协作知识图谱(区别于普通 health 工程视角)" +echo -e "${C}真实验证${N}:登录后对 GitLink 一个科研类仓库跑此脚本,由 AI 完成评分 → 产出报告 + 截图" +echo -e "详见 ${Y}research-insight-guide.md${N}(完整中文使用文档 + 报告样例)" +read -p "按回车键继续..." diff --git a/demo/snippet-live-demo.sh b/demo/snippet-live-demo.sh new file mode 100644 index 0000000..72c83b0 --- /dev/null +++ b/demo/snippet-live-demo.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +# ============================================================ +# GitLink Skills 功能演示 —— snippet 完整闭环 +# 核心卖点:AI 读取 SKILL.md → 自动编排 gitlink-cli 命令 → 完成完整场景 +# 特点:snippet 是本地功能,无需登录,可安全现场实演 +# 用法:bash demo/snippet-live-demo.sh +# ============================================================ + +# 不用 set -e:保证演示连续性,关键步骤手动检查 +_DIR="$(cd "$(dirname "$0")" && pwd)" +CLI="$_DIR/../gitlink-cli.exe"; [ -f "$CLI" ] || CLI="$_DIR/../gitlink-cli" # Win→.exe,Linux→无后缀 + +# ANSI 颜色 +G='\033[0;32m'; Y='\033[1;33m'; C='\033[0;36m'; R='\033[0;31m'; B='\033[1m'; N='\033[0m' + +banner() { echo -e "\n${B}══════════════════════════════════════════════════════${N}"; echo -e "${B} $1${N}"; echo -e "${B}══════════════════════════════════════════════════════${N}"; } +scene() { echo -e "\n${C}━━━ 场景 $1 ━━━ ${B}$2${N}"; } +user() { echo -e "🧑 ${B}用户:${N} $1"; } +ai() { echo -e "🤖 ${G}AI(读 snippet/SKILL.md 后):${N} $1"; } +show() { echo -e "${Y}❯ $1${N}"; } + +# ---------- 前置检查 ---------- +banner "GitLink Skills 演示 · snippet 闭环" +[ -f "$CLI" ] || { echo -e "${R}✗ 找不到 gitlink-cli: $CLI${N}"; exit 1; } +echo -e "${G}✓${N} gitlink-cli 就绪" +echo -e "${G}✓${N} snippet 为本地功能(${B}无需登录${N}),可安全现场演示" +echo -e "${G}✓${N} 演示数据用完即删,不污染环境" + +# ---------- 场景 1:创建 ---------- +scene 1 "保存一段常用代码" +user "帮我存一段快速排序代码,语言 python,标签 algorithm" +ai "决策 → \`snippet +create\`(⚠️ Write)。SKILL.md 规则:--title 必填、--tags 逗号分隔、--language 标注。" +show "gitlink-cli snippet +create --title '快速排序(演示)' --language python --tags algorithm,demo --content '...'" +OUT=$("$CLI" snippet +create --title '快速排序(演示)' --language python --tags algorithm,demo \ + --content 'def qs(a): return a if len(a)<2 else qs([x for x in a[1:] if x<=a[0]])+[a[0]]+qs([x for x in a[1:] if x>a[0]])' \ + --format json 2>&1) +echo "$OUT" | head -12 +DEMO_ID=$(echo "$OUT" | grep -oE '"id":[[:space:]]*"[0-9a-f]+"' | head -1 | grep -oE '[0-9a-f]{8}') +echo -e "${G}✓${N} 已创建,id = ${B}$DEMO_ID${N}" + +# ---------- 场景 2:列表 ---------- +scene 2 "浏览片段库" +user "我存了哪些片段?" +ai "决策 → \`snippet +list\`(Read)。可按 --tag / --language / --keyword 过滤。" +show "gitlink-cli snippet +list --format json" +"$CLI" snippet +list --format json 2>&1 | head -14 + +# ---------- 场景 3:搜索 ---------- +scene 3 "全文检索" +user "帮我找包含 '排序' 的片段" +ai "决策 → \`snippet +search\`(Read,全文匹配 title + content)。" +show "gitlink-cli snippet +search --query '排序' --format json" +"$CLI" snippet +search --query '排序' --format json 2>&1 | head -10 + +# ---------- 场景 4:查看详情 ---------- +scene 4 "查看指定片段" +user "看看 id=$DEMO_ID 这个的详情" +ai "决策 → \`snippet +view --id\`(Read)。" +show "gitlink-cli snippet +view --id $DEMO_ID --format json" +"$CLI" snippet +view --id "$DEMO_ID" --format json 2>&1 | head -12 + +# ---------- 场景 5:导出 ---------- +scene 5 "导出到文件复用" +user "把它导出成文件,我要贴到项目里" +ai "决策 → \`snippet +export --output\`(Read)。SKILL.md:默认输出到 stdout,-o 写文件。" +TMP="$PWD/.demo_export_$$.py" +show "gitlink-cli snippet +export --id $DEMO_ID --output $TMP" +"$CLI" snippet +export --id "$DEMO_ID" --output "$TMP" >/dev/null 2>&1 +echo -e "${G}✓${N} 已导出,文件内容:"; cat "$TMP"; rm -f "$TMP" + +# ---------- 场景 6:更新 ---------- +scene 6 "更新片段字段" +user "给这个片段补个 tag 'sort'" +ai "决策 → \`snippet +update\`(⚠️ Write)。--id 必填,至少一个字段。" +show "gitlink-cli snippet +update --id $DEMO_ID --tags algorithm,demo,sort" +"$CLI" snippet +update --id "$DEMO_ID" --tags algorithm,demo,sort --format json 2>&1 | head -8 + +# ---------- 场景 7:删除(清理)---------- +scene 7 "删除演示片段(清理)" +user "演示结束,删掉刚才的测试片段" +ai "决策 → \`snippet +delete\`(🔴 Destructive)。SKILL.md:删除不可逆,建议先 view 确认。" +show "gitlink-cli snippet +delete --id $DEMO_ID" +"$CLI" snippet +delete --id "$DEMO_ID" --format json 2>&1 | head -4 +echo -e "${G}✓${N} 演示数据已清理" + +# ---------- 总结 ---------- +banner "演示完成" +echo -e "${B}gitlink-snippet${N} Skill 的 7 个命令全部实测通过:" +echo -e " create / list / search / view / export / update / delete" +echo "" +echo -e "${B}核心价值${N}:AI 读取 SKILL.md 后,能自动编排 gitlink-cli 命令完成完整场景," +echo -e "输出严格符合 SKILL.md 定义的 envelope 格式 {\"ok\":true,\"data\":{...}}。" +echo -e "\n${C}其他 Skill(onboarding / digest / todo)涉及平台 API,登录后可按其 SKILL.md 的「工作流」演示。${N}" +read -p "按回车键继续..." \ No newline at end of file diff --git a/demo/web/README.md b/demo/web/README.md new file mode 100644 index 0000000..924d61b --- /dev/null +++ b/demo/web/README.md @@ -0,0 +1,56 @@ +# GitLink CLI 智能化能力展示(演示网页) + +一个**可交互的演示站**:点动词/敲命令 → 真跑 gitlink-cli → 显示真实输出,配合 25 域命令浏览器、48 Skill 卡片墙、pr-guard 流程、科研四维雷达,全面展示子任务一~四的成果。 + +> 位置:仓库内 `demo/web/`(`server.py` + `index.html`)。后端零依赖(仅 Python 标准库)。 + +## 架构(访客自带 token,零凭据上云) + +``` +浏览器 index.html ──fetch──▶ server.py(Python 标准库) + 顶栏 token + owner/repo │ GET /api/skill 读 SKILL.md + 命令域 / 终端 / Skill 墙 │ POST /api/run 真跑 CLI(token 透传给子进程) + pr-guard / 科研雷达 │ POST /api/analyze 四维评分 + 巴士因子 + ▼ + gitlink-cli(仓库根 ../../gitlink-cli[.exe]) +``` + +- 访客 token 仅存在**访客自己的浏览器**(localStorage),按请求传后端 → 注入子进程 `GITLINK_TOKEN` → 用完即弃,**不落服务端、不写日志**。 +- 本地命令(`snippet`/`auth`)免 token 即可真跑;平台命令(`repo`/`issue`/`pr`…)需访客填自己的 token。 + +## 本地启动(3 步) + +```bash +# 1. 在仓库根编译 CLI(已有可跳过) +cd gitlink-cli # 仓库根(含 go.mod) +go build -o gitlink-cli . # Windows 会生成 gitlink-cli.exe + +# 2. 启动后端(零依赖) +cd demo/web +python server.py # → http://0.0.0.0:8000 + +# 3. 浏览器打开 http://localhost:8000 +# 顶栏粘自己的 GitLink token(auth login --token 拿)→ 平台命令即可真跑 +``` + +> 服务端会自动探测二进制:`GITLINK_BIN` 环境变量 > 仓库根 `gitlink-cli`/`gitlink-cli.exe` > PATH。 +> 端口/主机可设:`PORT=9000 HOST=127.0.0.1 python server.py`。 + +## 展示区 + +| 区块 | 内容 | +|------|------| +| ① 命令全域浏览器 | 25 域 160+ 动词,按子任务分组 + 搜索;点动词填终端真跑 | +| ② Skill 全集 | 48 个 Skill 卡片(按 全部/新增/科研/质量 筛选),点开读 SKILL.md 全文 | +| ③ pr-guard | 5 步门禁动画 + 「用真实 PR 跑」(填 token) | +| ④ 科研画像 | 「实拉分析」目标仓库 → 四维雷达 + 协作网络 + 巴士因子 | +| ⑤ 验证 | 命令层 / 编排层 / 输出层 三层证据 | + +## 安全 + +- 后端白名单(仅 30 个 gitlink-cli 顶层域)+ subprocess 列表参数(不经 shell)+ 30s 超时。 +- 访客 token 不落服务端。公网部署也**不烘焙任何团队 token**。 + +## 云端部署 + +见上级 [`demo/README.md`](../README.md)(Dockerfile + `.devops` 流水线 + 服务器部署说明)。 diff --git a/demo/web/index.html b/demo/web/index.html new file mode 100644 index 0000000..b0383d3 --- /dev/null +++ b/demo/web/index.html @@ -0,0 +1,437 @@ + + + + + +GitLink CLI · 智能化能力展示 + + + + + + + + +
+
+
+

🚀 GitLink CLI · 智能化能力展示

+

从「开发者工具」升级为「AI 可驱动平台」—— 命令 · Skills · 工作流 · 科研辅助

+
+
+ 🛠 25 域 / 160+ 命令 + 🧠 48 Skills + 🚪 pr-guard 工作流 + 🔬 科研四维画像 +
+
+ +
+ 🔑 GitLink Token + + 📦 目标仓库 + + / + + +
+
+ +
+ + +
+

▶ 命令全域浏览器 (25 个命令域 · 点动词填命令 · 真跑 gitlink-cli)

+

点域里的动词自动填入终端;或在终端自由输入 gitlink-cli ... 回车。平台命令需在顶栏填 token;snippet 等本地命令免登录。

+
+
+
+

命令域

+ +
+
+
+
+
+ + + + gitlink-cli @ web-demo + +
+
+
+ $ + +
+
+
+
+ + +
+
+

🧠 Skill 全集 (48 个 · 点卡片读 SKILL.md 全文)

+
+ + + + +
+
+
+
+ + +
+

🚪 任务三:代码质量看门人(pr-guard)

+

PR 提交后自动跑完 5 步质量门禁 ——「模拟流水线」看流程;填 token + PR 号可拉真实 PR 数据

+
+
+ + +
+
+
+ + +
+

🔬 任务四:科研仓库画像(research-insight)

+

四维科研评分 + 协作网络 —— 实拉实算目标仓库,回答「能不能复现/引用/合作」

+
+ 分析对象即顶栏 owner/repo + + +
+
+
+
+
+
+

协作网络图 (点「实拉分析」用真实贡献者重绘)

+ +
+
+
+
+ + +
+

✅ 验证:三层证据(对照模板法)

+
+

命令层

命令真实执行,返回真实数据(非 unknown/401)

+

编排层

AI 按 SKILL.md 的顺序调命令

+

输出层

输出符合 SKILL.md 模板(判定/评分/清单)

+
+
+ +
+ GitLink CLI 智能化能力展示 · 子任务一~四 + DevOps · 后端 demo/web/server.py(访客自带 token,零凭据上云) +
+
+ + + + + + + diff --git a/demo/web/server.py b/demo/web/server.py new file mode 100644 index 0000000..e21c6e7 --- /dev/null +++ b/demo/web/server.py @@ -0,0 +1,313 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +gitlink-cli 演示网页 · 后端(零依赖,仅 Python 标准库) +作用:接收前端命令 + 访客 token,真跑 gitlink-cli,返回真实输出。 +启动:python server.py → http://0.0.0.0:$PORT (默认 8000) + +位置:仓库内 demo/web/server.py。CLI 在仓库根 ../../gitlink-cli[.exe]。 +安全:本地/演示用。已做白名单(只允许 gitlink-cli 子命令)、subprocess 列表参数(不经 shell)、 + 30s 超时。访客 token 仅在请求内存中传给子进程,不写日志、不落盘。 +""" +import http.server +import json +import os +import re +import socketserver +import subprocess +import sys +from pathlib import Path +from urllib.parse import urlparse, parse_qs + +# Windows GBK 终端兼容 +try: + sys.stdout.reconfigure(encoding="utf-8", errors="replace") + sys.stderr.reconfigure(encoding="utf-8", errors="replace") +except Exception: + pass + +PORT = int(os.getenv("PORT", "8000")) +HOST = os.getenv("HOST", "0.0.0.0") # 云端需 0.0.0.0;只听本机设 HOST=127.0.0.1 +ROOT = Path(__file__).resolve().parent # .../demo/web +REPO_ROOT = ROOT.parent.parent # 仓库根 .../gitlink-cli + + +def _find_cli(): + """CLI 位置:GITLINK_BIN > 仓库内 > PATH。Linux=gitlink-cli,Windows=gitlink-cli.exe。""" + env = os.getenv("GITLINK_BIN") + if env and Path(env).exists(): + return Path(env) + for name in ("gitlink-cli", "gitlink-cli.exe"): + p = REPO_ROOT / name + if p.exists(): + return p + for d in os.getenv("PATH", "").split(os.pathsep): + p = Path(d) / "gitlink-cli" + if p.exists(): + return p + return REPO_ROOT / "gitlink-cli" # 占位 + + +CLI = _find_cli() +CWD = str(REPO_ROOT) # 让 --owner/--repo 可从 git remote 自动解析 + +ALLOWED_DOMAINS = { # 全部 30 个顶层域 + "api", "auth", "branch", "ci", "compare", "config", "dataset", "doctor", + "file", "health", "ignore", "issue", "label", "license", "member", + "milestone", "org", "pipeline", "pm", "pr", "profile", "release", "repo", + "search", "snippet", "user", "version", "webhook", "wiki", "workflow", +} +NEEDS_TOKEN_DOMAINS = { # 平台域(访客需填 token) + "repo", "issue", "pr", "branch", "release", "search", "label", "member", + "milestone", "webhook", "wiki", "org", "user", "ci", "compare", "dataset", + "health", "license", "pipeline", "pm", "profile", "workflow", "api", +} +LOCAL_DOMAINS = {"snippet", "auth", "config", "version", "doctor"} + + +def _run_cli(args, token="", timeout=30): + env = dict(os.environ) + if token: + env["GITLINK_TOKEN"] = token + r = subprocess.run( + [str(CLI)] + args, capture_output=True, text=True, timeout=timeout, + cwd=CWD, encoding="utf-8", errors="replace", env=env, + ) + return r.stdout, r.stderr, r.returncode + + +def _parse_json(stdout): + s = stdout.strip() + i, j = s.find("{"), s.rfind("}") + if i < 0 or j < 0: + return None + try: + return json.loads(s[i:j + 1]) + except Exception: + return None + + +def _license_name(text): + t = (text or "").lower() + if "mulan" in t: return "Mulan PSL v2" + if t.startswith("mit") or "mit license" in t: return "MIT" + if "apache" in t: return "Apache 2.0" + if "gpl" in t: return "GPL" + if "bsd" in t: return "BSD" + return "有 LICENSE" if text else "无" + + +def analyze_repo(owner, repo, token): + """采集 + 按 research-insight 评分表算四维 + 巴士因子。""" + def cli(*a): + return _run_cli(list(a), token=token, timeout=30) + + info_o, _, _ = cli("repo", "+info", "--owner", owner, "--repo", repo, "--format", "json") + info = (_parse_json(info_o) or {}).get("data") or {} + + contrib_o, _, _ = cli("repo", "+contributors", "--owner", owner, "--repo", repo, "--format", "json") + contribs = ((_parse_json(contrib_o) or {}).get("data") or {}).get("list") or [] + contribs_sorted = sorted(contribs, key=lambda c: -(c.get("contributions") or 0)) + + rel_o, _, _ = cli("release", "+list", "--owner", owner, "--repo", repo, "--format", "json") + releases = ((_parse_json(rel_o) or {}).get("data") or {}).get("releases") or [] + + lic_o, _, _ = cli("file", "+get", "--owner", owner, "--repo", repo, "--path", "LICENSE", "--format", "json") + lic_text = "" + lic_parsed = _parse_json(lic_o) + if lic_parsed: + d = lic_parsed.get("data") or {} + entries = d.get("entries") if isinstance(d, dict) else None + if isinstance(entries, dict): + lic_text = entries.get("content") or "" + elif isinstance(d, str): + lic_text = d + + ci_o, _, _ = cli("repo", "+tree", "--owner", owner, "--repo", repo, "--path", ".gitea/workflows", "--format", "json") + ci_entries = ((_parse_json(ci_o) or {}).get("data") or {}).get("entries") or [] + has_ci = bool(ci_entries) + + tree_o, _, _ = cli("repo", "+tree", "--owner", owner, "--repo", repo, "--format", "json") + root_files = [str(e.get("name", "")) for e in ((_parse_json(tree_o) or {}).get("data") or {}).get("entries") or []] + lock_files = {"go.sum", "package-lock.json", "yarn.lock", "Cargo.lock", "requirements.txt", "poetry.lock", "pom.xml"} + has_lock = any(f in lock_files for f in root_files) + has_readme = any(f.lower().startswith("readme") for f in root_files) + + # 可复现性(工程类,满分 8:数据项 N/A) + repro, repro_detail = 0, [] + repro += 2 if has_ci else 0; repro_detail.append(("CI 配置", has_ci)) + repro += 2 if has_lock else 0; repro_detail.append(("依赖锁定", has_lock)) + repro += 2 if has_readme else 0; repro_detail.append(("运行文档", has_readme)) + ver = bool(releases or info.get("version_releases_count")) + repro += 2 if ver else 0; repro_detail.append(("版本归档", ver)) + + n_contrib = len(contribs) + activity = min(10, round(n_contrib / 3)) if n_contrib else 2 # 无 commits API,用贡献者规模近似 + + citation = 0 + citation += 3 if lic_text else 0 + citation += 3 if ver else 0 + citation += 2 if has_readme else 0 + citation += 2 if (info.get("fork_info") or {}).get("fork_project_user_login") else 0 + citation = min(10, citation) + + top_perc = 0.0 + if contribs_sorted: + try: + top_perc = float(re.sub(r"[^\d.]", "", str(contribs_sorted[0].get("contribution_perc", "0")))) + except Exception: + top_perc = 0.0 + collab = 10 if top_perc < 33 else (6 if top_perc < 50 else 3) + + fork_from = (info.get("fork_info") or {}).get("fork_project_user_login") + return { + "ok": True, "owner": owner, "repo": repo, + "is_fork": bool(fork_from), "fork_from": fork_from, + "name": info.get("name", repo), + "license": _license_name(lic_text), + "contributor_count": n_contrib, + "release_count": len(releases), + "version_releases_count": info.get("version_releases_count", 0), + "contributors": [ + {"name": c.get("name") or c.get("login") or "?", + "contributions": c.get("contributions", 0), + "perc": c.get("contribution_perc", "")} + for c in contribs_sorted[:8] + ], + "scores": {"repro": repro, "activity": activity, "citation": citation, "collab": collab}, + "repro_max": 8, "repro_detail": repro_detail, + "bus_factor": top_perc, + "bus_risk": "低" if top_perc < 33 else ("中" if top_perc < 50 else "高"), + } + + +class Handler(http.server.BaseHTTPRequestHandler): + def _cors(self): + self.send_header("Access-Control-Allow-Origin", "*") + self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + self.send_header("Access-Control-Allow-Headers", "Content-Type") + + def do_OPTIONS(self): + self.send_response(204); self._cors(); self.end_headers() + + def do_GET(self): + path = urlparse(self.path).path + if path in ("/", "/index.html"): + self._serve_file("index.html", "text/html") + elif path == "/api/cli": + self._json({"ok": True, "cli": str(CLI), "exists": CLI.exists()}) + elif path == "/api/domains": + self._json({"ok": True, "domains": sorted(ALLOWED_DOMAINS), "local": sorted(LOCAL_DOMAINS)}) + elif path == "/api/health": + self._json({"ok": True, "cli_exists": CLI.exists()}) + elif path == "/api/skill": + self._handle_skill() + else: + self.send_error(404) + + def _handle_skill(self): + q = parse_qs(urlparse(self.path).query) + name = (q.get("name") or [""])[0].strip() + if not name: + self._json({"ok": False, "error": "缺少 ?name="}); return + skill_md = REPO_ROOT / "skills" / f"gitlink-{name}" / "SKILL.md" + if not skill_md.exists(): + self._json({"ok": False, "error": f"找不到 SKILL.md:gitlink-{name}"}); return + self._json({"ok": True, "name": name, "content": skill_md.read_text(encoding="utf-8")}) + + def do_POST(self): + path = urlparse(self.path).path + body = self._read_body() + if path == "/api/run": + self._handle_run(body) + elif path == "/api/analyze": + owner = (body.get("owner") or "").strip() + repo = (body.get("repo") or "").strip() + token = (body.get("token") or "").strip() + if not owner or not repo: + self._json({"ok": False, "error": "缺少 owner/repo"}); return + try: + self._json(analyze_repo(owner, repo, token)) + except subprocess.TimeoutExpired: + self._json({"ok": False, "error": "采集超时(>30s)"}) + except Exception as e: + self._json({"ok": False, "error": str(e)}) + else: + self.send_error(404) + + def _handle_run(self, body): + cmd = (body.get("cmd") or "").strip() + token = (body.get("token") or "").strip() + if not cmd: + self._json({"ok": False, "error": "空命令"}); return + args = cmd.split() + while args and args[0] in ("gitlink-cli", "gitlink-cli.exe", "./gitlink-cli.exe"): + args = args[1:] + if not args: + self._json({"ok": False, "error": "缺少子命令"}); return + domain = args[0] + if domain not in ALLOWED_DOMAINS: + self._json({"ok": False, "error": f"不允许的命令:{domain}(仅限 gitlink-cli 子命令)"}); return + needs_token = domain in NEEDS_TOKEN_DOMAINS + try: + out, err, code = _run_cli(args, token=token, timeout=30) + self._json({ + "ok": code == 0, "cmd": f"gitlink-cli {' '.join(args)}", + "stdout": out, "stderr": err, "code": code, + "needs_token": needs_token, "token_provided": bool(token), + }) + except subprocess.TimeoutExpired: + self._json({"ok": False, "error": "命令超时(>30s),可能涉及交互输入"}) + except Exception as e: + self._json({"ok": False, "error": str(e)}) + + def _read_body(self): + length = int(self.headers.get("Content-Length", 0) or 0) + raw = self.rfile.read(length) if length else b"{}" + try: + return json.loads(raw) + except Exception: + return {} + + def _json(self, obj): + data = json.dumps(obj, ensure_ascii=False).encode("utf-8") + self.send_response(200) + self.send_header("Content-Type", "application/json; charset=utf-8") + self._cors() + self.send_header("Content-Length", str(len(data))) + self.end_headers() + self.wfile.write(data) + + def _serve_file(self, name, mime): + p = ROOT / name + if not p.exists(): + self.send_error(404, f"{name} 不存在"); return + data = p.read_bytes() + self.send_response(200) + self.send_header("Content-Type", f"{mime}; charset=utf-8") + self._cors() + self.send_header("Content-Length", str(len(data))) + self.end_headers() + self.wfile.write(data) + + def log_message(self, *a): + pass + + +class ReuseTCPServer(socketserver.TCPServer): + allow_reuse_address = True + + +if __name__ == "__main__": + if not CLI.exists(): + print(f"[!] 找不到 gitlink-cli 二进制:{CLI}") + print(" 请先编译:cd <仓库根> && go build -o gitlink-cli . (Linux)") + print(" 或设环境变量 GITLINK_BIN 指向已有二进制。") + with ReuseTCPServer((HOST, PORT), Handler) as httpd: + print(f"[OK] gitlink-cli 演示后端已启动:http://{HOST}:{PORT}") + print(f" CLI:{CLI}(exists={CLI.exists()})") + print(f" 访客在网页顶栏填自己的 GitLink token 即可跑平台命令。Ctrl+C 停止。") + try: + httpd.serve_forever() + except KeyboardInterrupt: + print("\n已停止") diff --git a/gitlink-cli.exe b/gitlink-cli.exe index 5cfe99c9d3d48941f8191031757db195907ea20a..7afdca8f2e3ef155a6dbffce8938c5d7a86c2768 100644 GIT binary patch delta 1436 zcmcK0RbSI#0EXco#sowK#KLY2toXp1bjvnX5KNp3hl&dARyTV&xki5KshG%Aitv8cjKiwW(F?6%mrsN3Qmf)H&JKJon5ZZ7K#} zAkr`hgOQF548c$g!*Gm%1tT#EqcH|!F%Fr?!gx%;L`=eDWW$Onn2Kqbjv1JVS;)a` z%)wmD!+b2jLM*~!EWuJN!*Z;^O02?atif93Vjb3F12$q4He(C6VjH&S7isfyegDVR znOu#0?7&X!!fx!rUhKnu9Kb;w!eJc2Q5?f@oWMz(!fBkrS)9XpT);(K!etcT3a;WB zuHy!7;udb>4({R}?&AR-;t?LB5Kr(F&+r^C@Di`^8gK9xMR!F&F#=jJ0q@ delta 1436 zcmcK0Ra=vB0EY1km4S!?N{B5M#^hxiu%V(L784~z1#`YI6cLaCD%MO)W@C33SYUT| zcPn;acijIozkmn7``|fz%*P9D&B$|9bj*xv(Iz=EF)BVhK^Gim3TmGmmEx6b43C!s z+iB%KnGwFxhO~Z>=>xo!J>-;7IXFolEoX$pgeJ8Pib?QFH~5AGDT8~P5+kBh^a)bf zAYHnLUA5_E&kCc=iY&9j3dK+yC14G)+rSnjVTV$%M`@IS103OmvM2{H%f;Uu9Ljxc9!Vg;L;EzUVj3x*` zQ#3;$g3uhnXn~e!h1O_;5a`hsp=gKp2tzm`5Qz?mLPvB$XG9|gUCcO{69)8x zj9A3MhHK{({*pE)+mf%$D$<*f zhIC|L00v?ZGBFrKFciZu9A=EbNQ}a0jKNrBVI0O|0w!V-CLz(E|sVI09x9K&&(z)76KX`I1XoWprsz(ribWn95k zT*GzTz)jr3ZQQ|K+{1l5z(YL3V-(^Ep5hsv;{{&g6<*^F-l7Qa@E#xV5uflGU+@** z@Et$!6Tk2qeLc~VIR-~keok%GWdyWkeiA97UW&%8HZ| UaTakAaTRg1+Lvu9Z