Merge PR #408: 提交pr

# Conflicts:
#	.gitignore
#	.golangci.yml
#	Makefile
#	cmd/root.go
#	internal/client/client.go
#	shortcuts/_template/template.go
#	shortcuts/branch/branch_test.go
#	shortcuts/ci/ci.go
#	shortcuts/ci/ci_test.go
#	shortcuts/common/types.go
#	shortcuts/file/file.go
#	shortcuts/file/file_test.go
#	shortcuts/issue/batch.go
#	shortcuts/issue/batch_test.go
#	shortcuts/issue/issue_test.go
#	shortcuts/label/label.go
#	shortcuts/label/label_test.go
#	shortcuts/member/member.go
#	shortcuts/member/member_test.go
#	shortcuts/milestone/milestone.go
#	shortcuts/milestone/milestone_test.go
#	shortcuts/org/org.go
#	shortcuts/org/org_test.go
#	shortcuts/pm/pm.go
#	shortcuts/pm/pm_test.go
#	shortcuts/pr/pr.go
#	shortcuts/pr/pr_test.go
#	shortcuts/register.go
#	shortcuts/register_test.go
#	shortcuts/release/release_test.go
#	shortcuts/search/search.go
#	shortcuts/search/search_test.go
#	shortcuts/user/user.go
#	shortcuts/user/user_test.go
#	shortcuts/wiki/wiki.go
#	shortcuts/wiki/wiki_test.go
#	skills/README.md
#	skills/gitlink-ci/SKILL.md
#	skills/gitlink-file/SKILL.md
#	skills/gitlink-issue/SKILL.md
#	skills/gitlink-label/SKILL.md
#	skills/gitlink-member/SKILL.md
#	skills/gitlink-org/SKILL.md
#	skills/gitlink-pm/SKILL.md
#	skills/gitlink-pr/SKILL.md
#	skills/gitlink-research-insight/SKILL.md
#	skills/gitlink-research-progress/SKILL.md
#	skills/gitlink-user/SKILL.md
#	skills/gitlink-wiki/SKILL.md
This commit is contained in:
wbtiger 2026-07-14 22:50:17 +08:00
commit ca17974d1f
315 changed files with 42924 additions and 8057 deletions

View File

@ -0,0 +1,42 @@
version: 2
name: 自动构建部署
description: "代码提交自动触发 - 增量拉取 + Docker镜像构建与部署"
global:
concurrent: 1
trigger:
webhook: gitlink@1.0.0
event:
- ref: push
ruleset-operator: AND
workflow:
- ref: start
name: 开始
task: start
- ref: ssh_cmd_0
name: ssh增量拉取并部署
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: '"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 -p 8080:8080 $([ -f /root/.gitlink-env ] && echo --env-file /root/.gitlink-env) 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) || echo Demo deploy FAILED non-blocking, main :8080 unaffected"'
needs:
- ssh_cmd_0
- ref: end
name: 结束
task: end
needs:
- ssh_cmd_0
- ssh_cmd_1

11
.dockerignore Normal file
View File

@ -0,0 +1,11 @@
.git
.devops
.github
node_modules
dist
doc
npm
*.md
*.exe
.gitignore
.golangci.yml

26
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: CI
on:
push:
branches: [master, main]
pull_request:
branches: [master, main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Vet
run: go vet ./...
- name: Test
run: go test -v -race ./...
- name: Build
run: go build -v .

9
.gitignore vendored
View File

@ -1,4 +1,7 @@
gitlink-cli.exe
/gitlink-cli
docs/
doc/
# Python & demo artifacts
__pycache__/
*.pyc
demo/bin/
data/

View File

@ -1,65 +1,24 @@
version: "2"
run:
timeout: 5m
go: '1.22'
linters:
default: none
enable:
# Core: catch real bugs
- errcheck # unchecked errors
- govet # suspicious constructs
- ineffassign # wasted assignments
- staticcheck # comprehensive bug detection
- unused # dead code
- errcheck
- govet
- revive
- unused
- gosimple
- ineffassign
- typecheck
# Error handling
- errorlint # errors.As / %w best practices
# Security
- gosec # security issues
# Typos
- misspell # spelling mistakes in identifiers
settings:
misspell:
ignore-rules:
- creater # GitLink API/DB 字段拼写creater_id非笔误
gosec:
excludes:
- G104 # errcheck already handles unchecked errors
- G304 # file inclusion by variable is expected for CLI tools
exclusions:
paths:
- vendor/
- npm/
- skills/
- docs/
linters-settings:
revive:
rules:
# Idiomatic Go: defer Close() error is intentionally ignored
- linters: [errcheck]
text: "Error return value of .*(resp\\.Body\\.Close|file\\.Close).*is not checked"
# Output formatting: fmt.Fprint* errors are low-value
- linters: [errcheck]
text: "Error return value of `fmt\\.Fprintf?"
# Test helpers: FlagSet.Set is setup code
- linters: [errcheck]
text: "Error return value of .*FlagSet.*\\.Set"
# Best-effort output rendering
- linters: [errcheck]
path: render\.go$
# errcheck: test helpers intentionally ignore return values
- linters: [errcheck]
path: _test\.go$
# errorlint: type assertions are fine in tests
- linters: [errorlint]
path: _test\.go$
# gosec: tests are not attack surface
- linters: [gosec]
path: _test\.go$
# apiInt: intentional uint64->int truncation for API response parsing
- linters: [gosec]
text: "G115: integer overflow conversion uint64 -> int"
# apiInt: same intentional truncation for uint on 32-bit platforms
- linters: [gosec]
text: "G115: integer overflow conversion uint -> int"
- name: unused-parameter
severity: warning
issues:
exclude-use-default: false
max-issues-per-linter: 50
max-same-issues: 3

41
Dockerfile Normal file
View File

@ -0,0 +1,41 @@
# ============================================================
# 多阶段构建gitlink-cli 子赛题四网页终端
# ============================================================
# 阶段1 builder —— Go 静态编译
# ============================================================
FROM golang:1.26-alpine AS builder
ENV GOPROXY=https://goproxy.cn,direct
WORKDIR /src
# 先拷依赖清单,利用 Docker 层缓存
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# modernc.org/sqlite 是 pure-GoCGO_ENABLED=0 即可编译纯静态二进制
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /out/gitlink-cli .
# ============================================================
# 阶段2 runtime —— Python + Go 二进制
# ============================================================
FROM python:3.12-slim
# Go CLI 放入 PATH
COPY --from=builder /out/gitlink-cli /usr/local/bin/gitlink-cli
# 科研算法层:先拷 requirements.txt 安装依赖(利用层缓存),再拷源码
# pip 先升级自身,再用清华镜像(带 retry + trusted-host 防证书/网络抖动)
COPY scripts/research/requirements.txt /app/scripts/research/requirements.txt
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir --default-timeout=300 --retries 5 \
-i https://pypi.tuna.tsinghua.edu.cn/simple \
--trusted-host pypi.tuna.tsinghua.edu.cn \
-r /app/scripts/research/requirements.txt
COPY scripts/research/ /app/scripts/research/
WORKDIR /app
# 子赛题四网页终端 HTTP 服务
EXPOSE 8080
ENTRYPOINT ["gitlink-cli", "server", "--port", "8080", "--research-dir", "/app/scripts/research", "--work-dir", "/app/research-output"]

View File

@ -3,7 +3,7 @@ BINARY := gitlink-cli
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
LDFLAGS := -s -w -X '$(MODULE)/cmd.Version=$(VERSION)'
.PHONY: build install clean test check vet fmt cover lint skills
.PHONY: build install clean test test-cover lint ci
build:
go build -ldflags "$(LDFLAGS)" -o $(BINARY) .
@ -15,33 +15,16 @@ clean:
rm -f $(BINARY)
test:
go test -race ./...
go test -v -race ./...
vet:
go vet ./...
fmt:
@unformatted=$$(gofmt -s -l .); \
if [ -n "$$unformatted" ]; then \
echo "Files not formatted:"; \
echo "$$unformatted"; \
exit 1; \
fi
cover:
go test -coverprofile=coverage.out ./...
test-cover:
go test -v -race -coverprofile=coverage.out ./...
go tool cover -func=coverage.out
lint:
golangci-lint run ./...
skills:
go run ./internal/skillmeta/cmd/check
ci: lint test
check: fmt vet lint skills test
@echo "All checks passed."
hooks:
cp scripts/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
@echo "Pre-commit hook installed."
vet:
go vet ./...

View File

@ -7,17 +7,14 @@ import (
"github.com/spf13/cobra"
aliasCmd "github.com/gitlink-org/gitlink-cli/cmd/alias"
apiCmd "github.com/gitlink-org/gitlink-cli/cmd/api"
authCmd "github.com/gitlink-org/gitlink-cli/cmd/auth"
browseCmd "github.com/gitlink-org/gitlink-cli/cmd/browse"
"github.com/gitlink-org/gitlink-cli/cmd/cmdutil"
configCmd "github.com/gitlink-org/gitlink-cli/cmd/config"
doctorCmd "github.com/gitlink-org/gitlink-cli/cmd/doctor"
statusCmd "github.com/gitlink-org/gitlink-cli/cmd/status"
internalConfig "github.com/gitlink-org/gitlink-cli/internal/config"
"github.com/gitlink-org/gitlink-cli/internal/i18n"
"github.com/gitlink-org/gitlink-cli/internal/output"
serverCmd "github.com/gitlink-org/gitlink-cli/cmd/server"
"github.com/gitlink-org/gitlink-cli/shortcuts"
)
@ -48,29 +45,22 @@ func NewRootCmd(opts RootOptions, tr *i18n.Translator) (*cobra.Command, error) {
Use: "gitlink-cli",
Short: tr.T("cmd.root.short"),
Long: tr.T("cmd.root.long"),
Version: version,
SilenceUsage: true,
SilenceErrors: true,
}
rootCmd.SetVersionTemplate(tr.Tf("output.version", i18n.Args{"version": version}) + "\n")
rootCmd.PersistentFlags().StringVar(&cmdutil.Owner, "owner", "", tr.T("flag.owner"))
rootCmd.PersistentFlags().StringVar(&cmdutil.Repo, "repo", "", tr.T("flag.repo"))
rootCmd.PersistentFlags().StringVar(&cmdutil.Format, "format", "", tr.T("flag.format"))
rootCmd.PersistentFlags().BoolVar(&cmdutil.Debug, "debug", false, tr.T("flag.debug"))
rootCmd.PersistentFlags().StringVar(&cmdutil.Lang, "lang", "", tr.T("flag.lang"))
rootCmd.PersistentFlags().StringVar(&output.Query, "jq", "", tr.T("flag.jq"))
rootCmd.AddCommand(authCmd.NewAuthCmd(tr))
rootCmd.AddCommand(apiCmd.NewAPICmd(tr))
rootCmd.AddCommand(configCmd.NewConfigCmd(tr))
rootCmd.AddCommand(aliasCmd.NewAliasCmd(tr))
rootCmd.AddCommand(doctorCmd.NewDoctorCmd(tr))
rootCmd.AddCommand(newCompletionCmd(tr))
rootCmd.AddCommand(serverCmd.NewServerCmd())
rootCmd.AddCommand(newVersionCmd(version, tr))
rootCmd.AddCommand(aliasCmd.NewAliasCmd())
rootCmd.AddCommand(browseCmd.NewBrowseCmd())
rootCmd.AddCommand(statusCmd.NewStatusCmd())
shortcuts.RegisterAll(rootCmd, tr)
@ -91,43 +81,6 @@ func newVersionCmd(version string, tr *i18n.Translator) *cobra.Command {
}
}
func newCompletionCmd(tr *i18n.Translator) *cobra.Command {
var noDescriptions bool
cmd := &cobra.Command{
Use: "completion [bash|zsh|fish|powershell]",
Short: tr.T("cmd.completion.short"),
Long: tr.T("cmd.completion.long"),
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
RunE: func(cmd *cobra.Command, args []string) error {
root := cmd.Root()
out := cmd.OutOrStdout()
includeDescriptions := !noDescriptions
switch args[0] {
case "bash":
return root.GenBashCompletionV2(out, includeDescriptions)
case "zsh":
if noDescriptions {
return root.GenZshCompletionNoDesc(out)
}
return root.GenZshCompletion(out)
case "fish":
return root.GenFishCompletion(out, includeDescriptions)
case "powershell":
if noDescriptions {
return root.GenPowerShellCompletion(out)
}
return root.GenPowerShellCompletionWithDesc(out)
default:
return fmt.Errorf("unsupported shell: %s", args[0])
}
},
}
cmd.Flags().BoolVar(&noDescriptions, "no-descriptions", false, tr.T("flag.completion.no_descriptions"))
return cmd
}
func Execute() error {
args := os.Args[1:]
rootCmd, err := NewRootCmd(RootOptions{
@ -139,12 +92,6 @@ func Execute() error {
return err
}
// Rewrite argv when the first token is a saved alias. Translator resolution
// above still sees the raw args, so --lang is unaffected by expansion.
if expanded, ok := expandAlias(rootCmd, args); ok {
rootCmd.SetArgs(expanded)
}
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
return err

589
cmd/server/server.go Normal file
View File

@ -0,0 +1,589 @@
/*
* 子赛题四网页终端HTTP 演示服务
*
* 前端搜索驱动界面 后端串行运行 Python 算法脚本
* 支持 7 个科研分析维度热点/画像/启发/谱系/合规/报告/可视化
* Python 子进程继承 GITLINK_TOKEN / DEEPSEEK_API_KEY 环境变量
*
* API:
* GET /api/dimensions - 返回可用维度列表
* POST /api/chain - 统一全链路分析入口
* POST /api/run - 单场景执行(向后兼容)
* GET /api/result/{key} - 查询缓存产物
*/
package server
import (
"embed"
"encoding/json"
"fmt"
"io/fs"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
"time"
"github.com/spf13/cobra"
)
//go:embed static/*
var staticFS embed.FS
const defaultPort = 8080
// 场景定义:前端按钮 ↔ 后端 Python 脚本。
type scenarioDef struct {
Key string `json:"key"`
Label string `json:"label"`
Desc string `json:"desc"`
Script string `json:"script"`
Needs []string `json:"needs"` // 需要的输入: "owner","repo","keyword"
Timeout int `json:"timeout_s"`
}
var scenarios = []scenarioDef{
{Key: "s1", Label: "S1 仓库洞悉", Desc: "科研项目演进谱系 + 创新点", Script: "lineage.py", Needs: []string{"owner", "repo"}, Timeout: 180},
{Key: "s2", Label: "S2 知识图谱", Desc: "科研领域知识图谱(networkx)", Script: "graph_build.py", Needs: []string{"keyword"}, Timeout: 240},
{Key: "s3", Label: "S3 合规复现", Desc: "许可证/密钥/复现性检查", Script: "repro.py", Needs: []string{"owner", "repo"}, Timeout: 120},
{Key: "s4", Label: "S4 协作匹配", Desc: "学者×缺口 智能匹配", Script: "match.py", Needs: []string{"owner", "repo"}, Timeout: 180},
{Key: "s5", Label: "S5 进度预警", Desc: "周报 + 风险预警", Script: "report.py", Needs: []string{"owner", "repo"}, Timeout: 180},
{Key: "s6", Label: "S6 成果可视化", Desc: "交互图表(plotly)", Script: "visual.py", Needs: []string{"owner", "repo"}, Timeout: 240},
{Key: "hotspot", Label: "🔥 热点追踪(关键词)", Desc: "关键词搜索:飙升项目+活跃讨论+主题热度+学者团队", Script: "hotspot.py", Needs: []string{"keyword"}, Timeout: 300},
{Key: "hotspot-cat", Label: "🔥 热点追踪(分类精选)", Desc: "GitLink 官方分类精选 → 领域热点(缩范围)", Script: "hotspot.py", Needs: []string{"category"}, Timeout: 300},
{Key: "profile", Label: "🪪 主体画像", Desc: "项目画像:主题/语言/贡献者/研究维度评分", Script: "profile.py", Needs: []string{"owner", "repo"}, Timeout: 150},
{Key: "inspire", Label: "💡 创新启发", Desc: "缺口挖掘 + 合作者匹配 + LLM 研究方向建议", Script: "inspire.py", Needs: []string{"owner", "repo"}, Timeout: 240},
{Key: "chain", Label: "🔬 全链路", Desc: "分类→热点→画像→启发→合规→分析(一条命令打通)", Script: "research.py", Needs: []string{"category"}, Timeout: 600},
}
// dimensionDef 分析维度:前端展示用,对应一个 Python 脚本。
type dimensionDef struct {
Key string `json:"key"`
Label string `json:"label"`
Icon string `json:"icon"`
Desc string `json:"desc"`
Script string `json:"script"`
Needs []string `json:"needs"` // 需要的参数: "keyword","category","owner","repo","owner_repo"
Timeout int `json:"timeout_s"`
}
var dimensions = []dimensionDef{
{Key: "hotspot", Label: "科研热点分析", Icon: "🔥", Desc: "飙升项目 + 活跃讨论 + 主题热度 + 核心学者", Script: "hotspot.py", Needs: []string{"keyword_or_category"}, Timeout: 300},
{Key: "profile", Label: "主体画像", Icon: "🪪", Desc: "项目/学者画像:主题向量/语言/研究维度评分", Script: "profile.py", Needs: []string{"owner_repo_or_category"}, Timeout: 150},
{Key: "inspire", Label: "创新启发", Icon: "💡", Desc: "缺口挖掘 + 合作者匹配 + LLM 研究方向建议", Script: "inspire.py", Needs: []string{"owner_repo_or_category"}, Timeout: 240},
{Key: "lineage", Label: "演进谱系", Icon: "🌳", Desc: "创新点识别 + 项目演化分支 + 贡献者参与分析", Script: "lineage.py", Needs: []string{"owner", "repo"}, Timeout: 180},
{Key: "repro", Label: "合规复现", Icon: "✅", Desc: "许可证/依赖锁定/容器化/密钥泄漏/复现性评分", Script: "repro.py", Needs: []string{"owner", "repo"}, Timeout: 120},
{Key: "report", Label: "进度报告", Icon: "📋", Desc: "周报 + 里程碑追踪 + 风险预警(交通灯系统)", Script: "report.py", Needs: []string{"owner", "repo"}, Timeout: 180},
{Key: "visual", Label: "成果可视化", Icon: "📊", Desc: "交互式 Plotly 图表:时间线/热力图/语言饼图/Gantt", Script: "visual.py", Needs: []string{"owner", "repo"}, Timeout: 240},
}
// chainRequest 统一分析请求。
type chainRequest struct {
Dimensions []string `json:"dimensions"` // 选中的维度 key 列表
Keyword string `json:"keyword"`
Owner string `json:"owner"`
Repo string `json:"repo"`
Category string `json:"category"`
}
// dimensionResult 单个维度的运行结果。
type dimensionResult struct {
Key string `json:"key"`
Label string `json:"label"`
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
Duration string `json:"duration"`
Command string `json:"command"`
Stdout string `json:"stdout"`
OutDir string `json:"out_dir"`
Artifacts map[string]string `json:"artifacts"`
}
// chainResponse 统一分析 API 返回。
type chainResponse struct {
OK bool `json:"ok"`
SessionID string `json:"session_id"`
Duration string `json:"duration"`
Results map[string]*dimensionResult `json:"results"`
}
type Options struct {
Port int
ResearchDir string // scripts/research 目录
WorkDir string // 产物输出根目录
Token string // 可选鉴权 token
LLMKey string // LLM API Key内置到服务端非前端输入
LLMBase string // LLM API Base URL
LLMModel string // LLM Model 名称
GitLinkToken string // GitLink API Token内置Python 子进程通过 GITLINK_TOKEN 使用)
}
func NewServerCmd() *cobra.Command {
opts := Options{Port: defaultPort, ResearchDir: "scripts/research", WorkDir: "research-output", LLMKey: "sk-52b7f7db19fe41118d3b931bded9403c", LLMBase: "https://api.deepseek.com/anthropic", LLMModel: "deepseek-v4-pro", GitLinkToken: "330e35fbb163da345df372b4cbe1cf973aae2b67"}
cmd := &cobra.Command{
Use: "server",
Short: "启动子赛题四网页终端HTTP 演示服务)",
RunE: func(cmd *cobra.Command, args []string) error {
return Run(opts)
},
}
cmd.Flags().IntVarP(&opts.Port, "port", "p", defaultPort, "监听端口")
cmd.Flags().StringVar(&opts.ResearchDir, "research-dir", "scripts/research", "scripts/research 目录")
cmd.Flags().StringVar(&opts.WorkDir, "work-dir", "research-output", "产物输出根目录")
cmd.Flags().StringVar(&opts.Token, "token", "", "可选鉴权 token亦可用 DEMO_TOKEN 环境变量)")
cmd.Flags().StringVar(&opts.LLMKey, "llm-key", opts.LLMKey, "LLM API Key默认内置")
cmd.Flags().StringVar(&opts.LLMBase, "llm-base", opts.LLMBase, "LLM API Base URL")
cmd.Flags().StringVar(&opts.LLMModel, "llm-model", opts.LLMModel, "LLM Model 名称")
cmd.Flags().StringVar(&opts.GitLinkToken, "gitlink-token", opts.GitLinkToken, "GitLink API Token默认内置")
return cmd
}
// Run 启动 HTTP 服务(阻塞)。
func Run(opts Options) error {
if t := os.Getenv("DEMO_TOKEN"); t != "" && opts.Token == "" {
opts.Token = t
}
// LLM key 优先级:--llm-key > DEEPSEEK_API_KEY > LLM_API_KEY
if opts.LLMKey == "" {
if k := os.Getenv("DEEPSEEK_API_KEY"); k != "" {
opts.LLMKey = k
} else if k := os.Getenv("LLM_API_KEY"); k != "" {
opts.LLMKey = k
}
}
// GitLink token内置默认值注入进程环境子进程自动继承
if opts.GitLinkToken != "" && os.Getenv("GITLINK_TOKEN") == "" {
_ = os.Setenv("GITLINK_TOKEN", opts.GitLinkToken)
}
// 让 python 子进程复用本二进制gitlink_data.cli_path 读 GITLINK_CLI免去额外配置
if os.Getenv("GITLINK_CLI") == "" {
if exe, err := filepath.Abs(os.Args[0]); err == nil {
_ = os.Setenv("GITLINK_CLI", exe)
}
}
_ = os.MkdirAll(opts.WorkDir, 0o755)
mux := http.NewServeMux()
h := &handler{opts: opts}
mux.HandleFunc("GET /api/scenarios", h.handleScenarios)
mux.HandleFunc("POST /api/run", h.handleRun)
mux.HandleFunc("GET /api/result/{key}", h.handleResult)
mux.HandleFunc("GET /api/health", h.handleHealth)
mux.HandleFunc("GET /api/dimensions", h.handleDimensions)
mux.HandleFunc("POST /api/chain", h.handleChain)
sub, err := fs.Sub(staticFS, "static")
if err != nil {
return fmt.Errorf("static fs: %w", err)
}
mux.Handle("GET /", http.FileServer(http.FS(sub)))
addr := fmt.Sprintf(":%d", opts.Port)
fmt.Fprintf(os.Stderr, "子赛题四 网页终端已启动: http://localhost%s\n", addr)
fmt.Fprintf(os.Stderr, " research-dir=%s work-dir=%s auth=%v\n", opts.ResearchDir, opts.WorkDir, opts.Token != "")
if opts.LLMKey != "" {
fmt.Fprintf(os.Stderr, " LLM: enabled (model=%s)\n", opts.LLMModel)
} else {
fmt.Fprintf(os.Stderr, " LLM: disabled (no key)\n")
}
srv := &http.Server{Addr: addr, Handler: mux, ReadHeaderTimeout: 10 * time.Second}
return srv.ListenAndServe()
}
type handler struct {
opts Options
mu sync.Mutex // 串行化场景执行,避免并发打爆 GitLink API
}
func (h *handler) authed(r *http.Request) bool {
if h.opts.Token == "" {
return true
}
return r.Header.Get("X-Demo-Token") == h.opts.Token
}
func (h *handler) handleHealth(w http.ResponseWriter, r *http.Request) {
writeJSON(w, map[string]any{"ok": true, "scenarios": len(scenarios), "dimensions": len(dimensions)})
}
func (h *handler) handleDimensions(w http.ResponseWriter, r *http.Request) {
if !h.authed(r) {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
writeJSON(w, map[string]any{"ok": true, "dimensions": dimensions})
}
func (h *handler) handleScenarios(w http.ResponseWriter, r *http.Request) {
if !h.authed(r) {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
writeJSON(w, map[string]any{"ok": true, "scenarios": scenarios})
}
// handleResult 返回某场景最近一次运行的产物(供 result.html 独立结果页按 key 读取,
// URL 可刷新/分享,便于演示讲解)。无需鉴权串行锁——只读已落盘产物。
func (h *handler) handleResult(w http.ResponseWriter, r *http.Request) {
if !h.authed(r) {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
key := r.PathValue("key")
sc, ok := findScenario(key)
if !ok {
writeJSON(w, map[string]any{"ok": false, "error": "unknown scenario: " + key})
return
}
outDir := filepath.Join(h.opts.WorkDir, sc.Key)
writeJSON(w, map[string]any{
"ok": true,
"scenario": sc.Key,
"label": sc.Label,
"desc": sc.Desc,
"artifacts": readArtifacts(outDir),
})
}
type runRequest struct {
Scenario string `json:"scenario"`
Owner string `json:"owner"`
Repo string `json:"repo"`
Keyword string `json:"keyword"`
Category string `json:"category"`
}
func (h *handler) handleRun(w http.ResponseWriter, r *http.Request) {
if !h.authed(r) {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
var req runRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeJSON(w, map[string]any{"ok": false, "error": "bad request: " + err.Error()})
return
}
sc, ok := findScenario(req.Scenario)
if !ok {
writeJSON(w, map[string]any{"ok": false, "error": "unknown scenario: " + req.Scenario})
return
}
for _, need := range sc.Needs {
if (need == "keyword" && req.Keyword == "") ||
(need == "owner" && req.Owner == "") ||
(need == "repo" && req.Repo == "") ||
(need == "category" && req.Category == "") {
writeJSON(w, map[string]any{"ok": false, "error": "missing parameter: " + need})
return
}
}
// 串行执行:一次只跑一个场景,保护 GitLink API。
h.mu.Lock()
defer h.mu.Unlock()
scriptPath := filepath.Join(h.opts.ResearchDir, sc.Script)
outDir := filepath.Join(h.opts.WorkDir, sc.Key)
_ = os.MkdirAll(outDir, 0o755)
argv := []string{scriptPath, "--out", outDir}
if contains(sc.Needs, "owner") {
argv = append(argv, "--owner", req.Owner, "--repo", req.Repo)
}
if contains(sc.Needs, "keyword") {
argv = append(argv, "--keywords", req.Keyword)
}
if contains(sc.Needs, "category") {
argv = append(argv, "--category", req.Category)
}
// chain 支持可选焦点仓(省略则自动取热点榜 top-1
if sc.Key == "chain" && req.Owner != "" && req.Repo != "" {
argv = append(argv, "--repo", req.Owner+"/"+req.Repo)
}
// python3 优先,回退 python
py, err := pythonBin()
if err != nil {
writeJSON(w, map[string]any{"ok": false, "error": err.Error()})
return
}
cmd := exec.Command(py, argv...)
// 子进程复用本二进制python 经 GITLINK_CLI 找 gitlink-cli直接注入子进程 env最稳。
env := os.Environ()
if !envHas(env, "GITLINK_CLI") {
if exe, err := filepath.Abs(os.Args[0]); err == nil {
env = append(env, "GITLINK_CLI="+exe)
}
}
cmd.Env = env
start := time.Now()
out, err := cmd.CombinedOutput()
dur := time.Since(start)
resp := map[string]any{
"ok": err == nil,
"scenario": sc.Key,
"command": py + " " + strings.Join(argv, " "),
"duration": dur.Truncate(time.Millisecond).String(),
"stdout": string(out),
"out_dir": outDir,
}
if err != nil {
resp["error"] = err.Error()
}
// 附带读取关键产物json + 第一个 mmd + report.md便于前端直接渲染
resp["artifacts"] = readArtifacts(outDir)
writeJSON(w, resp)
}
// handleChain 统一全链路科研分析入口
//
// 接受维度 key 列表 + 关键词/分类/仓库参数,串行执行各 Python 脚本,
// 聚合结果返回给前端 Tab 面板渲染。每个维度独立计时并记录成功/失败状态。
// 复用全局 mutex 防止并发打爆 GitLink API。
//
// 参数:
// w - HTTP ResponseWriter
// r - HTTP RequestJSON body 为 chainRequest
//
// 返回:
// JSON chainResponse包含 session_id、总耗时、各维度结果映射
func (h *handler) handleChain(w http.ResponseWriter, r *http.Request) {
if !h.authed(r) {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
var req chainRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeJSON(w, chainResponse{OK: false, Results: map[string]*dimensionResult{"_error": {Key: "_error", Label: "parse error", OK: false, Error: "bad request: " + err.Error()}}})
return
}
if len(req.Dimensions) == 0 {
writeJSON(w, chainResponse{OK: false, Results: map[string]*dimensionResult{"_error": {Key: "_error", Label: "no dimensions", OK: false, Error: "至少选择一个分析维度"}}})
return
}
// 校验所有维度 key 合法
for _, dk := range req.Dimensions {
if _, ok := findDimension(dk); !ok {
writeJSON(w, chainResponse{OK: false, Results: map[string]*dimensionResult{"_error": {Key: dk, Label: dk, OK: false, Error: "未知分析维度: " + dk}}})
return
}
}
// 串行执行(复用 mutex 保护 GitLink API
h.mu.Lock()
defer h.mu.Unlock()
sessionID := fmt.Sprintf("session_%s", time.Now().Format("20060102_150405"))
results := make(map[string]*dimensionResult)
totalStart := time.Now()
for _, dk := range req.Dimensions {
dim, _ := findDimension(dk)
dimArgs, err := buildDimensionArgs(dim, req)
outDir := filepath.Join(h.opts.WorkDir, sessionID, dim.Key)
_ = os.MkdirAll(outDir, 0o755)
dr := &dimensionResult{Key: dim.Key, Label: dim.Label, OutDir: outDir}
if err != nil {
dr.OK = false
dr.Error = err.Error()
results[dim.Key] = dr
continue
}
py, err := pythonBin()
if err != nil {
dr.OK = false
dr.Error = err.Error()
results[dim.Key] = dr
continue
}
scriptPath := filepath.Join(h.opts.ResearchDir, dim.Script)
argv := append([]string{scriptPath, "--out", outDir}, dimArgs...)
cmd := exec.Command(py, argv...)
env := os.Environ()
if !envHas(env, "GITLINK_CLI") {
if exe, e2 := filepath.Abs(os.Args[0]); e2 == nil {
env = append(env, "GITLINK_CLI="+exe)
}
}
// LLM key 注入子进程
if h.opts.LLMKey != "" {
if !envHas(env, "DEEPSEEK_API_KEY") && !envHas(env, "LLM_API_KEY") {
env = append(env, "DEEPSEEK_API_KEY="+h.opts.LLMKey)
}
if !envHas(env, "DEEPSEEK_BASE_URL") && !envHas(env, "LLM_BASE_URL") {
env = append(env, "DEEPSEEK_BASE_URL="+h.opts.LLMBase)
}
if !envHas(env, "DEEPSEEK_MODEL") && !envHas(env, "LLM_MODEL") {
env = append(env, "DEEPSEEK_MODEL="+h.opts.LLMModel)
}
}
cmd.Env = env
dr.Command = py + " " + strings.Join(argv, " ")
dimStart := time.Now()
out, runErr := cmd.CombinedOutput()
dr.Duration = time.Since(dimStart).Truncate(time.Millisecond).String()
dr.Stdout = string(out)
dr.OK = runErr == nil
if runErr != nil {
dr.Error = runErr.Error()
}
dr.Artifacts = readArtifacts(outDir)
results[dim.Key] = dr
}
resp := chainResponse{
OK: true,
SessionID: sessionID,
Duration: time.Since(totalStart).Truncate(time.Millisecond).String(),
Results: results,
}
writeJSON(w, resp)
}
func findScenario(key string) (scenarioDef, bool) {
for _, s := range scenarios {
if s.Key == key || strings.EqualFold(s.Key, key) {
return s, true
}
}
return scenarioDef{}, false
}
func findDimension(key string) (dimensionDef, bool) {
for _, d := range dimensions {
if d.Key == key || strings.EqualFold(d.Key, key) {
return d, true
}
}
return dimensionDef{}, false
}
func readArtifacts(dir string) map[string]string {
out := map[string]string{}
// json 产物(取第一个 *.json
if entries, err := os.ReadDir(dir); err == nil {
for _, e := range entries {
if e.IsDir() {
continue
}
name := e.Name()
switch {
case strings.HasSuffix(name, ".json"):
b, _ := os.ReadFile(filepath.Join(dir, name))
out["json"] = string(b)
case strings.HasSuffix(name, ".mmd"):
b, _ := os.ReadFile(filepath.Join(dir, name))
out["mermaid"] = string(b)
case name == "visual.html":
b, _ := os.ReadFile(filepath.Join(dir, name))
out["html"] = string(b)
case strings.HasSuffix(name, ".md"):
// 第一份 .md 报告report.md / weekly_report.md / compliance_report.md
if _, ok := out["report"]; !ok {
b, _ := os.ReadFile(filepath.Join(dir, name))
out["report"] = string(b)
}
}
}
}
return out
}
func pythonBin() (string, error) {
// 候选按 Linux 习惯 python3 优先,再 python / py(Windows)。
// 必须实测能产出Windows 的 WindowsApps\python3.exe 是 Store 桩,对 -c 也可能 exit 0 但不真正执行,
// 故用「stdout 必须含 PYOK」来拦截桩。
for _, name := range []string{"python3", "python", "py"} {
path, err := exec.LookPath(name)
if err != nil {
continue
}
if out, err := exec.Command(path, "-c", "print('PYOK')").Output(); err == nil &&
strings.Contains(string(out), "PYOK") {
return path, nil
}
}
return "", fmt.Errorf("python 未安装;容器需内置 python3 并 pip install -r scripts/research/requirements.txt")
}
func contains(xs []string, s string) bool {
for _, x := range xs {
if x == s {
return true
}
}
return false
}
// buildDimensionArgs 根据维度定义和请求参数构建 Python 脚本 CLI 参数。
func buildDimensionArgs(dim dimensionDef, req chainRequest) ([]string, error) {
argv := []string{} // script 在调用方追加
hasKeyword := req.Keyword != ""
hasCategory := req.Category != ""
hasRepo := req.Owner != "" && req.Repo != ""
// 检查每个 need
for _, need := range dim.Needs {
switch need {
case "keyword_or_category":
if !hasKeyword && !hasCategory {
return nil, fmt.Errorf("维度 %s 需要 --keywords 或 --category", dim.Key)
}
if hasCategory {
argv = append(argv, "--category", req.Category)
} else {
argv = append(argv, "--keywords", req.Keyword)
}
case "keyword":
if !hasKeyword {
return nil, fmt.Errorf("维度 %s 需要 --keywords", dim.Key)
}
argv = append(argv, "--keywords", req.Keyword)
case "owner_repo_or_category":
if !hasRepo && !hasCategory {
return nil, fmt.Errorf("维度 %s 需要 --owner/--repo 或 --category", dim.Key)
}
if hasCategory {
argv = append(argv, "--category", req.Category)
} else {
argv = append(argv, "--owner", req.Owner, "--repo", req.Repo)
}
case "owner":
if !hasRepo {
return nil, fmt.Errorf("维度 %s 需要 --owner 和 --repo", dim.Key)
}
argv = append(argv, "--owner", req.Owner)
case "repo":
if !hasRepo {
return nil, fmt.Errorf("维度 %s 需要 --repo", dim.Key)
}
argv = append(argv, "--repo", req.Repo)
}
}
return argv, nil
}
// envHas 报告环境变量切片里是否已含某 KEY形如 "KEY=...")。
func envHas(env []string, key string) bool {
prefix := key + "="
for _, e := range env {
if strings.HasPrefix(e, prefix) {
return true
}
}
return false
}
func writeJSON(w http.ResponseWriter, v any) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
_ = json.NewEncoder(w).Encode(v)
}

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=index.html">
<title>科研热点追踪 · GitLink Research Atlas</title>
</head>
<body style="font-family:-apple-system,'PingFang SC','Microsoft YaHei',sans-serif;text-align:center;padding:60px 20px;color:#475569">
<p>🔥 热点追踪已整合到 <a href="index.html" style="color:#4F6BED;font-weight:600">全链路科研分析</a></p>
<p style="font-size:13px;color:#94A3B8;margin-top:10px">正在跳转…</p>
</body>
</html>

1048
cmd/server/static/index.html Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,504 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GitLink Research Atlas · 结果详情</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@500;700&family=Noto+Serif+SC:wght@600;700&family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<style>
:root{
--bg:#F7F9FC; --card:#FFFFFF; --ink:#1E2A44; --ink2:#475569; --mute:#94A3B8;
--line:#E6EBF2; --indigo:#4F6BED; --coral:#F26B5E; --mint:#2EC4B6;
--t-blue:#E8EEFF; --t-coral:#FFEDEA; --t-mint:#E6F7F4; --t-amber:#FEF3C7;
--serif:"Cormorant Garamond","Noto Serif SC",Georgia,serif;
--sans:"Inter","Noto Sans SC",-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;
--mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
--shadow:0 1px 2px rgba(30,42,68,.04),0 6px 18px rgba(30,42,68,.06);
--shadow-sm:0 1px 2px rgba(30,42,68,.06);
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:auto;min-height:100%;margin:0}
body{font-family:var(--sans);color:var(--ink);background:var(--bg);
background-image:radial-gradient(1200px 480px at 80% -8%,#EAF0FF 0%,rgba(234,240,255,0) 60%),
radial-gradient(900px 420px at 0% 0%,#FFF1EE 0%,rgba(255,241,238,0) 55%);
-webkit-font-smoothing:antialiased}
/* ========== PRINT ========== */
@media print{
body{background:#fff!important}
.no-print{display:none!important}
.page-wrap{max-width:100%!important;box-shadow:none!important}
}
/* ========== PAGE WRAPPER ========== */
.page-wrap{max-width:1120px;margin:0 auto;padding:32px 40px 60px}
@media(max-width:760px){.page-wrap{padding:20px 16px 40px}}
/* ========== HEADER ========== */
.res-header{margin-bottom:32px}
.res-header .back{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;
color:var(--indigo);text-decoration:none;margin-bottom:16px;padding:6px 14px;border-radius:10px;
background:var(--t-blue);transition:.15s}
.res-header .back:hover{background:#D6DEFF}
.res-header h1{font-family:var(--serif);font-weight:700;font-size:34px;line-height:1.2;letter-spacing:.3px;color:var(--ink)}
.res-header .sub{font-size:15px;color:var(--ink2);margin-top:6px;line-height:1.5}
.res-header .meta{display:flex;flex-wrap:wrap;gap:16px;margin-top:14px;align-items:center}
.res-header .meta .chip{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:500;
padding:5px 12px;border-radius:999px;background:var(--card);border:1px solid var(--line);color:var(--ink2);box-shadow:var(--shadow-sm)}
.res-header .meta .chip b{font-family:var(--mono);font-weight:700;color:var(--ink)}
.res-header .cmd-drawer{margin-top:14px;background:var(--ink);color:#CBD5E1;font-family:var(--mono);
font-size:12px;padding:10px 16px;border-radius:10px;display:flex;align-items:center;gap:10px;overflow:hidden}
.res-header .cmd-drawer .dots{display:flex;gap:6px;flex-shrink:0}
.res-header .cmd-drawer .dots i{width:11px;height:11px;border-radius:50%;display:block}
.res-header .cmd-drawer .cmd{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#E2E8F0}
/* ========== SECTION TITLES ========== */
.section{margin-top:36px}
.section-title{font-family:var(--serif);font-weight:700;font-size:22px;color:var(--ink);margin-bottom:16px;
padding-bottom:8px;border-bottom:2px solid var(--line)}
.section-title .eyebrow{font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
color:var(--mute);display:block;margin-bottom:4px}
/* ========== METRICS ROW ========== */
.metrics-row{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:8px}
@media(max-width:760px){.metrics-row{grid-template-columns:repeat(2,1fr)}}
.metric-card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:18px;
box-shadow:var(--shadow);text-align:center}
.metric-card .label{font-size:12px;color:var(--ink2);font-weight:500;margin-bottom:8px}
.metric-card .value{font-family:var(--mono);font-weight:700;font-size:32px;color:var(--ink);line-height:1}
.metric-card .note{font-size:11px;color:var(--mute);margin-top:6px}
/* ========== KNOWLEDGE GRAPH ========== */
.graph-container{background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
padding:20px;overflow:hidden}
.graph-svg-wrap{width:100%;height:500px;position:relative;background:radial-gradient(500px 380px at 50% 45%,#F2F6FF 0%,rgba(255,255,255,0) 70%);
border-radius:10px;overflow:hidden}
.graph-svg-wrap svg{width:100%;height:100%;display:block}
.g-edge{stroke:#9DB4F0;stroke-opacity:.55;stroke-width:1}
.g-node circle{stroke:#fff;stroke-width:2;transition:.2s}
.g-node:hover circle{filter:brightness(1.08)}
.g-node text{font-family:var(--sans);font-size:11px;font-weight:600;fill:var(--ink);pointer-events:none;text-anchor:middle}
.graph-legend{display:flex;flex-wrap:wrap;gap:14px;margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
.graph-legend .leg-item{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--ink2)}
.graph-legend .leg-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.graph-legend .leg-note{font-size:12px;color:var(--mute);margin-left:auto}
/* ========== VIZ IFRAME (S6) ========== */
.viz-container{background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
padding:12px;overflow:hidden}
.viz-container iframe{width:100%;height:520px;border:0;border-radius:10px;background:#fff}
/* ========== MERMAID ========== */
.mmd-container{background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
padding:16px;overflow:auto;max-height:600px}
/* ========== RADAR / SCORE (S3) ========== */
.score-display{display:flex;align-items:center;justify-content:center;gap:40px;padding:30px;
background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);flex-wrap:wrap}
.score-circle{width:140px;height:140px;border-radius:50%;display:flex;flex-direction:column;align-items:center;justify-content:center;
position:relative;border:6px solid}
.score-circle .val{font-family:var(--mono);font-weight:700;font-size:40px;line-height:1}
.score-circle .label{font-size:13px;color:var(--ink2);margin-top:2px}
.score-circle.repro{border-color:var(--mint);color:var(--mint);background:var(--t-mint)}
.score-circle.compliance{border-color:var(--indigo);color:var(--indigo);background:var(--t-blue)}
/* ========== WEEKLY COMPARISON (S5) ========== */
.weekly-bars{display:flex;flex-direction:column;gap:16px;padding:20px;
background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow)}
.week-row{display:flex;align-items:center;gap:14px}
.week-row .label{width:70px;font-size:13px;font-weight:600;color:var(--ink2);flex-shrink:0}
.week-row .bar-bg{flex:1;height:28px;background:#F1F5F9;border-radius:8px;overflow:hidden;position:relative}
.week-row .bar-fill{height:100%;border-radius:8px;transition:width .6s ease}
.week-row .bar-fill.this-week{background:linear-gradient(90deg,var(--indigo),#7C8CF5)}
.week-row .bar-fill.last-week{background:var(--line)}
.week-row .bar-val{position:absolute;right:8px;top:50%;transform:translateY(-50%);font-family:var(--mono);font-size:12px;font-weight:600;color:var(--ink)}
.risk-list{margin-top:20px;display:flex;flex-direction:column;gap:10px}
.risk-item{padding:10px 14px;border-radius:10px;border-left:4px solid}
.risk-item.critical{border-color:var(--coral);background:var(--t-coral)}
.risk-item.warning{border-color:#F59E0B;background:var(--t-amber)}
.risk-item .type{font-size:11px;font-family:var(--mono);color:var(--mute);text-transform:uppercase}
.risk-item .msg{font-size:13px;color:var(--ink);margin-top:4px}
.risk-item .suggestion{font-size:12px;color:var(--ink2);margin-top:4px;font-style:italic}
/* ========== REPORT (markdown) ========== */
.report-content{background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
padding:28px 32px;line-height:1.75;font-size:14px;color:var(--ink)}
.report-content h1{font-family:var(--serif);font-weight:700;font-size:26px;margin:24px 0 12px;padding-bottom:8px;border-bottom:2px solid var(--line)}
.report-content h1:first-child{margin-top:0}
.report-content h2{font-family:var(--serif);font-weight:700;font-size:20px;margin:20px 0 10px;color:var(--ink)}
.report-content h3{font-weight:700;font-size:16px;margin:16px 0 8px;color:var(--ink2)}
.report-content p{margin:10px 0}
.report-content ul,.report-content ol{margin:8px 0;padding-left:24px}
.report-content li{margin:4px 0}
.report-content strong{font-weight:700;color:var(--ink)}
.report-content code{font-family:var(--mono);font-size:12.5px;background:var(--t-blue);padding:2px 6px;border-radius:4px;color:var(--indigo)}
.report-content table{width:100%;border-collapse:collapse;margin:12px 0;font-size:13px}
.report-content th{background:var(--t-blue);font-weight:600;text-align:left;padding:8px 12px;border:1px solid var(--line)}
.report-content td{padding:8px 12px;border:1px solid var(--line)}
/* ========== STRUCTURED CARDS ========== */
.cards-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:16px;margin-top:20px}
.conclusion-card{background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow);
padding:16px 18px;border-top:4px solid}
.conclusion-card.innovation{border-top-color:var(--indigo)}
.conclusion-card.risk{border-top-color:var(--coral)}
.conclusion-card.collab{border-top-color:var(--mint)}
.conclusion-card .card-title{font-weight:700;font-size:14px;color:var(--ink);margin-bottom:8px}
.conclusion-card .card-body{font-size:13px;color:var(--ink2);line-height:1.55}
.conclusion-card .card-body p{margin:4px 0}
/* ========== LOADING STATE ========== */
.loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:80px 20px;color:var(--mute);gap:16px}
.spin-lg{width:40px;height:40px;border-radius:50%;border:4px solid var(--t-blue);border-top-color:var(--indigo);animation:rot .8s linear infinite}
@keyframes rot{to{transform:rotate(360deg)}}
/* ========== ERROR ========== */
.error-state{padding:60px 20px;text-align:center;color:var(--coral)}
.error-state h2{font-family:var(--serif);font-size:24px;margin-bottom:12px}
.error-state p{font-size:14px;color:var(--ink2);max-width:500px;margin:0 auto}
/* empty */
.empty-state{padding:60px 20px;text-align:center;color:var(--mute)}
.empty-state p{font-size:14px}
</style>
</head>
<body>
<div class="page-wrap" id="app">
<div class="loading-state"><div class="spin-lg"></div><div>正在加载结果…</div></div>
</div>
<script>
mermaid.initialize({startOnLoad:false, theme:"base", securityLevel:"loose",
themeVariables:{primaryColor:"#E8EEFF",primaryTextColor:"#1E2A44",primaryBorderColor:"#4F6BED",lineColor:"#9DB4F0",fontSize:"13px"}});
const NODE_COLOR={repo:"#4F6BED",scholar:"#3B82F6",team:"#6366F1",topic:"#06B6D4",method:"#6366F1",
paper:"#8B5CF6",dataset:"#2EC4B6",model:"#4F6BED",experiment:"#F26B5E",
reproduce:"#2EC4B6",license:"#64748B",trend:"#F26B5E",issue:"#F59E0B",pr:"#10B981",default:"#94A3B8"};
const NODE_LABEL={repo:"仓库",scholar:"学者",topic:"主题",paper:"论文",dataset:"数据集",
model:"模型",experiment:"实验",reproduce:"复现",license:"许可证",trend:"趋势",issue:"Issue",pr:"PR"};
function esc(s){return String(s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));}
function token(){return localStorage.getItem("demo_token")||"";}
function licOf(o){const l=o.license;if(!l)return o.license_id||"—";return typeof l==="string"?l:(l.id||l.name||l.spdx_id||l.identifier||"—");}
/* ========== Force layout (same as index) ========== */
function forceLayout(nodes,edges,W,H,iters){
const cx=W/2,cy=H/2;
nodes.forEach(n=>{if(n.x==null){n.x=cx+(Math.random()-.5)*W*.5;n.y=cy+(Math.random()-.5)*H*.5;}});
for(let it=0;it<iters;it++){
for(const n of nodes){n._fx=0;n._fy=0;}
for(let i=0;i<nodes.length;i++){for(let j=i+1;j<nodes.length;j++){
let dx=nodes[i].x-nodes[j].x,dy=nodes[i].y-nodes[j].y,d2=dx*dx+dy*dy+.02,d=Math.sqrt(d2),f=2600/d2,fx=dx/d*f,fy=dy/d*f;
nodes[i]._fx+=fx;nodes[i]._fy+=fy;nodes[j]._fx-=fx;nodes[j]._fy-=fy;}}
for(const e of edges){const a=nodes.find(n=>n.id===e[0]),b=nodes.find(n=>n.id===e[1]);if(!a||!b)continue;
let dx=b.x-a.x,dy=b.y-a.y,d=Math.sqrt(dx*dx+dy*dy)+.02,L=a.imp||b.imp?130:85,k=.04;
let f=(d-L)*k,fx=dx/d*f,fy=dy/d*f;a._fx+=fx;a._fy+=fy;b._fx-=fx;b._fy-=fy;}
for(const n of nodes){n._fx+=(cx-n.x)*.012;n._fy+=(cy-n.y)*.012;
n.x+=Math.max(-14,Math.min(14,n._fx));n.y+=Math.max(-14,Math.min(14,n._fy));
n.x=Math.max(45,Math.min(W-45,n.x));n.y=Math.max(38,Math.min(H-34,n.y));}}
}
function drawGraphIn(containerId,data){
const svg=document.getElementById(containerId); if(!svg) return;
const W=svg.clientWidth||800,H=svg.clientHeight||500;
svg.setAttribute("viewBox",`0 0 ${W} ${H}`);
let nodes=(data.nodes||[]).map(n=>Object.assign({},n));
let edges=(data.edges||[]).map(e=>Array.isArray(e)?e:[e.source||e.from,e.target||e.to]);
if(nodes.length>40){
const deg=new Map(nodes.map(n=>[n.id,0]));
edges.forEach(e=>{deg.set(e[0],(deg.get(e[0])||0)+1);deg.set(e[1],(deg.get(e[1])||0)+1);});
nodes.sort((a,b)=>(deg.get(b.id)||0)-(deg.get(a.id)||0));
const keep=new Set(nodes.slice(0,40).map(n=>n.id));nodes=nodes.filter(n=>keep.has(n.id));edges=edges.filter(e=>keep.has(e[0])&&keep.has(e[1]));
}
forceLayout(nodes,edges,W,H,300);
let s=`<defs><filter id="glow2"><feGaussianBlur stdDeviation="5" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs>`;
for(const e of edges){const a=nodes.find(n=>n.id===e[0]),b=nodes.find(n=>n.id===e[1]);if(!a||!b)continue;
s+=`<line class="g-edge" x1="${a.x.toFixed(1)}" y1="${a.y.toFixed(1)}" x2="${b.x.toFixed(1)}" y2="${b.y.toFixed(1)}"/>`;}
for(const n of nodes){const col=NODE_COLOR[n.type]||NODE_COLOR.default,r=n.imp?13:8;
s+=`<g class="g-node" transform="translate(${n.x.toFixed(1)},${n.y.toFixed(1)})"><circle r="${r}" fill="${col}"${n.imp?' filter="url(#glow2)"':""}/><text y="${r+13}">${esc(n.label||n.id).slice(0,18)}</text></g>`;}
svg.innerHTML=s;
}
function buildGraphLegend(types){
let h="";
for(const t of [...types].sort()){
h+=`<span class="leg-item"><span class="leg-dot" style="background:${NODE_COLOR[t]||NODE_COLOR.default}"></span>${NODE_LABEL[t]||t}</span>`;
}
return h;
}
/* ========== Simple markdown to HTML ========== */
function mdToHtml(md){
if(!md) return "";
let html=esc(md);
// code blocks
html=html.replace(/```(\w*)\n([\s\S]*?)```/g,'<pre><code>$2</code></pre>');
// inline code
html=html.replace(/`([^`]+)`/g,'<code>$1</code>');
// tables
html=html.replace(/^(\|.+\|)\n(\|[-:\s|]+\|)\n((?:\|.+\|\n?)*)/gm,function(_,hdr,sep,body){
const ths=hdr.split("|").filter(c=>c.trim()).map(c=>`<th>${c.trim()}</th>`).join("");
let rows="";
body.trim().split("\n").forEach(row=>{
const tds=row.split("|").filter(c=>c.trim()).map(c=>`<td>${c.trim()}</td>`).join("");
rows+=`<tr>${tds}</tr>`;
});
return `<table><thead><tr>${ths}</tr></thead><tbody>${rows}</tbody></table>`;
});
// headings
html=html.replace(/^### (.+)$/gm,'<h3>$1</h3>');
html=html.replace(/^## (.+)$/gm,'<h2>$1</h2>');
html=html.replace(/^# (.+)$/gm,'<h1>$1</h1>');
// bold
html=html.replace(/\*\*([^*]+)\*\*/g,'<strong>$1</strong>');
// unordered lists
html=html.replace(/^- (.+)$/gm,'<li>$1</li>');
html=html.replace(/(<li>.*<\/li>\n?)+/g,'<ul>$&</ul>');
// paragraphs (lines not inside tags)
html=html.replace(/^(?!<[huplo])((?!<).+)$/gm,'<p>$1</p>');
return html;
}
/* ========== MAIN RENDER ========== */
async function loadResult(){
const params=new URLSearchParams(window.location.search);
const scenario=params.get("scenario");
if(!scenario){
document.getElementById("app").innerHTML='<div class="error-state"><h2>缺少场景参数</h2><p>请从仪表盘点击场景,或手动打开 <code>result.html?scenario=s1</code></p></div>';
return;
}
let data;
try{
const r=await fetch("/api/result/"+encodeURIComponent(scenario),{headers:{"X-Demo-Token":token()}});
data=await r.json();
}catch(e){
document.getElementById("app").innerHTML='<div class="error-state"><h2>加载失败</h2><p>'+esc(e.message)+'</p><a class="back" href="index.html">返回仪表盘</a></div>';
return;
}
if(!data.ok){
document.getElementById("app").innerHTML='<div class="error-state"><h2>'+esc(data.error||"数据未就绪")+'</h2><p>请先在仪表盘运行该场景以生成结果。</p><a class="back" href="index.html">返回仪表盘</a></div>';
return;
}
const art=data.artifacts||{};
const obj=art.json?JSON.parse(art.json):null;
const owner=params.get("owner")||val_from("owner")||"";
const repo=params.get("repo")||val_from("repo")||"";
const keyword=params.get("keyword")||val_from("keyword")||"";
render(data,obj,art,scenario,owner,repo,keyword);
}
function val_from(name){try{return localStorage.getItem("atlas_"+name)||"";}catch(e){return"";}}
function render(data,obj,art,scenario,owner,repo,keyword){
const label=data.label||scenario;
const desc=data.desc||"";
const now=new Date().toLocaleString("zh-CN");
let h="";
// ---- HEADER ----
h+=`<div class="res-header">
<a class="back no-print" href="index.html">&#8592; 返回仪表盘</a>
<h1>${esc(label)}</h1>
<div class="sub">${esc(desc)}</div>
<div class="meta">`;
if(owner||repo) h+=`<span class="chip">仓库 <b>${esc(owner)}${repo?"/"+esc(repo):""}</b></span>`;
if(keyword) h+=`<span class="chip">关键词 <b>${esc(keyword)}</b></span>`;
h+=`<span class="chip">场景 <b>${esc(scenario)}</b></span>
<span class="chip">生成于 ${esc(now)}</span>
</div>
<div class="cmd-drawer no-print">
<div class="dots"><i style="background:#FF5F57"></i><i style="background:#FEBC2E"></i><i style="background:#28C840"></i></div>
<span style="color:var(--mint)">atlas &#10095;</span>
<span class="cmd">gitlink-cli research --scenario ${esc(scenario)} ${owner?"--repo "+esc(owner)+"/"+esc(repo):""} ${keyword?'-k "'+esc(keyword)+'"':""}</span>
</div></div>`;
// ---- METRICS ROW ----
const metrics=metricsFor(scenario,obj);
if(metrics){
h+=`<div class="section"><div class="section-title"><span class="eyebrow">Key Metrics</span>关键指标</div>
<div class="metrics-row">${metrics}</div></div>`;
}
// ---- MAIN VIZ ----
h+=`<div class="section"><div class="section-title"><span class="eyebrow">Visualization</span>可视化</div>`;
// S2: Knowledge Graph
if(scenario==="s2"&&obj&&obj.nodes&&obj.edges){
const graphNodes=obj.nodes.map(n=>({id:n.id,type:n.type||"default",label:n.label||n.id,imp:false}));
// highlight repo and high-degree nodes
const deg=new Map();
obj.edges.forEach(e=>{deg.set((e.source||e.from),(deg.get(e.source||e.from)||0)+1);deg.set((e.target||e.to),(deg.get(e.target||e.to)||0)+1);});
graphNodes.forEach(n=>{if(n.type==="repo"||deg.get(n.id)>3)n.imp=true;});
const graphEdges=obj.edges.map(e=>[e.source||e.from,e.target||e.to]);
const types=new Set(graphNodes.map(n=>n.type));
const gId="resGraph_"+Date.now();
h+=`<div class="graph-container">
<div class="graph-svg-wrap"><svg id="${gId}" preserveAspectRatio="xMidYMid meet"></svg></div>
<div class="graph-legend">${buildGraphLegend(types)}
<span class="leg-note">${esc(label)} — ${(obj.meta||{}).repo_count||graphNodes.length} 个仓库节点, ${(obj.meta||{}).edge_count||graphEdges.length} 条关联边</span>
</div></div>`;
// defer drawing
setTimeout(()=>drawGraphIn(gId,{nodes:graphNodes,edges:graphEdges}),100);
}
// S6: plotly
else if(scenario==="s6"&&art.html){
const blob=URL.createObjectURL(new Blob([art.html],{type:"text/html"}));
h+=`<div class="viz-container"><iframe src="${blob}"></iframe></div>`;
}
// S1/S4: mermaid
else if((scenario==="s1"||scenario==="s4")&&art.mermaid){
const mId="resMmd_"+Date.now();
const mmd=art.mermaid.replace(/```mermaid|```/g,"");
h+=`<div class="mmd-container"><div class="mermaid" id="${mId}">${esc(mmd)}</div></div>`;
setTimeout(()=>{const el=document.getElementById(mId);if(el)el.removeAttribute("data-processed");
mermaid.run({nodes:["#"+mId]}).catch(()=>{});},100);
}
// S3: radar / scores
else if(scenario==="s3"&&obj){
const rs=obj.repro_score||0;const cs=obj.compliance_score||0;
h+=`<div class="score-display">
<div class="score-circle repro"><span class="val">${rs}</span><span class="label">复现性 / 10</span></div>
<div class="score-circle compliance"><span class="val">${cs}</span><span class="label">合规性 / 10</span></div>
</div>`;
}
// S5: weekly comparison + risks
else if(scenario==="s5"&&obj){
const ws=obj.week_stats||{};
const tw=ws.this_week||{};const lw=ws.last_week||{};
const maxC=Math.max(tw.commits||0,lw.commits||0,1);
const maxP=Math.max(tw.prs_merged||0,lw.prs_merged||0,1);
const maxI=Math.max(tw.issues_closed||0,lw.issues_closed||0,1);
h+=`<div class="weekly-bars">
<div style="font-weight:700;font-size:14px;margin-bottom:8px;color:var(--ink)">本周 vs 上周 对比</div>
<div class="week-row"><span class="label">Commits</span><div class="bar-bg"><div class="bar-fill last-week" style="width:${(lw.commits/maxC*100||0).toFixed(1)}%"><span class="bar-val">${lw.commits||0}</span></div><div class="bar-fill this-week" style="width:${(tw.commits/maxC*100||0).toFixed(1)}%;position:relative;margin-top:-28px"><span class="bar-val">${tw.commits||0}</span></div></div></div>
<div class="week-row"><span class="label">PR merged</span><div class="bar-bg"><div class="bar-fill last-week" style="width:${(lw.prs_merged/maxP*100||0).toFixed(1)}%"><span class="bar-val">${lw.prs_merged||0}</span></div><div class="bar-fill this-week" style="width:${(tw.prs_merged/maxP*100||0).toFixed(1)}%;position:relative;margin-top:-28px"><span class="bar-val">${tw.prs_merged||0}</span></div></div></div>
<div class="week-row"><span class="label">Issues</span><div class="bar-bg"><div class="bar-fill last-week" style="width:${(lw.issues_closed/maxI*100||0).toFixed(1)}%"><span class="bar-val">${lw.issues_closed||0}</span></div><div class="bar-fill this-week" style="width:${(tw.issues_closed/maxI*100||0).toFixed(1)}%;position:relative;margin-top:-28px"><span class="bar-val">${tw.issues_closed||0}</span></div></div></div>
</div>`;
// risk warnings
const risks=obj.risk_warnings||[];
if(risks.length){
h+=`<div style="margin-top:20px;font-weight:700;font-size:14px;color:var(--ink)">风险预警</div><div class="risk-list">`;
risks.forEach(r=>{const cls=r.level==="critical"?"critical":"warning";
h+=`<div class="risk-item ${cls}"><div class="type">${esc(r.level||"")} · ${esc(r.type||"")}</div><div class="msg">${esc(r.message||"")}</div>${r.suggestion?`<div class="suggestion">${esc(r.suggestion)}</div>`:""}</div>`;});
h+=`</div>`;
}
}
else{
h+=`<div class="empty-state"><p>该场景无可视化产物,详见下方报告。</p></div>`;
}
h+=`</div>`;
// ---- REPORT ----
if(art.report){
h+=`<div class="section"><div class="section-title"><span class="eyebrow">Full Report</span>完整报告</div>
<div class="report-content">${mdToHtml(art.report)}</div></div>`;
}
// ---- STRUCTURED CONCLUSION CARDS ----
const conclusions=buildConclusionCards(scenario,obj);
if(conclusions){
h+=`<div class="section"><div class="section-title"><span class="eyebrow">Conclusions</span>结构化结论</div>
<div class="cards-grid">${conclusions}</div></div>`;
}
document.getElementById("app").innerHTML=h;
}
/* ========== METRICS ========== */
function metricCard(label,val,note){
return `<div class="metric-card"><div class="label">${esc(label)}</div><div class="value">${esc(String(val))}</div><div class="note">${esc(note||"")}</div></div>`;
}
function metricsFor(key,o){
if(!o) return "";
const M=o.meta||{};
switch(key){
case "s1": return metricCard("commits",M.commit_count||0,"采样提交")+metricCard("merged PR",M.merged_pr_count||0,"已合并")+metricCard("docs",M.doc_count||0,"文档文件")+metricCard("创新点",(o.innovation_points||[]).length,"高影响合并");
case "s2": return metricCard("repos",M.repo_count||(o.nodes||[]).length,"仓库节点")+metricCard("scholars",M.scholar_count||0,"学者")+metricCard("topics",M.topic_count||0,"主题方向")+metricCard("edges",M.edge_count||(o.edges||[]).length,"关系边");
case "s3": return metricCard("复现性",(o.repro_score||0)+"/10","reproducibility")+metricCard("合规性",(o.compliance_score||0)+"/10","compliance")+metricCard("风险项",(o.risks||o.risk_items||[]).length,"项")+metricCard("许可证",esc(licOf(o)),"识别");
case "s4": return metricCard("缺口主题",(o.gap_topics||[]).length,"gap topics")+metricCard("推荐候选",(o.candidates||[]).length,"candidates")+metricCard("最高匹配",o.candidates&&o.candidates[0]?o.candidates[0].score:0,"top score")+metricCard("候选池",o.meta&&o.meta.pool_size||0,"pool size");
case "s5":{const tw=(o.week_stats&&o.week_stats.this_week)||{};return metricCard("本周 commits",tw.commits||0,"")+metricCard("预警",(o.risk_warnings||[]).length,"risks")+metricCard("PR 合并",tw.prs_merged||0,"")+metricCard("活跃度",(o.trend&&o.trend.activity_level)||"—","");}
case "s6":{const tl=o.timeline||{};const sm=a=>(a||[]).reduce((x,y)=>x+(y||0),0);return metricCard("周数",(tl.labels||[]).length,"")+metricCard("commits",sm(tl.commits),"")+metricCard("PRs",sm(tl.prs),"")+metricCard("issues",sm(tl.issues),"");}
}
return "";
}
/* ========== CONCLUSION CARDS ========== */
function buildConclusionCards(key,o){
if(!o) return "";
let cards="";
switch(key){
case "s1":{
const ips=o.innovation_points||[];
if(ips.length){
cards+=`<div class="conclusion-card innovation"><div class="card-title">&#128161; 创新点 (${ips.length})</div><div class="card-body">`;
ips.slice(0,8).forEach(i=>{cards+=`<p><strong>[${esc(i.category)}]</strong> ${esc(i.description)}<br><small style="color:var(--mute)">${esc(i.evidence||"")}</small></p>`;});
cards+=`</div></div>`;
}
break;}
case "s2":{
const scholars=o.core_scholars||[];
if(scholars.length){
cards+=`<div class="conclusion-card collab"><div class="card-title">&#128101; 核心学者</div><div class="card-body">`;
scholars.slice(0,6).forEach(s=>{cards+=`<p><strong>${esc(s.login)}</strong> — ${s.repo_count} 个仓库</p>`;});
cards+=`</div></div>`;
}
const topics=o.topic_heat||[];
if(topics.length){
cards+=`<div class="conclusion-card innovation"><div class="card-title">&#128293; 热门主题</div><div class="card-body">`;
topics.slice(0,6).forEach(t=>{cards+=`<p><strong>${esc(t.topic)}</strong> — ${t.count} 个仓库</p>`;});
cards+=`</div></div>`;
}
break;}
case "s3":{
const risks=o.risk_items||o.risks||[];
if(risks.length){
cards+=`<div class="conclusion-card risk"><div class="card-title">&#9888;&#65039; 风险项 (${risks.length})</div><div class="card-body">`;
risks.slice(0,8).forEach(r=>{
const lvl=(r.level||"").includes("high")||r.severity==="P0"?"&#x1F534;":"&#x1F7E1;";
cards+=`<p>${lvl} <strong>${esc(r.category||r.name||"")}</strong> — ${esc(r.detail||r.evidence||"")}</p>`;});
cards+=`</div></div>`;
}
break;}
case "s4":{
const cands=o.candidates||[];
if(cands.length){
cards+=`<div class="conclusion-card collab"><div class="card-title">&#129309; 协作推荐 (${cands.length})</div><div class="card-body">`;
cands.slice(0,6).forEach((c,i)=>{cards+=`<p><strong>#${i+1} ${esc(c.login)}</strong> (${c.score}分)<br><small>${(c.reasons||[]).join("")}</small></p>`;});
cards+=`</div></div>`;
}
const gaps=o.gap_topics||[];
if(gaps.length){
cards+=`<div class="conclusion-card innovation"><div class="card-title">&#128270; 缺口主题 (${gaps.length})</div><div class="card-body">`;
gaps.slice(0,6).forEach(g=>{cards+=`<p>${esc(typeof g==="string"?g:(g.topic||g.name||JSON.stringify(g)))}</p>`;});
cards+=`</div></div>`;
}
break;}
case "s5":{
const risks=o.risk_warnings||[];
if(risks.length){
cards+=`<div class="conclusion-card risk"><div class="card-title">&#9888;&#65039; 风险预警 (${risks.length})</div><div class="card-body">`;
risks.slice(0,6).forEach(w=>{cards+=`<p><strong>[${esc(w.type)}]</strong> ${esc(w.message)}${w.suggestion?"<br><small>"+esc(w.suggestion)+"</small>":""}</p>`;});
cards+=`</div></div>`;
}
const trend=o.trend||{};
cards+=`<div class="conclusion-card innovation"><div class="card-title">&#128200; 活跃趋势</div><div class="card-body"><p>commit 变化: <strong>${trend.commit_delta_pct||"—"}</strong></p><p>活跃度: <strong>${esc(trend.activity_level||"—")}</strong></p></div></div>`;
break;}
case "s6":{
const tl=o.timeline||{};
cards+=`<div class="conclusion-card innovation"><div class="card-title">&#128202; 数据概览</div><div class="card-body"><p>时间线: ${(tl.labels||[]).length} 周</p><p>语言分布: ${(o.language_pie||[]).length} 类</p><p>累计 commits: ${(tl.commits||[]).reduce((a,b)=>a+(b||0),0)}</p></div></div>`;
break;}
}
return cards;
}
/* go */
loadResult();
</script>
</body>
</html>

29
demo/Dockerfile Normal file
View File

@ -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-cliLinux ----------
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
# 演示网页 + Skillsserver.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"]

100
demo/README.md Normal file
View File

@ -0,0 +1,100 @@
# 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` 在 push 到 master 后SSH 到服务器增量拉取并**自动构建启动两个服务**
| 端口 | 服务 | 镜像 | 入口 |
|:---:|------|------|------|
| **:8080** | 任务四科研网页终端 | 根 `Dockerfile`Go + Python | `gitlink-cli server --port 8080`(调 `scripts/research/` 跑 S1S6 |
| **:8000** | 综合能力展示站(本 demo | `demo/Dockerfile` | `python3 demo/web/server.py` |
```
# ssh_cmd_0根 Dockerfile → :8080带 --env-file /root/.gitlink-env 注入 token
docker build -t gitlink-cli:latest . && docker run -d --name gitlink-cli -p 8080:8080 --env-file /root/.gitlink-env gitlink-cli:latest
# ssh_cmd_1demo Dockerfile → :8000非阻塞失败不影响 :8080
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. 阿里云安全组/防火墙**开放 8080 + 8000** 两条入方向 TCP 规则。
2. 在服务器建 `/root/.gitlink-env`,内容 `GITLINK_TOKEN=你的令牌`(供 :8080 科研终端调平台 API:8000 展示站不需要,访客自带 token
3. 之后每次 `git push origin master` → CI 自动重建双服务 → 直接打开网址:
- 科研终端 `http://121.41.222.73:8080`
- 综合展示 `http://121.41.222.73:8000`
> 手动部署(不走 CISSH 到服务器,`cd /root/gitlink-cli` 后分别跑上面两条 docker 命令。
### 镜像里有什么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` 环境变量,无需改。

96
demo/SHOWCASE.md Normal file
View File

@ -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 |

13
demo/build-demo.sh Normal file
View File

@ -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"

146
demo/live-demo-guide.md Normal file
View File

@ -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 维度评估)
**① 触发语**
> "我想参与 <owner>/<repo> 这个项目,帮我找几个适合新手的任务"
**② 预期 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 <owner> --repo <repo> --keyword "good first issue" --category opened
gitlink-cli repo +info --owner <owner> --repo <repo>
gitlink-cli repo +readme --owner <owner> --repo <repo>
```
**④ 讲解要点**
- **5 维度评估表**是设计亮点:把"哪个 Issue 适合新人"从主观判断变成可量化打分(指着 AI 输出的评分讲)
- 引导评论模板AI 能生成「欢迎贡献 + 代码定位 + 修改步骤」个性化评论(写操作,会先确认)
- 若无 good-first-issue 标签AI 应从开放 Issue 推荐最简单的(决策规则)
---
## 三、digest 实演(亮点:跨源聚合成简报)
**① 触发语**
> "给我一份 <owner>/<repo> 的项目简报,今天有什么动态"
**② 预期 AI 行为**:读 `digest/SKILL.md` → 并行采集 → 聚合分类 →
1. `issue +list --state open` + `pr +list`Issue/PR 动态)
2. `ci +builds`CI 状态)
3. `api GET "users/<me>/messages.json"`(通知)
4. 按 🔴需关注 / 🟢新增 / 🔵进行中 / 📊指标 分类,输出 Markdown 简报
**③ 手动备选**
```bash
gitlink-cli issue +list --state open --format json
gitlink-cli pr +list --format json
gitlink-cli ci +builds --owner <owner> --repo <repo> --format json
gitlink-cli api GET "users/<me>/messages.json"
```
**④ 讲解要点**
- **跨源聚合**是亮点:一份简报汇总 Issue/PR/CI/通知,不用挨个刷
- 与团队 `notification-digest` 分工它做通知中心标记已读digest 做项目全景(不做标记已读)—— 体现去重思考
- 纯只读,安全可随时跑
---
## 四、todo 实演(亮点:补上「我的」视角)
**① 触发语**
> "我的待办有哪些?哪些 Issue/PR 在等我处理"
**② 预期 AI 行为**:读 `todo/SKILL.md`
1. `api GET "users/me"`(识别身份)
2. `search +issues --assignee <me> --category opened`(分配我的)
3. `api GET "users/<me>/messages.json"`@我的)
4. `pr +list`(我的 PR 状态)
5. 按紧急度(@我 > 待 review > 指派)排序,输出待办清单
**③ 手动备选**
```bash
gitlink-cli api GET "users/me" --format json
gitlink-cli search +issues --assignee <me> --category opened
gitlink-cli api GET "users/<me>/messages.json"
```
**④ 讲解要点**
- **「我的」视角**是 gitlink 最缺的:跨 Issue/PR 汇总个人待办
- 紧急度排序逻辑:@我且停留 >24h → 🔴紧急;待 review 的 PR → 🟡本周
- 团队无对应 Skill是真正的新增价值
---
## 五、验收串场词5 分钟版)
```
开场30sSkills 让 AI 能驱动 gitlink-cli。先看 snippet 实演(跑 snippet-live-demo.sh
转场snippet 是本地功能。接下来演示需要平台 API 的 4 个 Skill
我用自然语言提问,看 AI 是否自主读 SKILL.md 编排命令。
① auth30s「检查登录状态」→ AI 调 auth status。
② onboarding1.5min):「找新手任务」→ AI 5 维度评估出推荐清单。(重点讲评估表)
③ digest1.5min):「给我项目简报」→ AI 跨源聚合出报告。(重点讲与团队分工)
④ todo1min「我的待办」→ AI 汇总排序。(重点讲个人视角是缺口)
收尾30s5 个新增 Skill 都能被 AI 正确调用snippet 7 命令实测通过。
```
---
## 六、安全清单(实演前确认)
- [ ] 用**测试仓库**演示,不用团队主仓库
- [ ] 写操作onboarding 引导评论、issue close让 AI **先确认 / --dry-run**
- [ ] 演示完 `auth logout` 的话,记得重新登录
- [ ] 只读命令list/view/search/info/messages可放心反复跑

59
demo/live-demo.sh Normal file
View File

@ -0,0 +1,59 @@
#!/usr/bin/env bash
# ============================================================
# 4 个 Skill 登录实演 · 辅助采集脚本
# 作用:把每个 Skill 的「只读采集命令」串起来自动跑,展示真实数据
# 分析(评估/聚合/排序)部分由 AI 在 Claude Code 里做——那才是亮点
# 用法bash demo/live-demo.sh <owner> <repo> [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→.exeLinux→无后缀
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 <owner> <repo> [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 "按回车键继续..."

View File

@ -0,0 +1,118 @@
# 代码质量看门人 · 工作流说明与架构(子任务三)
> 端到端自动化工作流PR 提交后自动跑完「采集 → AI Review → CI → 评论 → 质量判定/合并」。
> 对应 Skill`skills/gitlink-pr-guard/SKILL.md`;可复现脚本:`demo/pr-guard-workflow.sh`。
---
## 一、工作流架构图
```
┌─────────────────────────────────────────────┐
│ 触发PR 提交 / 更新 │
│ (或用户:帮我把关 PR #<id>
└──────────────────────┬──────────────────────┘
┌─────────────────────────────────────────────┐
│ 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.mdClaude Code 可读)✅ |
| 可复现执行脚本 | `demo/pr-guard-workflow.sh`(参数化)✅ |
| 真实 GitLink 项目演示 | 登录后对真实 PR 运行(见下) |
| 工作流说明 + 架构图 | 本文档 ✅ |
---
## 五、真实演示步骤(登录后)
```bash
# 1. 登录
gitlink-cli auth login
# 2. 找一个真实 PR
gitlink-cli pr +list --owner <owner> --repo <repo> --state open
# 3. 跑质量看门人流水线脚本采集AI 在 Claude Code 做 Step2 分析)
bash demo/pr-guard-workflow.sh <owner> <repo> <pr_id>
# 或在 Claude Code 里自然语言触发:
# "读 skills/gitlink-pr-guard/SKILL.md帮我把关 <owner>/<repo> 的 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` — 本文档(说明 + 架构图)
- [ ] 真实项目演示(登录后运行 + 截图/录屏)
- [ ] 报告(暂缓,后续按统一策略补《新需求构思》《变更影响测试》)

76
demo/pr-guard-workflow.sh Normal file
View File

@ -0,0 +1,76 @@
#!/usr/bin/env bash
# ============================================================
# 代码质量看门人 · 端到端工作流脚本(子任务三)
# 串联 5 步:采集 PR → AI Review → CI 检查 → 汇总评论 → 质量判定
# 用法bash demo/pr-guard-workflow.sh <owner> <repo> <pr_id>
# 例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→.exeLinux→无后缀
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 <owner> <repo> <pr_id>${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 2AI 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 3CI 检查 ----------
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-reviewReview+ ci构建+ api评论"
echo -e "\n${C}真实演示${N}:登录后对本仓库一个真实 PR 跑此脚本,由 AI 完成 Step 2 分析。"
echo -e "详见 ${Y}pr-guard-architecture.md${N}(工作流说明 + 架构图)"
read -p "按回车键继续..."

View File

@ -0,0 +1,104 @@
#!/usr/bin/env bash
# ============================================================
# 科研仓库画像 · 端到端工作流脚本(子任务四)
# 4 步:采集数据 → 四维评分 → 协作图谱 → 科研画像报告
# 用法bash demo/research-insight-workflow.sh <owner> <repo>
# 例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→.exeLinux→无后缀
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 <owner> <repo>${N}"
echo -e "${R}例 : bash $0 someresearch awesome-paper-code${N}"; exit 1
fi
echo -e "${G}${N} 分析对象: ${B}$OWNER/$REPO${N}(只读,不改数据)"
# ---------- Step 0fork 检测(避免给 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}科研核心满分10CI(+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 "按回车键继续..."

94
demo/snippet-live-demo.sh Normal file
View File

@ -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→.exeLinux→无后缀
# 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}其他 Skillonboarding / digest / todo涉及平台 API登录后可按其 SKILL.md 的「工作流」演示。${N}"
read -p "按回车键继续..."

56
demo/web/README.md Normal file
View File

@ -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.pyPython 标准库)
顶栏 token + owner/repo │ GET /api/skill 读 SKILL.md
命令域 / 终端 / Skill 墙 │ POST /api/run 真跑 CLItoken 透传给子进程)
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 tokenauth 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` 流水线 + 服务器部署说明)。

424
demo/web/index.html Normal file
View File

@ -0,0 +1,424 @@
<!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>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
:root { --bg:#0d1117; --panel:#161b22; --border:#30363d; --txt:#c9d1d9; --acc:#58a6ff; --green:#3fb950; --red:#f85149; --yellow:#d29922; }
body { background:var(--bg); color:var(--txt); font-family: -apple-system, "Segoe UI", "Microsoft YaHei", sans-serif; }
.panel { background:var(--panel); border:1px solid var(--border); }
.mono { font-family: "Cascadia Code", Consolas, "Courier New", monospace; }
#term-out { background:#010409; min-height:300px; max-height:440px; overflow-y:auto; padding:14px; }
.l-cmd { color:var(--acc); } .l-out { color:var(--txt); white-space:pre-wrap; word-break:break-all; }
.l-err { color:var(--red); } .l-muted { color:#6e7681; font-style:italic; }
#term-input { background:#010409; border-top:1px solid var(--border); }
.skill-card { transition:.2s; }
.skill-card:hover { border-color:var(--acc); transform:translateY(-2px); }
.step { transition:.3s; }
.step.active { border-color:var(--green); background:#1c2820; }
.verb { font-size:11px; padding:2px 7px; border-radius:4px; border:1px solid var(--border); background:#0d1117; cursor:pointer; transition:.15s; }
.verb:hover { border-color:var(--acc); color:var(--acc); }
.chip { background:#21262d; border:1px solid var(--border); }
.fbtn { font-size:12px; padding:4px 12px; border-radius:9999px; border:1px solid var(--border); cursor:pointer; transition:.15s; }
.fbtn.active { background:var(--acc); color:#000; border-color:var(--acc); }
details > summary { list-style:none; }
details > summary::-webkit-details-marker { display:none; }
details[open] > summary .arr { transform:rotate(90deg); }
.arr { display:inline-block; transition:.15s; }
#skill-modal-body h1,#skill-modal-body h2,#skill-modal-body h3,#skill-modal-body h4 { color:#fff; margin:.7em 0 .35em; font-weight:600; }
#skill-modal-body h1 { font-size:1.3em; border-bottom:1px solid var(--border); padding-bottom:.2em; }
#skill-modal-body h2 { font-size:1.15em; } #skill-modal-body h3 { font-size:1.02em; }
#skill-modal-body p { margin:.4em 0; line-height:1.6; }
#skill-modal-body table { border-collapse:collapse; margin:.5em 0; display:block; overflow-x:auto; }
#skill-modal-body th,#skill-modal-body td { border:1px solid var(--border); padding:4px 8px; text-align:left; font-size:.85em; }
#skill-modal-body th { background:#21262d; }
#skill-modal-body code { background:#010409; padding:1px 5px; border-radius:3px; color:var(--green); font-size:.85em; }
#skill-modal-body pre { background:#010409; padding:10px; border-radius:6px; overflow-x:auto; margin:.5em 0; border:1px solid var(--border); }
#skill-modal-body pre code { background:none; padding:0; color:var(--txt); }
#skill-modal-body strong { color:#fff; }
#skill-modal-body blockquote { border-left:3px solid var(--acc); padding-left:10px; color:#8b949e; margin:.5em 0; }
#skill-modal-body ul,#skill-modal-body ol { padding-left:1.4em; margin:.4em 0; }
#skill-modal-body hr { border-color:var(--border); margin:.8em 0; }
#skill-modal-body a { color:var(--acc); }
</style>
</head>
<body class="min-h-screen">
<!-- Header -->
<header class="border-b border-[var(--border)] panel">
<div class="max-w-7xl mx-auto px-6 py-5 flex items-center justify-between flex-wrap gap-4">
<div>
<h1 class="text-2xl font-bold text-white">🚀 GitLink CLI · 智能化能力展示</h1>
<p class="text-sm text-[#8b949e] mt-1">从「开发者工具」升级为「AI 可驱动平台」—— 命令 · Skills · 工作流 · 科研辅助</p>
</div>
<div class="flex gap-2 flex-wrap text-xs">
<span class="chip px-3 py-1.5 rounded-full">🛠 25 域 / 160+ 命令</span>
<span class="chip px-3 py-1.5 rounded-full">🧠 53 Skills</span>
<span class="chip px-3 py-1.5 rounded-full">🚪 pr-guard 工作流</span>
<span class="chip px-3 py-1.5 rounded-full">🔬 科研四维画像</span>
</div>
</div>
<div class="max-w-7xl mx-auto px-6 pb-4 flex items-center gap-3 flex-wrap text-sm">
<span class="text-[#8b949e] whitespace-nowrap">🔑 GitLink Token</span>
<input id="token-input" type="password" placeholder="粘贴你的 GitLink 个人访问令牌(仅存本机浏览器;公开仓库命令可免)" class="flex-1 min-w-[220px] bg-[#0d1117] border border-[var(--border)] rounded px-3 py-1.5 text-xs mono">
<span class="text-[#8b949e] whitespace-nowrap">📦 默认目标</span>
<input id="owner-input" value="Gitlink" class="w-28 bg-[#0d1117] border border-[var(--border)] rounded px-2 py-1.5 text-xs mono" placeholder="owner">
<span class="text-[#6e7681]">/</span>
<input id="repo-input" value="gitlink-cli" class="w-36 bg-[#0d1117] border border-[var(--border)] rounded px-2 py-1.5 text-xs mono" placeholder="repo">
<span id="token-state" class="text-xs"></span>
</div>
</header>
<main class="max-w-7xl mx-auto px-6 py-8 space-y-10">
<!-- ① 命令浏览器 + 参数构建 + 终端 -->
<section>
<h2 class="text-xl font-bold text-white mb-1">▶ 命令浏览器 <span class="text-sm text-[#8b949e] font-normal">(先选大方向 → 展开域 → 点动词填参数 → 真跑)</span></h2>
<p class="text-sm text-[#8b949e] mb-4">左侧点分类展开命令域;点动词在右侧「参数构建」里填参(搜索类命令的 keyword 等由你决定),回车或点▶运行。本地命令免 token。</p>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-4">
<!-- 左:折叠分层浏览器 -->
<div class="panel rounded-lg p-4">
<div class="flex items-center gap-2 mb-3">
<h3 class="font-semibold text-white">命令域</h3>
<input id="cmd-search" placeholder="🔍 搜索" class="flex-1 bg-[#0d1117] border border-[var(--border)] rounded px-2 py-1 text-xs mono">
</div>
<div id="cmd-groups" class="text-sm max-h-[460px] overflow-y-auto pr-1"></div>
</div>
<!-- 右:参数构建 + 终端 -->
<div class="panel rounded-lg lg:col-span-2 flex flex-col">
<!-- 参数构建条 -->
<div class="px-4 py-3 border-b border-[var(--border)] bg-[#0d1017]">
<div class="flex items-center gap-2 mb-2">
<span class="text-xs text-[var(--yellow)] font-semibold">🧩 参数构建</span>
<span id="builder-hint" class="text-xs text-[#6e7681]">点左侧动词开始</span>
</div>
<div id="builder-params" class="grid grid-cols-2 gap-2 mb-2"></div>
<div class="flex items-center gap-2">
<span class="text-[var(--green)] mono text-sm">$</span>
<input id="builder-cmd" class="flex-1 bg-[#010409] border border-[var(--border)] rounded px-2 py-1.5 text-xs mono text-[var(--green)]" placeholder="组装好的命令会显示在这里(可手改)" autocomplete="off">
<button onclick="runBuilder()" class="bg-[var(--green)] text-black px-3 py-1.5 rounded text-xs font-semibold whitespace-nowrap">▶ 运行</button>
</div>
</div>
<!-- 终端 -->
<div class="flex items-center gap-2 px-4 py-2 border-b border-[var(--border)] text-xs text-[#8b949e]">
<span class="w-3 h-3 rounded-full bg-[var(--red)]"></span><span class="w-3 h-3 rounded-full bg-[var(--yellow)]"></span><span class="w-3 h-3 rounded-full bg-[var(--green)]"></span>
<span class="ml-2">终端</span><span id="term-target" class="ml-auto text-[var(--acc)]"></span>
</div>
<div id="term-out" class="mono text-sm flex-1"></div>
<div class="flex items-center px-4 py-2 mono text-sm" id="term-input">
<span class="text-[var(--green)] mr-2">$</span>
<input id="cmd-input" class="flex-1 bg-transparent text-[var(--green)] mono" placeholder="或在此自由输入 gitlink-cli 命令回车" autocomplete="off">
</div>
</div>
</div>
</section>
<!-- ② Skill 卡片墙 -->
<section>
<div class="flex items-center justify-between flex-wrap gap-3 mb-4">
<h2 class="text-xl font-bold text-white">🧠 Skill 全集 <span class="text-sm text-[#8b949e] font-normal">53 个 · 点卡片读 SKILL.md 全文)</span></h2>
<div class="flex gap-2 flex-wrap">
<button class="fbtn active" onclick="filterSkill('all',this)">全部 53</button>
<button class="fbtn" onclick="filterSkill('new',this)">✨ 本次新增 7</button>
<button class="fbtn" onclick="filterSkill('research',this)">🔬 科研</button>
<button class="fbtn" onclick="filterSkill('quality',this)">🚪 代码质量</button>
</div>
</div>
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3" id="skill-wall"></div>
</section>
<!-- ③ 任务三 pr-guard -->
<section class="panel rounded-lg p-6">
<div class="flex items-center gap-2 mb-1"><h2 class="text-xl font-bold text-white">🚪 任务三:代码质量看门人</h2><span class="chip px-2 py-0.5 rounded text-xs">pr-guard</span></div>
<div class="text-sm text-[#8b949e] mb-3 space-y-1">
<p><b class="text-[var(--txt)]">是什么</b>PR 提交后自动跑完 5 步质量门禁 —— 串接 <code class="text-[var(--green)]">pr → code-review → ci → api → pr</code> 四个命令域。</p>
<p><b class="text-[var(--txt)]">门禁规则</b><span class="text-[var(--green)]">0 Critical + CI success → ✅ 合并</span>;否则 <span class="text-[var(--red)]">🔴 拒绝</span></p>
<p><b class="text-[var(--txt)]">与 code-review 区别</b>code-review 只做 Reviewpr-guard 是<b>完整闭环</b>采集→审查→CI→评论→判定/合并)。</p>
<p><b class="text-[var(--txt)]">任务三全家桶</b>(不止 pr-guardcode-review×pr-summary 闭环、community-ops-sweep 七段式周报wauxing+ 自动化 Skill 族 <code class="text-[var(--green)]">gatekeeper / commit-quality / issue-triage / issueops / release-auto / wiki-builder / pipeline-guardian / webhook-sentinel</code>(点下方 Skill 墙查看)。</p>
</div>
<div class="flex items-center justify-between gap-2 mb-5 flex-wrap" id="pr-steps"></div>
<div class="flex gap-2 flex-wrap">
<button onclick="runPipeline()" class="bg-[var(--acc)] text-black px-4 py-2 rounded font-semibold text-sm hover:opacity-90">▶ 模拟流水线</button>
<button onclick="livePR()" class="border border-[var(--border)] text-[var(--txt)] px-4 py-2 rounded text-sm hover:bg-[#21262d]">🔌 用真实 PR 跑(需 token</button>
</div>
<div id="pr-verdict" class="mt-4 text-sm mono"></div>
</section>
<!-- ④ 任务四 科研画像 -->
<section class="panel rounded-lg p-6">
<div class="flex items-center gap-2 mb-1"><h2 class="text-xl font-bold text-white">🔬 任务四:科研仓库画像</h2><span class="chip px-2 py-0.5 rounded text-xs">research-insight</span></div>
<div class="text-sm text-[#8b949e] mb-3 space-y-1">
<p><b class="text-[var(--txt)]">是什么</b>:四维科研评分(🔁可复现性 / 📈活跃度 / 📑引用价值 / 🤝协作健康)+ 贡献者协作网络 + 巴士因子。</p>
<p><b class="text-[var(--txt)]">区别于 health</b>health 看「工程维护好不好」,本工具看「<b class="text-[var(--txt)]">科研上值不值得引用/复现</b>」;含 <b class="text-[var(--txt)]">fork 检测</b>fork 自动改评 upstream</p>
<p><b class="text-[var(--txt)]">任务四全家桶</b>whale 主导,<b class="text-[var(--txt)]">S1S6 全生命周期</b><code class="text-[var(--green)]">research-insight(S1) / research-graph(S2) / compliance(S3) / collab-match(S4) / research-progress(S5) / research-visual(S6)</code> + research-fork-impact/scholar-profilePython 算法层 ~5800 行 + Go Web demo。</p>
<p><b class="text-[var(--txt)]">真实验证</b><code class="text-[var(--green)]">whale_hihihi/gitlink-cli</code> → 识别为 fork、巴士因子 38%、可复现性 8/10。</p>
</div>
<div class="flex items-center gap-2 mb-5 flex-wrap">
<span class="text-sm text-[#8b949e]">分析对象 = 顶栏 owner/repo</span>
<button onclick="analyze()" class="bg-[var(--green)] text-black px-4 py-2 rounded font-semibold text-sm hover:opacity-90">🔍 实拉分析</button>
<span id="analyze-status" class="text-xs text-[#8b949e]">(公开仓库可免 token</span>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div><canvas id="radar"></canvas><div id="repro-detail" class="text-xs text-[#8b949e] mt-3 mono"></div></div>
<div>
<h4 class="text-white font-semibold mb-2">协作网络图 <span id="bus-info" class="text-xs text-[#8b949e] font-normal">(点「实拉分析」用真实贡献者重绘)</span></h4>
<svg id="collab-svg" viewBox="0 0 360 260" class="w-full panel rounded border border-[var(--border)]"></svg>
<div id="repo-meta" class="text-xs text-[#8b949e] mt-2"></div>
</div>
</div>
</section>
<!-- ⑤ 验证 -->
<section>
<h2 class="text-xl font-bold text-white mb-4">✅ 验证:三层证据(对照模板法)</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-3">
<div class="panel rounded-lg p-4"><div class="text-[var(--green)] text-2xl mb-1"></div><h4 class="text-white font-semibold">命令层</h4><p class="text-sm text-[#8b949e] mt-1">命令真实执行,返回真实数据(非 unknown/401</p></div>
<div class="panel rounded-lg p-4"><div class="text-[var(--yellow)] text-2xl mb-1"></div><h4 class="text-white font-semibold">编排层</h4><p class="text-sm text-[#8b949e] mt-1">AI 按 SKILL.md 的顺序调命令</p></div>
<div class="panel rounded-lg p-4"><div class="text-[var(--acc)] text-2xl mb-1"></div><h4 class="text-white font-semibold">输出层</h4><p class="text-sm text-[#8b949e] mt-1">输出符合 SKILL.md 模板(判定/评分/清单)</p></div>
</div>
</section>
<footer class="text-center text-xs text-[#6e7681] py-6 border-t border-[var(--border)]">
GitLink CLI 智能化能力展示 · 子任务一~四 + DevOps · 后端 demo/web/server.py访客自带 token零凭据上云
</footer>
</main>
<script>
// ===== token & owner/repo =====
const tokenInput=document.getElementById('token-input'), ownerInput=document.getElementById('owner-input'), repoInput=document.getElementById('repo-input');
tokenInput.value=localStorage.getItem('gl_token')||'';
const tokenState=document.getElementById('token-state');
function syncTokenState(){ tokenState.textContent=tokenInput.value?'✅ 已提供':'⚠️ 未提供(公开仓库命令仍可跑)'; tokenState.style.color=tokenInput.value?'var(--green)':'var(--yellow)'; }
tokenInput.addEventListener('input',()=>{localStorage.setItem('gl_token',tokenInput.value);syncTokenState();}); syncTokenState();
const getToken=()=>tokenInput.value.trim(), getOwner=()=>ownerInput.value.trim()||'Gitlink', getRepo=()=>repoInput.value.trim()||'gitlink-cli';
function syncTarget(){ document.getElementById('term-target').textContent=getOwner()+'/'+getRepo(); } syncTarget();
[ownerInput,repoInput].forEach(el=>el.addEventListener('input',()=>{syncTarget();updateCmd();}));
// ===== 命令域25 域,按子任务分组)=====
const DOMAIN_GROUPS=[
{g:'资源管理(仓库/文件/版本)',open:true,domains:[
{d:'repo',v:['info','languages','contributors','readme','tree','code-stats','list','create','delete','fork','stargazers','watchers']},
{d:'file',v:['get','browse','create','update','delete']},
{d:'branch',v:['list','create','delete','protect','unprotect']},
{d:'release',v:['list','view','create','update','delete','download']},
{d:'search',v:['issues','repos','users']},
{d:'compare',v:['view','files']}]},
{g:'Issue 跟踪',domains:[
{d:'issue',v:['list','view','create','update','close','comment','batch-create','batch-update','batch-close','batch-assign','batch-label']},
{d:'label',v:['list','create','update','delete']},
{d:'milestone',v:['list','view','create','close','delete']}]},
{g:'PR 与代码审查',domains:[
{d:'pr',v:['list','view','diff','files','merge','reopen','comment','review','reviews','check-merge']}]},
{g:'CI/CD · 流水线 · 工作流',domains:[
{d:'ci',v:['builds','logs','restart','stop','enable','disable']},
{d:'pipeline',v:['list','runs','run','view','logs','results','save-yaml']},
{d:'workflow',v:['triage','health','pr-summary','repo-report']}]},
{g:'项目管理 · 协作',domains:[
{d:'pm',v:['boards','sprints','weekly','tags','pipelines','actions']},
{d:'org',v:['list','info','members','create']},
{d:'member',v:['list','add','remove']},
{d:'webhook',v:['list','view','create','update','delete','history','test']},
{d:'wiki',v:['list','view','create','update','delete']}]},
{g:'用户与画像',domains:[
{d:'user',v:['me','info','headmaps','stats-activity','stats-develop','trends']},
{d:'profile',v:['activity','ability','contribution','role']}]},
{g:'数据 · 合规 · 健康',domains:[
{d:'dataset',v:['list','view','create','update']},
{d:'license',v:['list']},
{d:'health',v:['fetch']}]},
{g:'本地工具(免登录)',open:true,domains:[
{d:'snippet',v:['create','list','view','search','update','delete','export']},
{d:'auth',v:['login','status','logout'],raw:true}]},
];
const LOCAL_DOMAINS=new Set(['snippet','auth','config','version','doctor']);
// 需要额外参数表单的动词flag 已核对 CLI --help
const FORM={
'search +issues':[{f:'-k',k:'keyword',req:true,ph:'如 good first issue'},{f:'-c',k:'category',sel:['opened','closed','all'],def:'opened'}],
'search +repos':[{f:'-k',k:'keyword',req:true,ph:'如 gitlink'}],
'search +users':[{f:'-k',k:'keyword',req:true,ph:'如用户名'}],
'issue +list':[{f:'-s',k:'state',sel:['open','closed','all'],def:'open'},{f:'-k',k:'keyword',ph:'可选关键词'}],
'issue +view':[{f:'-n',k:'number',req:true,ph:'Issue 编号URL 里)'}],
'pr +view':[{f:'-i',k:'id',req:true,ph:'PR 编号'}],
'file +get':[{f:'--path',k:'path',req:true,ph:'如 LICENSE / README.md'}],
'repo +tree':[{f:'--path',k:'path',ph:'目录路径,默认根'}],
'snippet +create':[{f:'--title',k:'title',req:true},{f:'--language',k:'language',ph:'python/go'},{f:'--tags',k:'tags',ph:'逗号分隔'},{f:'--content',k:'content',req:true,area:true}],
'snippet +view':[{f:'--id',k:'id',req:true,ph:'先 +list 取 id'}],
'snippet +search':[{f:'--query',k:'query',req:true,ph:'搜索词'}],
'snippet +delete':[{f:'--id',k:'id',req:true,ph:'先 +list 取 id'}],
};
// ===== 渲染折叠浏览器 =====
function renderDomains(q=''){
const Q=q.trim().toLowerCase(); let html='';
DOMAIN_GROUPS.forEach(grp=>{
const doms=grp.domains.filter(dm=>!Q||dm.d.includes(Q)||dm.v.some(x=>x.includes(Q)));
if(!doms.length) return;
html+=`<details class="mb-1" ${grp.open&&!Q?'open':''}><summary class="cursor-pointer text-xs text-[var(--yellow)] py-1 select-none hover:text-[var(--acc)]"><span class="arr"></span> ${grp.g} <span class="text-[#6e7681]">(${doms.length})</span></summary><div class="pl-2 mt-1 space-y-1.5">`;
doms.forEach(dm=>{
const local=LOCAL_DOMAINS.has(dm.d);
const tag=local?'<span class="text-[10px] text-[var(--green)]">本地</span>':'<span class="text-[10px] text-[#6e7681]">平台</span>';
const verbs=dm.v.filter(x=>!Q||x.includes(Q)||dm.d.includes(Q)).map(v=>{
const formTag=FORM[dm.d+' +'+v]?'<span class="text-[var(--acc)]"></span>':'';
return `<span class="verb" onclick="clickVerb('${dm.d}','+${v}')">${formTag}+${v}</span>`;
}).join(' ');
html+=`<div class="panel rounded p-2"><div class="mono text-xs text-[var(--acc)] mb-1">${dm.d} ${tag}</div><div class="flex flex-wrap gap-1">${verbs}</div></div>`;
});
html+=`</div></details>`;
});
document.getElementById('cmd-groups').innerHTML=html||'<p class="text-xs text-[#6e7681]">无匹配</p>';
}
renderDomains();
document.getElementById('cmd-search').addEventListener('input',e=>renderDomains(e.target.value));
// ===== 参数构建 =====
let currentVerb=null;
function clickVerb(domain,verb){
currentVerb={domain,verb,key:domain+' '+verb,local:LOCAL_DOMAINS.has(domain),form:FORM[domain+' '+verb]};
renderBuilder();
}
function buildCmd(){
const v=currentVerb; if(!v) return '';
let parts=['gitlink-cli',v.domain,v.verb];
if(v.form) v.form.forEach(p=>{
const el=document.getElementById('pf-'+p.k); let val=el?el.value.trim():'';
if(p.sel&&!val) val=p.def||'';
if(val) parts.push(p.f,val);
});
if(!v.local) parts.push('--owner',getOwner(),'--repo',getRepo());
return parts.join(' ');
}
function updateCmd(){ const c=buildCmd(); if(c) document.getElementById('builder-cmd').value=c; }
function renderBuilder(){
const v=currentVerb; const pe=document.getElementById('builder-params'); const hi=document.getElementById('builder-hint');
if(!v){ pe.innerHTML=''; hi.textContent='点左侧动词开始'; document.getElementById('builder-cmd').value=''; return; }
hi.innerHTML=`<code class="text-[var(--acc)]">${v.domain} ${v.verb}</code> · ${v.local?'本地命令':(v.form?'填参数后运行(自动带 owner/repo':'平台命令,自动带 owner/repo')}`;
if(v.form){
pe.innerHTML=v.form.map(p=>{
const req=p.req?'<span class="text-[var(--red)]">*</span>':'';
const label=`<label class="text-xs text-[#8b949e]">${p.k}${req}${p.req?'<span class="text-[10px]"> 必填</span>':''}</label>`;
if(p.sel) return `<div>${label}<select id="pf-${p.k}" class="w-full mt-0.5 bg-[#0d1117] border border-[var(--border)] rounded px-1 py-1 text-xs mono">${p.sel.map(s=>`<option ${s===p.def?'selected':''}>${s}</option>`).join('')}</select></div>`;
if(p.area) return `<div class="col-span-2">${label}<textarea id="pf-${p.k}" rows="2" placeholder="${p.ph||''}" class="w-full mt-0.5 bg-[#0d1117] border border-[var(--border)] rounded px-2 py-1 text-xs mono"></textarea></div>`;
return `<div>${label}<input id="pf-${p.k}" placeholder="${p.ph||''}" class="w-full mt-0.5 bg-[#0d1117] border border-[var(--border)] rounded px-2 py-1 text-xs mono"></div>`;
}).join('');
setTimeout(()=>v.form.forEach(p=>{const el=document.getElementById('pf-'+p.k);if(el){el.oninput=updateCmd;el.onchange=updateCmd;}}),0);
} else { pe.innerHTML=''; }
updateCmd();
}
function runBuilder(){ const c=document.getElementById('builder-cmd').value.trim(); if(c) runRaw(c); }
// ===== 终端 =====
const out=document.getElementById('term-out');
const input=document.getElementById('cmd-input');
let history=[],hidx=0;
function appendOut(text,cls='l-out'){const div=document.createElement('div');div.className='mono text-sm '+cls;div.textContent=text;out.appendChild(div);out.scrollTop=out.scrollHeight;}
async function runRaw(cmd){
if(!cmd||cmd.startsWith('#'))return;
history.push(cmd);hidx=history.length;
appendOut('$ '+cmd,'l-cmd');
const m=document.createElement('div');m.className='mono text-sm l-muted';m.textContent='⏳ 运行中...';out.appendChild(m);out.scrollTop=out.scrollHeight;
try{
const r=await fetch('/api/run',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({cmd,token:getToken()})});
const d=await r.json();m.remove();
if(d.stdout) appendOut(d.stdout,'l-out');
if(d.stderr) appendOut('[stderr] '+d.stderr,d.ok?'l-muted':'l-err');
if(!d.ok){
if(!d.stdout&&!d.stderr&&d.error) appendOut('❌ '+d.error,'l-err');
if(d.code!=null) appendOut('[退出码 '+d.code+']','l-err');
if(/缺少必需参数|required|missing/i.test(d.stderr||d.error||'')) appendOut('💡 该命令有必填参数,看上方「参数构建」填写','l-muted');
if(d.needs_token&&!d.token_provided&&/401|登录|未授权|token/i.test(d.stderr||d.error||'')) appendOut('💡 此命令可能需要 token顶栏填写','l-muted');
if(/timeout|handshake|refused|no such host|dial tcp/i.test(d.stderr||d.error||'')) appendOut('💡 网络连不上 GitLinkTLS/超时),稍后重试一次','l-muted');
if(/接口数据异常|\[-1\]|数据异常/i.test(d.stderr||d.error||'')) appendOut('💡 GitLink 接口对该仓库返回异常(该仓库可能无此类数据 / CI 未启用)','l-muted');
} else if(!d.stdout&&!d.stderr){ appendOut('(无输出)','l-muted'); }
}catch(e){m.remove();appendOut('❌ 请求失败:'+e+'(后端 server.py 是否启动?)','l-err');}
}
input.addEventListener('keydown',e=>{
if(e.key==='Enter'){const c=input.value.trim();input.value='';runRaw(c);}
else if(e.key==='ArrowUp'){if(hidx>0){hidx--;input.value=history[hidx]||'';e.preventDefault();}}
else if(e.key==='ArrowDown'){if(hidx<history.length){hidx++;input.value=history[hidx]||'';e.preventDefault();}}
});
// ===== Skill 全集 =====
const SKILLS=['auth','branch','ci','ci-health','code-review','collab-match','commit-quality','compare','competition-manager','compliance','contributor-insight','digest','file','gatekeeper','health','insight','issue','issue-tag','issue-triage','issueops','label','license-compliance','member','milestone','notification-digest','onboarding','org','pipeline','pipeline-guardian','pm','pr','pr-guard','release','release-auto','repo','research-fork-impact','research-graph','research-insight','research-progress','research-tracker','research-visual','scholar-profile','search','shared','snippet','stale-issue-manager','todo','user','webhook','webhook-sentinel','wiki','wiki-builder','workflow'];
const NEW_SKILLS=new Set(['onboarding','auth','snippet','digest','todo','pr-guard','research-insight']);
const SKILL_ICON={onboarding:'🚀',auth:'🔑',snippet:'📦',digest:'📰',todo:'📋','pr-guard':'🚪','research-insight':'🔬','code-review':'👁','commit-quality':'✨','health':'❤','release-auto':'🏷','workflow':'🔁','compliance':'✅','license-compliance':'📜','wiki-builder':'📚','pipeline-guardian':'🛡','webhook-sentinel':'📡'};
function skillCat(n){if(NEW_SKILLS.has(n))return'new';if(/research|scholar|contributor-insight|insight|fork-impact|tracker/.test(n))return'research';if(/code-review|commit-quality|gatekeeper|pr-guard|compliance|license-compliance/.test(n))return'quality';return'other';}
function skillEmoji(n){return SKILL_ICON[n]||(/research|scholar/.test(n)?'🔬':/wiki/.test(n)?'📚':/pipeline|ci|webhook/.test(n)?'🛠':'📁');}
let SKILL_FILTER='all';
function filterSkill(f,btn){SKILL_FILTER=f;document.querySelectorAll('.fbtn').forEach(b=>b.classList.remove('active'));btn.classList.add('active');renderSkills();}
function renderSkills(){
const list=SKILLS.filter(n=>SKILL_FILTER==='all'?true:(SKILL_FILTER==='new'?NEW_SKILLS.has(n):skillCat(n)===SKILL_FILTER));
document.getElementById('skill-wall').innerHTML=list.map(n=>{
const tag=NEW_SKILLS.has(n)?'<span class="text-[10px] text-[var(--green)]">✨新增</span>':(skillCat(n)==='research'?'<span class="text-[10px] text-[var(--acc)]">科研</span>':skillCat(n)==='quality'?'<span class="text-[10px] text-[var(--yellow)]">质量</span>':'');
return `<div class="skill-card panel rounded-lg p-3 cursor-pointer" onclick="openSkill('${n}')"><div class="text-xl mb-1">${skillEmoji(n)}</div><div class="text-white text-sm font-semibold mono">gitlink-${n}</div><div class="mt-1">${tag}</div><div class="text-[10px] text-[var(--green)] mt-2">📖 SKILL.md →</div></div>`;
}).join('');
}
renderSkills();
// ===== pr-guard =====
const STEPS=[{n:'① 采集',d:'pr +diff/+files',c:'#8b949e'},{n:'② AI Review',d:'分级找问题',c:'#d29922'},{n:'③ CI 检查',d:'ci +builds',c:'#58a6ff'},{n:'④ 汇总评论',d:'api reviews',c:'#a371f7'},{n:'⑤ 质量判定',d:'门禁规则',c:'#3fb950'}];
document.getElementById('pr-steps').innerHTML=STEPS.map((s,i)=>`<div class="step panel rounded p-3 text-center flex-1 min-w-[120px]" id="step-${i}"><div class="text-sm font-semibold text-white">${s.n}</div><div class="text-xs mono mt-1" style="color:${s.c}">${s.d}</div></div>${i<STEPS.length-1?'<span class="text-[#6e7681]"></span>':''}`).join('');
function runPipeline(){
document.getElementById('pr-verdict').textContent='';STEPS.forEach((_,i)=>document.getElementById('step-'+i).classList.remove('active'));
let i=0;const tick=setInterval(()=>{if(i>0)document.getElementById('step-'+(i-1)).classList.remove('active');if(i>=STEPS.length){clearInterval(tick);document.getElementById('pr-verdict').innerHTML='<span style="color:var(--green)">✅ 质量判定:通过</span> 0 Critical + CI success → 建议合并';return;}document.getElementById('step-'+i).classList.add('active');i++;},600);
}
async function livePR(){
runRaw(`pr +list --owner ${getOwner()} --repo ${getRepo()} --format json`);
}
// ===== 雷达 + 协作图 =====
let radarChart=new Chart(document.getElementById('radar'),{type:'radar',data:{labels:['🔁 可复现性','📈 活跃度','📑 引用价值','🤝 协作健康'],datasets:[{label:'示例(点「实拉分析」换真实数据)',data:[6,5,5,6],fill:true,backgroundColor:'rgba(88,166,255,0.18)',borderColor:'#58a6ff',pointBackgroundColor:'#58a6ff'}]},options:{plugins:{legend:{labels:{color:'#c9d1d9',font:{size:11}}}},scales:{r:{min:0,max:10,ticks:{color:'#6e7681',backdropColor:'transparent',stepSize:2},grid:{color:'#30363d'},pointLabels:{color:'#c9d1d9',font:{size:12}},angleLines:{color:'#30363d'}}}}});
function drawCollab(contribs,repoName){
const svg=document.getElementById('collab-svg');svg.innerHTML='';const cx=180,cy=130,R=95;
svg.innerHTML+=`<circle cx="${cx}" cy="${cy}" r="24" fill="#1f6feb"/><text x="${cx}" y="${cy+3}" text-anchor="middle" fill="#fff" font-size="9">${(repoName||'repo').slice(0,8)}</text>`;
const top=(contribs||[]).slice(0,6);if(!top.length){svg.innerHTML+='<text x="180" y="250" text-anchor="middle" fill="#6e7681" font-size="10">(点「实拉分析」用真实贡献者重绘)</text>';return;}
const max=top[0].contributions||1;
top.forEach((c,i)=>{const a=(-Math.PI/2)+i*(2*Math.PI/top.length),x=cx+Math.cos(a)*R,y=cy+Math.sin(a)*R,rad=Math.max(8,18*(c.contributions/max)),core=i<2;
svg.innerHTML+=`<line x1="${cx}" y1="${cy}" x2="${x}" y2="${y}" stroke="${core?'#3fb950':'#30363d'}" stroke-width="${core?2:1}" stroke-dasharray="${core?'':'4'}"/>`;
svg.innerHTML+=`<circle cx="${x}" cy="${y}" r="${rad}" fill="${core?'#238636':'#6e7681'}"/><text x="${x}" y="${y+3}" text-anchor="middle" fill="#fff" font-size="9">${(c.name||'?').slice(0,8)}</text><text x="${x}" y="${y+rad+12}" text-anchor="middle" fill="#8b949e" font-size="8">${c.perc||''}</text>`;});
}
drawCollab(null);
async function analyze(){
document.getElementById('analyze-status').textContent='⏳ 采集中...';
try{
const r=await fetch('/api/analyze',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({owner:getOwner(),repo:getRepo(),token:getToken()})});
const d=await r.json();if(!d.ok){document.getElementById('analyze-status').textContent='❌ '+d.error;return;}
const s=d.scores;radarChart.data.datasets[0].label=`${d.owner}/${d.repo}${d.is_fork?'(⚠️ fork of '+d.fork_from+'':''}`;
radarChart.data.datasets[0].data=[s.repro,s.activity,s.citation,s.collab];radarChart.update();
document.getElementById('analyze-status').innerHTML=`✅ ${d.contributor_count} 贡献者 · ${d.release_count} release · 协议 ${d.license}`;
document.getElementById('repo-meta').innerHTML=`${d.is_fork?'⚠️ <b style="color:var(--yellow)">是 fork</b>(引用应指 upstream '+d.fork_from+'':'✅ 独立仓库'} · 巴士因子 <b style="color:${d.bus_risk==='低'?'var(--green)':d.bus_risk==='中'?'var(--yellow)':'var(--red)'}">${d.bus_factor}%${d.bus_risk}风险)</b>`;
document.getElementById('repro-detail').innerHTML='可复现性 '+s.repro+'/'+d.repro_max+''+d.repro_detail.map(x=>x[1]?'✅'+x[0]:'❌'+x[0]).join(' · ');
drawCollab(d.contributors,d.name);
}catch(e){document.getElementById('analyze-status').textContent='❌ '+e;}
}
// 初始提示
appendOut('💡 左侧点分类展开 → 点动词(带 ⚙ 的有参数表单)→ 右侧填参 → ▶运行。','l-muted');
appendOut(' 本地命令snippet/auth免 token公开仓库的 repo/issue 等其实不填 token 也能跑。','l-muted');
// ===== Skill 详情模态框 =====
async function openSkill(name){
const modal=document.getElementById('skill-modal');
document.getElementById('skill-modal-title').textContent='📖 gitlink-'+name;
const body=document.getElementById('skill-modal-body');body.innerHTML='<p class="text-[#8b949e]">⏳ 加载 SKILL.md...</p>';modal.classList.remove('hidden');
try{const r=await fetch('/api/skill?name='+encodeURIComponent(name));const d=await r.json();if(!d.ok){body.innerHTML='<p class="l-err">❌ '+d.error+'</p>';return;}body.innerHTML=marked.parse(d.content);}catch(e){body.innerHTML='<p class="l-err">❌ '+e+'</p>';}
}
function closeSkill(){document.getElementById('skill-modal').classList.add('hidden');}
document.addEventListener('keydown',e=>{if(e.key==='Escape')closeSkill();});
</script>
<div id="skill-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center p-4" onclick="closeSkill()" style="background:rgba(0,0,0,.75)">
<div class="panel rounded-lg max-w-4xl w-full max-h-[88vh] flex flex-col" onclick="event.stopPropagation()">
<div class="flex items-center justify-between px-5 py-3 border-b border-[var(--border)]">
<h3 id="skill-modal-title" class="text-white font-bold text-lg"></h3>
<button onclick="closeSkill()" class="text-[#8b949e] hover:text-white text-3xl leading-none">×</button>
</div>
<div class="p-6 overflow-y-auto text-sm" id="skill-modal-body"></div>
</div>
</div>
</body>
</html>

319
demo/web/server.py Normal file
View File

@ -0,0 +1,319 @@
#!/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.pyCLI 在仓库根 ../../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-cliWindows=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.mdgitlink-{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)
# 失败时从 stderr 取首行作为 error前端绝不再显示 undefined
err_msg = None
if code != 0:
first = (err.strip() or out.strip()).splitlines()
err_msg = first[0][:200] if first else f"命令失败(退出码 {code}"
self._json({
"ok": code == 0, "cmd": f"gitlink-cli {' '.join(args)}",
"stdout": out, "stderr": err, "code": code, "error": err_msg,
"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.ThreadingMixIn, socketserver.TCPServer):
allow_reuse_address = True
daemon_threads = 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已停止")

BIN
gitlink-cli.exe Normal file

Binary file not shown.

BIN
gitlink-cli.exe~ Normal file

Binary file not shown.

View File

@ -41,19 +41,34 @@ func New() (*Client, error) {
}, nil
}
// Do makes an API call with automatic .json suffix appended.
func (c *Client) Do(method, path string, body interface{}, query url.Values) (*output.Envelope, error) {
path = normalizeAPIPath(c.BaseURL, path)
return c.do(method, path, body, query, true, "json")
}
// Append .json suffix if not already present (GitLink API convention)
// Handle paths that may already contain query strings (e.g., /path?key=val)
if idx := strings.Index(path, "?"); idx != -1 {
basePath := path[:idx]
queryStr := path[idx:]
if shouldAppendJSONSuffix(basePath) {
path = basePath + ".json" + queryStr
// DoRaw makes an API call without appending .json suffix.
func (c *Client) DoRaw(method, path string, body interface{}, query url.Values) (*output.Envelope, error) {
return c.do(method, path, body, query, false, "json")
}
// DoForm makes an API call with form-encoded body (no .json suffix).
// Used for Wiki and other endpoints that expect application/x-www-form-urlencoded.
func (c *Client) DoForm(method, path string, body url.Values, query url.Values) (*output.Envelope, error) {
return c.do(method, path, body, query, false, "form")
}
func (c *Client) do(method, path string, body interface{}, query url.Values, appendJSON bool, encoding string) (*output.Envelope, error) {
if appendJSON {
if idx := strings.Index(path, "?"); idx != -1 {
basePath := path[:idx]
queryStr := path[idx:]
if shouldAppendJSONSuffix(basePath) {
path = basePath + ".json" + queryStr
}
} else if shouldAppendJSONSuffix(path) {
path += ".json"
}
} else if shouldAppendJSONSuffix(path) {
path += ".json"
}
fullURL := c.BaseURL + path
if len(query) > 0 {
@ -64,14 +79,26 @@ func (c *Client) Do(method, path string, body interface{}, query url.Values) (*o
fullURL += sep + query.Encode()
}
// Replace path params
var bodyData []byte
var bodyReader io.Reader
var contentType string
if body != nil {
data, err := json.Marshal(body)
if err != nil {
return nil, err
if encoding == "form" {
formValues, ok := body.(url.Values)
if !ok {
return nil, fmt.Errorf("DoForm requires url.Values body")
}
bodyData = []byte(formValues.Encode())
contentType = "application/x-www-form-urlencoded"
} else {
var err error
bodyData, err = json.Marshal(body)
if err != nil {
return nil, err
}
contentType = "application/json"
}
bodyReader = bytes.NewReader(data)
bodyReader = bytes.NewReader(bodyData)
}
req, err := http.NewRequest(method, fullURL, bodyReader)
@ -79,8 +106,15 @@ func (c *Client) Do(method, path string, body interface{}, query url.Values) (*o
return nil, err
}
if contentType != "" {
req.Header.Set("Content-Type", contentType)
}
if c.Debug {
fmt.Printf("-> %s %s\n", method, fullURL)
fmt.Printf("→ %s %s\n", method, fullURL)
if bodyData != nil {
fmt.Printf(" body: %s\n", string(bodyData))
}
}
resp, err := c.HTTP.Do(req)
@ -95,10 +129,9 @@ func (c *Client) Do(method, path string, body interface{}, query url.Values) (*o
}
if c.Debug {
fmt.Printf("<- %d %s\n", resp.StatusCode, string(respData[:min(len(respData), 200)]))
fmt.Printf(" %d %s\n", resp.StatusCode, string(respData[:min(len(respData), 200)]))
}
// Check HTTP-level errors
if resp.StatusCode >= 400 {
return nil, &APIError{
StatusCode: resp.StatusCode,
@ -107,10 +140,8 @@ func (c *Client) Do(method, path string, body interface{}, query url.Values) (*o
}
}
// Parse JSON
var raw map[string]interface{}
if err := json.Unmarshal(respData, &raw); err != nil {
// Not JSON, return as-is
return output.SuccessEnvelope(string(respData), nil), nil
}
@ -147,7 +178,6 @@ func (c *Client) Do(method, path string, body interface{}, query url.Values) (*o
}
}
// Auto-parse JSON string data (GitLink API quirk: some endpoints return data as JSON string)
if dataStr, ok := raw["data"].(string); ok {
var parsedData interface{}
if err := json.Unmarshal([]byte(dataStr), &parsedData); err == nil {
@ -155,7 +185,6 @@ func (c *Client) Do(method, path string, body interface{}, query url.Values) (*o
}
}
// Build meta from pagination info
var meta *output.Meta
if tc, ok := raw["total_count"]; ok {
meta = &output.Meta{}
@ -177,11 +206,6 @@ func shouldAppendJSONSuffix(path string) bool {
if strings.HasSuffix(path, ".json") {
return false
}
// Wiki open endpoints are served by gateway.gitlink.org.cn which does not
// accept the .json suffix used by the www.gitlink.org.cn API convention.
if strings.Contains(path, "/wiki/open/") {
return false
}
parts := strings.Split(strings.Trim(path, "/"), "/")
for i, part := range parts {
if part == "raw" && i >= 2 && i+2 < len(parts) {

View File

@ -23,12 +23,15 @@
"cmd.config.short": "Manage gitlink-cli configuration",
"cmd.doctor.long": "Run local diagnostics for gitlink-cli configuration, authentication, repository context and API connectivity.",
"cmd.doctor.short": "Diagnose gitlink-cli environment problems",
"cmd.issue.batch_close.long": "Close filtered issues in bulk.\n\nThis command defaults to dry-run mode and only prints matching issues.\nPass --yes to execute remote close operations. Use restrictive filters and a small limit.\n\nExamples:\n gitlink-cli issue +batch-close --owner Gitlink --repo gitlink-cli --older-than-days 60 --limit 20\n gitlink-cli issue +batch-close --owner Gitlink --repo gitlink-cli --older-than-days 60 --limit 20 --yes",
"cmd.issue.batch_close.short": "Close filtered issues in bulk. Defaults to dry-run; pass --yes to execute.",
"cmd.issue.batch_label.long": "Add a label to filtered issues in bulk.\n\nThis command defaults to dry-run mode and only prints matching issues.\nPass --yes to execute remote label operations. The current implementation does not fake label writes when the API endpoint is unavailable.\n\nExamples:\n gitlink-cli issue +batch-label --owner Gitlink --repo gitlink-cli --add-label stale --older-than-days 30 --limit 50\n gitlink-cli issue +batch-label --owner Gitlink --repo gitlink-cli --add-label stale --older-than-days 30 --limit 50 --yes",
"cmd.issue.batch_label.short": "Add a label to filtered issues in bulk. Defaults to dry-run; pass --yes to execute.",
"cmd.issue.batch_list.long": "List issue batch maintenance candidates without changing remote data.\n\nExamples:\n gitlink-cli issue +batch-list --owner Gitlink --repo gitlink-cli --state open --older-than-days 30 --limit 50 --format table\n gitlink-cli issue +batch-list --owner Gitlink --repo gitlink-cli --label bug --format json",
"cmd.issue.batch_list.short": "List issue batch maintenance candidates without changing remote data",
"cmd.issue.batch_assign.short": "Assign issues to a user or via CSV",
"cmd.issue.batch_close.long": "Close multiple issues. Pass issue numbers via --numbers or read from a CSV via --from.\n\nDefaults to dry-run; pass --confirm to execute.",
"cmd.issue.batch_close.short": "Close multiple issues by issue numbers or a CSV file",
"cmd.issue.batch_create.short": "Create multiple issues from CSV",
"cmd.issue.batch_delete.short": "Batch delete multiple issues (use with caution)",
"cmd.issue.batch_label.long": "Batch add, remove, or set labels on multiple issues.\n\nDefaults to dry-run; pass --confirm to execute.",
"cmd.issue.batch_label.short": "Add, remove, or set labels on multiple issues",
"cmd.issue.batch_open.short": "Reopen multiple issues",
"cmd.issue.batch_update.short": "Update multiple issues via CSV or --ids",
"cmd.issue.close.short": "Close an issue",
"cmd.issue.comment.short": "Add a comment to an issue",
"cmd.issue.create.short": "Create a new issue",
@ -68,12 +71,19 @@
"cmd.repo.tree.short": "List repository files and directories",
"cmd.root.long": "Manage repositories, issues, pull requests, releases, CI and workflows on GitLink.",
"cmd.root.short": "GitLink CLI - command-line tool for GitLink",
"cmd.search.issues.short": "Search issues in a repository",
"cmd.search.repos.short": "Search repositories",
"cmd.search.short": "Search operations",
"cmd.search.users.short": "Search users",
"cmd.user.headmaps.short": "Show user contribution heatmap",
"cmd.user.info.short": "Show user profile",
"cmd.user.me.short": "Show current authenticated user",
"cmd.user.short": "User operations",
"cmd.user.stats_activity.short": "Show user activity statistics",
"cmd.user.stats_develop.short": "Show user development capability",
"cmd.user.stats_major.short": "Show user major positioning",
"cmd.user.stats_role.short": "Show user role positioning",
"cmd.user.trends.short": "Show user project activity trends",
"cmd.version.short": "Print version information",
"cmd.webhook.create.short": "Create a repository webhook",
"cmd.webhook.delete.short": "Delete a repository webhook",
@ -130,13 +140,36 @@
"flag.issue.assignee": "Assignee login",
"flag.issue.assignee_id": "Assignee user ID",
"flag.issue.author_id": "Author user ID",
"flag.issue.batch.reason": "Optional reason shown in the batch result",
"flag.issue.batch.yes": "Execute remote operations. Without this flag the command is dry-run only.",
"flag.issue.batch_close.older_than_days": "Required safety filter; must be at least 7",
"flag.issue.batch_close.state": "Filter by issue state before closing",
"flag.issue.batch_label.state": "Filter by issue state",
"flag.issue.batch_list.limit": "Maximum issues to return, capped at 100",
"flag.issue.batch_process.limit": "Maximum issues to process, capped at 100",
"flag.issue.batch.confirm": "Confirm batch operation",
"flag.issue.batch.delay": "Delay in milliseconds between requests",
"flag.issue.batch.dry_run": "Preview the issues that would be changed without making any changes",
"flag.issue.batch.from": "Read issue numbers from a CSV file. Supports a number/issue_number/project_issues_index column or first column without header",
"flag.issue.batch.label": "Filter by label name",
"flag.issue.batch.max": "Maximum number of issues to process",
"flag.issue.batch.numbers": "Comma-separated issue numbers from the web URL, for example: 1,2,3",
"flag.issue.batch.search": "Search issues by keyword",
"flag.issue.batch.state": "Filter by state: open, closed, all",
"flag.issue.batch_assign.assignee": "Assignee username or ID (uniform mode)",
"flag.issue.batch_assign.csv": "CSV file with number,assignee columns",
"flag.issue.batch_assign.numbers": "Comma-separated issue numbers",
"flag.issue.batch_close.state": "Filter by state before closing",
"flag.issue.batch_create.csv": "CSV file with issue data",
"flag.issue.batch_create.print_schema": "Print CSV header and exit",
"flag.issue.batch_delete.confirm": "Confirm deletion (required for safety)",
"flag.issue.batch_delete.dry_run": "Preview deletion without executing",
"flag.issue.batch_delete.ids": "Comma-separated issue IDs",
"flag.issue.batch_label.action": "Action: add, remove, or set",
"flag.issue.batch_label.csv": "CSV file path with issue numbers",
"flag.issue.batch_label.label_ids": "Comma-separated label IDs (mutually exclusive with --labels)",
"flag.issue.batch_label.labels": "Comma-separated label names",
"flag.issue.batch_label.numbers": "Comma-separated issue numbers",
"flag.issue.batch_update.assignees": "Comma-separated assignee user IDs",
"flag.issue.batch_update.csv": "CSV file path with updates",
"flag.issue.batch_update.ids": "Comma-separated issue IDs",
"flag.issue.batch_update.milestone": "Milestone ID",
"flag.issue.batch_update.priority": "Priority ID",
"flag.issue.batch_update.status": "New status: open or closed",
"flag.issue.batch_update.tags": "Comma-separated label/tag IDs",
"flag.issue.body": "Issue description",
"flag.issue.label": "Label ID",
"flag.issue.label_filter": "Filter by existing label",
@ -190,6 +223,11 @@
"flag.repo.private": "Make repository private (true/false)",
"flag.repo.tree.path": "Directory path to list (default: repository root)",
"flag.repo.tree.ref": "Branch, tag, or commit ref",
"flag.search.issues.assignee": "Filter by assignee user ID",
"flag.search.issues.author": "Filter by author user ID",
"flag.search.issues.category": "Issue category: all, opened, closed",
"flag.search.issues.milestone": "Filter by milestone ID",
"flag.search.issues.tag": "Filter by tag IDs (comma-separated)",
"flag.search.keyword": "Search keyword",
"flag.sort_by": "Sort field",
"flag.sort_direction": "Sort direction: asc, desc",

View File

@ -23,12 +23,15 @@
"cmd.config.short": "管理 gitlink-cli 配置",
"cmd.doctor.long": "诊断 gitlink-cli 的配置、认证、仓库上下文和 API 连通性问题。",
"cmd.doctor.short": "诊断 gitlink-cli 环境问题",
"cmd.issue.batch_close.long": "批量关闭筛选后的议题。\n\n该命令默认处于 dry-run 模式,只打印匹配的议题。\n传入 --yes 后执行远端关闭操作。请使用严格筛选条件和较小 limit。\n\n示例\n gitlink-cli issue +batch-close --owner Gitlink --repo gitlink-cli --older-than-days 60 --limit 20\n gitlink-cli issue +batch-close --owner Gitlink --repo gitlink-cli --older-than-days 60 --limit 20 --yes",
"cmd.issue.batch_close.short": "批量关闭筛选后的议题。默认 dry-run传入 --yes 后执行。",
"cmd.issue.batch_label.long": "给筛选后的议题批量添加标签。\n\n该命令默认处于 dry-run 模式,只打印匹配的议题。\n传入 --yes 后执行远端标签操作。当前实现不会在 API 端点不可用时伪造写入结果。\n\n示例\n gitlink-cli issue +batch-label --owner Gitlink --repo gitlink-cli --add-label stale --older-than-days 30 --limit 50\n gitlink-cli issue +batch-label --owner Gitlink --repo gitlink-cli --add-label stale --older-than-days 30 --limit 50 --yes",
"cmd.issue.batch_label.short": "给筛选后的议题批量添加标签。默认 dry-run传入 --yes 后执行。",
"cmd.issue.batch_list.long": "列出议题批量维护候选项,不修改远端数据。\n\n示例\n gitlink-cli issue +batch-list --owner Gitlink --repo gitlink-cli --state open --older-than-days 30 --limit 50 --format table\n gitlink-cli issue +batch-list --owner Gitlink --repo gitlink-cli --label bug --format json",
"cmd.issue.batch_list.short": "列出议题批量维护候选项,不修改远端数据",
"cmd.issue.batch_assign.short": "批量指派议题负责人",
"cmd.issue.batch_close.long": "批量关闭多个议题。支持 --numbers 直接传入编号,或 --from 从 CSV 读取。\n\n默认 dry-run传入 --confirm 后执行。",
"cmd.issue.batch_close.short": "批量关闭多个议题(按编号或 CSV",
"cmd.issue.batch_create.short": "从 CSV 批量创建议题",
"cmd.issue.batch_delete.short": "批量删除多个议题(谨慎使用)",
"cmd.issue.batch_label.long": "批量给多个议题添加、移除或设置标签。\n\n默认 dry-run传入 --confirm 后执行。",
"cmd.issue.batch_label.short": "批量管理议题标签(添加/移除/设置)",
"cmd.issue.batch_open.short": "批量重新打开多个议题",
"cmd.issue.batch_update.short": "批量更新议题(按 CSV 或 ID",
"cmd.issue.close.short": "关闭议题",
"cmd.issue.comment.short": "给议题添加评论",
"cmd.issue.create.short": "创建新议题",
@ -68,12 +71,19 @@
"cmd.repo.tree.short": "列出仓库文件和目录",
"cmd.root.long": "用于管理 GitLink 上的仓库、议题、拉取请求、发布、CI 和工作流。",
"cmd.root.short": "GitLink CLI - GitLink 命令行工具",
"cmd.search.issues.short": "搜索仓库议题",
"cmd.search.repos.short": "搜索仓库",
"cmd.search.short": "搜索操作",
"cmd.search.users.short": "搜索用户",
"cmd.user.headmaps.short": "显示用户贡献热力图",
"cmd.user.info.short": "显示用户资料",
"cmd.user.me.short": "显示当前认证用户",
"cmd.user.short": "用户操作",
"cmd.user.stats_activity.short": "显示用户活动统计",
"cmd.user.stats_develop.short": "显示用户开发能力",
"cmd.user.stats_major.short": "显示用户专业/学科定位",
"cmd.user.stats_role.short": "显示用户角色定位",
"cmd.user.trends.short": "显示用户项目活动趋势",
"cmd.version.short": "打印版本信息",
"cmd.webhook.create.short": "创建仓库 Webhook",
"cmd.webhook.delete.short": "删除仓库 Webhook",
@ -130,13 +140,36 @@
"flag.issue.assignee": "负责人登录名",
"flag.issue.assignee_id": "负责人用户 ID",
"flag.issue.author_id": "作者用户 ID",
"flag.issue.batch.reason": "批量结果中显示的可选原因",
"flag.issue.batch.yes": "执行远端操作。未传入该参数时仅 dry-run。",
"flag.issue.batch_close.older_than_days": "必需的安全筛选条件;至少为 7",
"flag.issue.batch.confirm": "确认执行批量操作",
"flag.issue.batch.delay": "请求间隔(毫秒)",
"flag.issue.batch.dry_run": "预览将被修改的议题,不实际执行",
"flag.issue.batch.from": "从 CSV 文件读取议题编号(支持 number/issue_number/project_issues_index 列)",
"flag.issue.batch.label": "按标签名筛选",
"flag.issue.batch.max": "最多处理的议题数",
"flag.issue.batch.numbers": "议题编号列表(逗号分隔),例如 1,2,3",
"flag.issue.batch.search": "按关键词搜索议题",
"flag.issue.batch.state": "按状态筛选open、closed、all",
"flag.issue.batch_assign.assignee": "负责人用户名或 ID统一模式",
"flag.issue.batch_assign.csv": "CSV 文件(含 number,assignee 列)",
"flag.issue.batch_assign.numbers": "议题编号列表(逗号分隔)",
"flag.issue.batch_close.state": "关闭前按议题状态筛选",
"flag.issue.batch_label.state": "按议题状态筛选",
"flag.issue.batch_list.limit": "最多返回的议题数,上限 100",
"flag.issue.batch_process.limit": "最多处理的议题数,上限 100",
"flag.issue.batch_create.csv": "含议题数据的 CSV 文件",
"flag.issue.batch_create.print_schema": "打印 CSV 表头并退出",
"flag.issue.batch_delete.confirm": "确认删除(安全必需)",
"flag.issue.batch_delete.dry_run": "预览删除,不实际执行",
"flag.issue.batch_delete.ids": "议题 ID 列表(逗号分隔)",
"flag.issue.batch_label.action": "操作类型add、remove 或 set",
"flag.issue.batch_label.csv": "含议题编号的 CSV 文件路径",
"flag.issue.batch_label.label_ids": "标签 ID 列表(逗号分隔,与 --labels 互斥)",
"flag.issue.batch_label.labels": "标签名列表(逗号分隔)",
"flag.issue.batch_label.numbers": "议题编号列表(逗号分隔)",
"flag.issue.batch_update.assignees": "负责人用户 ID 列表(逗号分隔)",
"flag.issue.batch_update.csv": "含更新数据的 CSV 文件路径",
"flag.issue.batch_update.ids": "议题 ID 列表(逗号分隔)",
"flag.issue.batch_update.milestone": "里程碑 ID",
"flag.issue.batch_update.priority": "优先级 ID",
"flag.issue.batch_update.status": "新状态open 或 closed",
"flag.issue.batch_update.tags": "标签/标记 ID 列表(逗号分隔)",
"flag.issue.body": "议题描述",
"flag.issue.label": "标签 ID",
"flag.issue.label_filter": "按已有标签筛选",
@ -190,6 +223,11 @@
"flag.repo.private": "设为私有仓库true/false",
"flag.repo.tree.path": "要列出的目录路径(默认:仓库根目录)",
"flag.repo.tree.ref": "分支、标签或提交引用",
"flag.search.issues.assignee": "按负责人用户 ID 筛选",
"flag.search.issues.author": "按作者用户 ID 筛选",
"flag.search.issues.category": "议题分类all、opened、closed",
"flag.search.issues.milestone": "按里程碑 ID 筛选",
"flag.search.issues.tag": "按标签 ID 筛选(逗号分隔)",
"flag.search.keyword": "搜索关键词",
"flag.sort_by": "排序字段",
"flag.sort_direction": "排序方向asc、desc",

View File

@ -74,6 +74,11 @@ func printTable(w io.Writer, envelope *Envelope) error {
return nil
}
// Detect and render diff data in git-diff style
if isDiffData(envelope.Data) {
return printDiffTable(w, envelope)
}
// Try to render as table if data is a slice of maps
switch data := envelope.Data.(type) {
case []interface{}:
@ -239,3 +244,99 @@ func formatValue(v interface{}) string {
return fmt.Sprintf("%v", v)
}
}
// isDiffData checks whether the envelope data is a PR diff response with sections.
// Distinguishes from the simpler files listing by checking for sections in files.
func isDiffData(data interface{}) bool {
m, ok := data.(map[string]interface{})
if !ok {
return false
}
files, hasFiles := m["files"].([]interface{})
if !hasFiles || len(files) == 0 {
return false
}
// Diff data has files with "sections"; simple file listing does not.
firstFile, ok := files[0].(map[string]interface{})
if !ok {
return false
}
_, hasSections := firstFile["sections"]
return hasSections
}
// printDiffTable renders diff data in git-diff style text output.
func printDiffTable(w io.Writer, envelope *Envelope) error {
data, ok := envelope.Data.(map[string]interface{})
if !ok {
return printJSON(w, envelope)
}
files, ok := data["files"].([]interface{})
if !ok {
return printJSON(w, envelope)
}
// Summary header
fileNums, _ := data["file_nums"].(float64)
totalAdd, _ := data["total_addition"].(float64)
totalDel, _ := data["total_deletion"].(float64)
fmt.Fprintf(w, " %d files changed, %d insertions(+), %d deletions(-)\n\n",
int(fileNums), int(totalAdd), int(totalDel))
for _, f := range files {
fm, ok := f.(map[string]interface{})
if !ok {
continue
}
name, _ := fm["name"].(string)
addition, _ := fm["addition"].(float64)
deletion, _ := fm["deletion"].(float64)
// File header
fmt.Fprintf(w, "diff --git a/%s b/%s\n", name, name)
if isCreated, _ := fm["is_created"].(bool); isCreated {
fmt.Fprintf(w, "new file\n")
}
if isDeleted, _ := fm["is_deleted"].(bool); isDeleted {
fmt.Fprintf(w, "deleted file\n")
}
fmt.Fprintf(w, "--- a/%s\n", name)
fmt.Fprintf(w, "+++ b/%s\n", name)
fmt.Fprintf(w, "@@ +%d -%d @@\n", int(addition), int(deletion))
// Render each line
sections, _ := fm["sections"].([]interface{})
for _, sec := range sections {
secMap, ok := sec.(map[string]interface{})
if !ok {
continue
}
lines, _ := secMap["lines"].([]interface{})
for _, l := range lines {
lineMap, ok := l.(map[string]interface{})
if !ok {
continue
}
content, _ := lineMap["content"].(string)
lineType, _ := lineMap["type"].(float64)
switch int(lineType) {
case 4: // diff hunk header
fmt.Fprintf(w, "%s\n", content)
case 2: // addition
fmt.Fprintf(w, "%s\n", content)
case 3: // deletion
fmt.Fprintf(w, "%s\n", content)
default: // context line
fmt.Fprintf(w, "%s\n", content)
}
}
}
fmt.Fprintln(w)
}
return nil
}

89
internal/snippet/store.go Normal file
View File

@ -0,0 +1,89 @@
package snippet
import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"os"
"path/filepath"
"time"
)
// Snippet represents a locally stored code snippet.
type Snippet struct {
ID string `json:"id"`
Title string `json:"title"`
Language string `json:"language"`
Tags []string `json:"tags"`
Content string `json:"content"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// SnippetStore manages snippet persistence in a JSON file.
type SnippetStore struct {
FilePath string
}
// NewSnippetStore creates a store pointing at the default path:
// ~/.config/gitlink-cli/snippets.json
// Respects GITLINK_CONFIG_DIR env var.
func NewSnippetStore() *SnippetStore {
dir := os.Getenv("GITLINK_CONFIG_DIR")
if dir == "" {
home, _ := os.UserHomeDir()
dir = filepath.Join(home, ".config", "gitlink-cli")
}
return &SnippetStore{
FilePath: filepath.Join(dir, "snippets.json"),
}
}
// NewSnippetStoreWithPath creates a store with an explicit file path.
// Used in tests to point at temp directories.
func NewSnippetStoreWithPath(path string) *SnippetStore {
return &SnippetStore{FilePath: path}
}
// Load reads all snippets from the JSON file.
// Returns an empty slice (not error) if the file does not exist.
func (s *SnippetStore) Load() ([]Snippet, error) {
data, err := os.ReadFile(s.FilePath)
if err != nil {
if os.IsNotExist(err) {
return []Snippet{}, nil
}
return nil, err
}
if len(data) == 0 {
return []Snippet{}, nil
}
var snippets []Snippet
if err := json.Unmarshal(data, &snippets); err != nil {
return nil, err
}
if snippets == nil {
return []Snippet{}, nil
}
return snippets, nil
}
// Save writes all snippets to the JSON file.
// Creates parent directories if needed.
func (s *SnippetStore) Save(snippets []Snippet) error {
if err := os.MkdirAll(filepath.Dir(s.FilePath), 0o755); err != nil {
return err
}
data, err := json.MarshalIndent(snippets, "", " ")
if err != nil {
return err
}
return os.WriteFile(s.FilePath, data, 0o644)
}
// GenerateID creates a random 8-character hex ID.
func GenerateID() string {
b := make([]byte, 4)
_, _ = rand.Read(b)
return hex.EncodeToString(b)
}

View File

@ -0,0 +1,121 @@
package snippet
import (
"os"
"path/filepath"
"testing"
"time"
)
func TestLoadReturnsEmptyOnMissingFile(t *testing.T) {
dir := t.TempDir()
store := NewSnippetStoreWithPath(filepath.Join(dir, "snippets.json"))
snippets, err := store.Load()
if err != nil {
t.Fatalf("Load on missing file should not error: %v", err)
}
if len(snippets) != 0 {
t.Fatalf("expected empty slice, got %d items", len(snippets))
}
}
func TestSaveAndLoad(t *testing.T) {
dir := t.TempDir()
store := NewSnippetStoreWithPath(filepath.Join(dir, "snippets.json"))
now := time.Now().Truncate(time.Second)
original := []Snippet{
{
ID: "abc12345",
Title: "Hello World",
Language: "go",
Tags: []string{"test", "example"},
Content: `fmt.Println("hello")`,
CreatedAt: now,
UpdatedAt: now,
},
{
ID: "def67890",
Title: "HTTP Handler",
Language: "go",
Tags: []string{"http"},
Content: `func handler(w http.ResponseWriter, r *http.Request) {}`,
CreatedAt: now,
UpdatedAt: now,
},
}
if err := store.Save(original); err != nil {
t.Fatalf("Save failed: %v", err)
}
loaded, err := store.Load()
if err != nil {
t.Fatalf("Load failed: %v", err)
}
if len(loaded) != 2 {
t.Fatalf("expected 2 snippets, got %d", len(loaded))
}
if loaded[0].ID != "abc12345" {
t.Errorf("ID mismatch: got %s", loaded[0].ID)
}
if loaded[0].Title != "Hello World" {
t.Errorf("Title mismatch: got %s", loaded[0].Title)
}
if loaded[0].Language != "go" {
t.Errorf("Language mismatch: got %s", loaded[0].Language)
}
if len(loaded[0].Tags) != 2 || loaded[0].Tags[0] != "test" {
t.Errorf("Tags mismatch: got %v", loaded[0].Tags)
}
if loaded[0].Content != `fmt.Println("hello")` {
t.Errorf("Content mismatch: got %s", loaded[0].Content)
}
if !loaded[0].CreatedAt.Equal(now) {
t.Errorf("CreatedAt mismatch: got %v, want %v", loaded[0].CreatedAt, now)
}
}
func TestSaveCreatesDirectory(t *testing.T) {
dir := t.TempDir()
nestedPath := filepath.Join(dir, "a", "b", "c", "snippets.json")
store := NewSnippetStoreWithPath(nestedPath)
err := store.Save([]Snippet{})
if err != nil {
t.Fatalf("Save to nested path failed: %v", err)
}
if _, err := os.Stat(nestedPath); os.IsNotExist(err) {
t.Fatal("file was not created")
}
}
func TestGenerateID(t *testing.T) {
ids := make(map[string]bool)
for i := 0; i < 100; i++ {
id := GenerateID()
if len(id) != 8 {
t.Errorf("ID length should be 8, got %d: %s", len(id), id)
}
if ids[id] {
t.Errorf("duplicate ID generated: %s", id)
}
ids[id] = true
}
}
func TestLoadEmptyFile(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "snippets.json")
os.WriteFile(path, []byte(""), 0o644)
store := NewSnippetStoreWithPath(path)
snippets, err := store.Load()
if err != nil {
t.Fatalf("Load empty file should not error: %v", err)
}
if len(snippets) != 0 {
t.Fatalf("expected empty slice, got %d", len(snippets))
}
}

1
pr-test-file.txt Normal file
View File

@ -0,0 +1 @@
PR Test 2026年 4月 7日 星期二 11时45分56秒 CST

View File

@ -0,0 +1,389 @@
{
"scenario": "hotspot",
"keywords": [
"深度学习"
],
"category": "",
"trending_repos": [
{
"repo": "Edgedev/Edge-Computing-Engine",
"description": "Edge : 一个开源的科学计算引擎",
"language": "C++",
"stars": 3,
"forks": 1,
"visits": 592,
"score": 64,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-07-13",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "CocytusXRS/AI_test",
"description": "",
"language": "Jupyter notebook",
"stars": 0,
"forks": 0,
"visits": 548,
"score": 54,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2022-12-02",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "AIEven/AIkun",
"description": "",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 382,
"score": 38,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2025-08-09",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "shenyan/machineLearningTemplate",
"description": "基于pytorch lightning的机器学习模板, 用于对机器学习算法进行训练, 验证, 测试等, 目前实现了神经网路, 深度学习, k折交叉, 自动保存训练信息等. ",
"language": "Python",
"stars": 1,
"forks": 0,
"visits": 309,
"score": 31,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-10-22",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "opensci/pDeep",
"description": "pDeep是一种基于深度学习的质谱预测系统。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 292,
"score": 29,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-03-19",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "dongeliu/dlvc",
"description": "一种视频编解码原型系统,内嵌深度学习编码工具显著提高压缩效率。",
"language": "C++",
"stars": 0,
"forks": 0,
"visits": 276,
"score": 27,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-03-19",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "Hua135/sam-optimizers",
"description": "深度神经网络的泛化能力是机器学习领域的核心问题之一。传统优化算法如随机梯度下降SGD和Adam仅最小化训练损失值容易导致模型收敛到尖锐的最小值点从而影响泛化性能。近年来锐度感知最小化Sharpness-Aware Minimization, SAM通过同时最小化损失值和损失锐度有效提升了模型的泛化能力但其计算开销约为传统优化器的两倍。本文系统研究了SAM及其两种高效变体——ESA",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 64,
"score": 26,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-06-23",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "ashh/jittor-chanshiguan-track2-straightpcf-denoise",
"description": "赛道二三维点云降噪项目,基于 StraightPCF 复现并改进三阶段耦合速度场方法:单速度预训练、双速度耦合训练、距离缩放模块精调。采用 patch 级迭代推理与稳健重建保证输入输出点数一致。最佳提交成绩72.63CD 60.31 / P2S 84.96)。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 39,
"score": 23,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-06-27",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "clj111/Edge-Computing-Engine",
"description": "Edge : 一个开源的科学计算引擎",
"language": "C++",
"stars": 0,
"forks": 0,
"visits": 186,
"score": 18,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-06-16",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "njuiselab/Gandalf",
"description": "",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 189,
"score": 18,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2024-10-11",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "ly15927029790/CodeRecommendation",
"description": "代码生成式补全工具",
"language": "Java",
"stars": 0,
"forks": 0,
"visits": 177,
"score": 17,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2020-10-12",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "co63oc/mcTVM",
"description": "mcTVM是MetaX-MACA生态下的开源深度学习编译框架项目基于Apache TVM v0.18.0版本进行扩展开发新增对沐曦MetaXGPU的专属支持打通沐曦GPU与TVM框架的适配通道实现深度学习模型在沐曦GPU上的高效编译、优化与部署。mcTVM助力完善沐曦GPU的软件生态为开发者提供便捷、高效的深度学习模型部署解决方案适用于人工智能、异构计算等相关领域的研发与应用场景。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 66,
"score": 16,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-04-15",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "aaasdasd/aa",
"description": "",
"language": "Python3.6",
"stars": 0,
"forks": 0,
"visits": 146,
"score": 14,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2023-07-15",
"contributors_count": 0,
"releases_count": 0
}
],
"active_discussions": [],
"topic_heat": [
{
"topic": "deep_learning",
"count": 15
},
{
"topic": "scientific_computing",
"count": 7
},
{
"topic": "computer_vision",
"count": 6
},
{
"topic": "machine_learning",
"count": 4
},
{
"topic": "database",
"count": 3
},
{
"topic": "time_series",
"count": 3
},
{
"topic": "generative_ai",
"count": 3
},
{
"topic": "reinforcement_learning",
"count": 2
},
{
"topic": "nlp",
"count": 2
},
{
"topic": "autonomous_systems",
"count": 2
}
],
"core_scholars": [
{
"login": "Edge",
"repo_count": 2,
"repos": [
"Edgedev/Edge-Computing-Engine",
"clj111/Edge-Computing-Engine"
]
},
{
"login": "junru shao",
"repo_count": 2,
"repos": [
"co63oc/mcTVM"
]
},
{
"login": "Edgedev",
"repo_count": 1,
"repos": [
"Edgedev/Edge-Computing-Engine"
]
},
{
"login": "cloudy1225",
"repo_count": 1,
"repos": [
"CocytusXRS/AI_test"
]
},
{
"login": "CocytusXRS",
"repo_count": 1,
"repos": [
"CocytusXRS/AI_test"
]
},
{
"login": "AIEven",
"repo_count": 1,
"repos": [
"AIEven/AIkun"
]
},
{
"login": "shenyan",
"repo_count": 1,
"repos": [
"shenyan/machineLearningTemplate"
]
},
{
"login": "jalew",
"repo_count": 1,
"repos": [
"opensci/pDeep"
]
},
{
"login": "wen-feng zeng",
"repo_count": 1,
"repos": [
"opensci/pDeep"
]
},
{
"login": "dong liu",
"repo_count": 1,
"repos": [
"dongeliu/dlvc"
]
},
{
"login": "404notfound233",
"repo_count": 1,
"repos": [
"njuiselab/Gandalf"
]
},
{
"login": "beginner401",
"repo_count": 1,
"repos": [
"njuiselab/Gandalf"
]
}
],
"core_teams": [
{
"login": "Edgedev",
"repo_count": 1
},
{
"login": "CocytusXRS",
"repo_count": 1
},
{
"login": "AIEven",
"repo_count": 1
},
{
"login": "shenyan",
"repo_count": 1
},
{
"login": "opensci",
"repo_count": 1
},
{
"login": "dongeliu",
"repo_count": 1
},
{
"login": "clj111",
"repo_count": 1
},
{
"login": "njuiselab",
"repo_count": 1
}
],
"meta": {
"repo_count": 13,
"issue_count": 2,
"pr_count": 0,
"scholar_count": 35,
"discussion_count": 0,
"topic_count": 10
}
}

View File

@ -0,0 +1,50 @@
# 🔬 科研热点追踪报告
> 关键词:深度学习
> 扫描时间2026-07-07
> 覆盖仓库13 个 · 讨论 0 条 · 主题 10 个 · 学者 35 位
## 🔥 飙升项目 Top 5
| # | 仓库 | 语言 | 👁 访问 | ★ Star | ⑂ Fork | 热度 | 更新 |
|---|------|------|---------|--------|--------|------|------|
| 1 | `Edgedev/Edge-Computing-Engine` | C++ | 592 | 3 | 1 | 64 | 2021-07-13 |
| 2 | `CocytusXRS/AI_test` | Jupyter notebook | 548 | 0 | 0 | 54 | 2022-12-02 |
| 3 | `AIEven/AIkun` | Python | 382 | 0 | 0 | 38 | 2025-08-09 |
| 4 | `shenyan/machineLearningTemplate` | Python | 309 | 1 | 0 | 31 | 2021-10-22 |
| 5 | `opensci/pDeep` | Python | 292 | 0 | 0 | 29 | 2021-03-19 |
## 📊 热门主题
- **deep_learning** — 15 个仓库 ███████████████
- **scientific_computing** — 7 个仓库 ███████
- **computer_vision** — 6 个仓库 ██████
- **machine_learning** — 4 个仓库 ████
- **database** — 3 个仓库 ███
- **time_series** — 3 个仓库 ███
- **generative_ai** — 3 个仓库 ███
- **reinforcement_learning** — 2 个仓库 ██
- **nlp** — 2 个仓库 ██
- **autonomous_systems** — 2 个仓库 ██
## 👥 核心学者
- **Edge** — 关联 2 个仓库
- **junru shao** — 关联 2 个仓库
- **Edgedev** — 关联 1 个仓库
- **cloudy1225** — 关联 1 个仓库
- **CocytusXRS** — 关联 1 个仓库
## 🏛 活跃组织/团队
- **Edgedev** — 1 个仓库
- **CocytusXRS** — 1 个仓库
- **AIEven** — 1 个仓库
- **shenyan** — 1 个仓库
- **opensci** — 1 个仓库
- **dongeliu** — 1 个仓库
- **clj111** — 1 个仓库
- **njuiselab** — 1 个仓库
---
*由 gitlink-research-hotspot 自动生成*

View File

@ -0,0 +1,389 @@
{
"scenario": "hotspot",
"keywords": [
"深度学习"
],
"category": "",
"trending_repos": [
{
"repo": "Edgedev/Edge-Computing-Engine",
"description": "Edge : 一个开源的科学计算引擎",
"language": "C++",
"stars": 3,
"forks": 1,
"visits": 592,
"score": 64,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-07-13",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "CocytusXRS/AI_test",
"description": "",
"language": "Jupyter notebook",
"stars": 0,
"forks": 0,
"visits": 548,
"score": 54,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2022-12-02",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "AIEven/AIkun",
"description": "",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 382,
"score": 38,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2025-08-09",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "shenyan/machineLearningTemplate",
"description": "基于pytorch lightning的机器学习模板, 用于对机器学习算法进行训练, 验证, 测试等, 目前实现了神经网路, 深度学习, k折交叉, 自动保存训练信息等. ",
"language": "Python",
"stars": 1,
"forks": 0,
"visits": 309,
"score": 31,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-10-22",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "opensci/pDeep",
"description": "pDeep是一种基于深度学习的质谱预测系统。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 292,
"score": 29,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-03-19",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "dongeliu/dlvc",
"description": "一种视频编解码原型系统,内嵌深度学习编码工具显著提高压缩效率。",
"language": "C++",
"stars": 0,
"forks": 0,
"visits": 276,
"score": 27,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-03-19",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "Hua135/sam-optimizers",
"description": "深度神经网络的泛化能力是机器学习领域的核心问题之一。传统优化算法如随机梯度下降SGD和Adam仅最小化训练损失值容易导致模型收敛到尖锐的最小值点从而影响泛化性能。近年来锐度感知最小化Sharpness-Aware Minimization, SAM通过同时最小化损失值和损失锐度有效提升了模型的泛化能力但其计算开销约为传统优化器的两倍。本文系统研究了SAM及其两种高效变体——ESA",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 64,
"score": 26,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-06-23",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "ashh/jittor-chanshiguan-track2-straightpcf-denoise",
"description": "赛道二三维点云降噪项目,基于 StraightPCF 复现并改进三阶段耦合速度场方法:单速度预训练、双速度耦合训练、距离缩放模块精调。采用 patch 级迭代推理与稳健重建保证输入输出点数一致。最佳提交成绩72.63CD 60.31 / P2S 84.96)。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 39,
"score": 23,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-06-27",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "clj111/Edge-Computing-Engine",
"description": "Edge : 一个开源的科学计算引擎",
"language": "C++",
"stars": 0,
"forks": 0,
"visits": 186,
"score": 18,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-06-16",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "njuiselab/Gandalf",
"description": "",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 189,
"score": 18,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2024-10-11",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "ly15927029790/CodeRecommendation",
"description": "代码生成式补全工具",
"language": "Java",
"stars": 0,
"forks": 0,
"visits": 177,
"score": 17,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2020-10-12",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "co63oc/mcTVM",
"description": "mcTVM是MetaX-MACA生态下的开源深度学习编译框架项目基于Apache TVM v0.18.0版本进行扩展开发新增对沐曦MetaXGPU的专属支持打通沐曦GPU与TVM框架的适配通道实现深度学习模型在沐曦GPU上的高效编译、优化与部署。mcTVM助力完善沐曦GPU的软件生态为开发者提供便捷、高效的深度学习模型部署解决方案适用于人工智能、异构计算等相关领域的研发与应用场景。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 66,
"score": 16,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-04-15",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "aaasdasd/aa",
"description": "",
"language": "Python3.6",
"stars": 0,
"forks": 0,
"visits": 146,
"score": 14,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2023-07-15",
"contributors_count": 0,
"releases_count": 0
}
],
"active_discussions": [],
"topic_heat": [
{
"topic": "deep_learning",
"count": 15
},
{
"topic": "scientific_computing",
"count": 7
},
{
"topic": "computer_vision",
"count": 6
},
{
"topic": "machine_learning",
"count": 4
},
{
"topic": "database",
"count": 3
},
{
"topic": "time_series",
"count": 3
},
{
"topic": "generative_ai",
"count": 3
},
{
"topic": "reinforcement_learning",
"count": 2
},
{
"topic": "nlp",
"count": 2
},
{
"topic": "autonomous_systems",
"count": 2
}
],
"core_scholars": [
{
"login": "Edge",
"repo_count": 2,
"repos": [
"Edgedev/Edge-Computing-Engine",
"clj111/Edge-Computing-Engine"
]
},
{
"login": "junru shao",
"repo_count": 2,
"repos": [
"co63oc/mcTVM"
]
},
{
"login": "Edgedev",
"repo_count": 1,
"repos": [
"Edgedev/Edge-Computing-Engine"
]
},
{
"login": "cloudy1225",
"repo_count": 1,
"repos": [
"CocytusXRS/AI_test"
]
},
{
"login": "CocytusXRS",
"repo_count": 1,
"repos": [
"CocytusXRS/AI_test"
]
},
{
"login": "AIEven",
"repo_count": 1,
"repos": [
"AIEven/AIkun"
]
},
{
"login": "shenyan",
"repo_count": 1,
"repos": [
"shenyan/machineLearningTemplate"
]
},
{
"login": "jalew",
"repo_count": 1,
"repos": [
"opensci/pDeep"
]
},
{
"login": "wen-feng zeng",
"repo_count": 1,
"repos": [
"opensci/pDeep"
]
},
{
"login": "dong liu",
"repo_count": 1,
"repos": [
"dongeliu/dlvc"
]
},
{
"login": "404notfound233",
"repo_count": 1,
"repos": [
"njuiselab/Gandalf"
]
},
{
"login": "beginner401",
"repo_count": 1,
"repos": [
"njuiselab/Gandalf"
]
}
],
"core_teams": [
{
"login": "Edgedev",
"repo_count": 1
},
{
"login": "CocytusXRS",
"repo_count": 1
},
{
"login": "AIEven",
"repo_count": 1
},
{
"login": "shenyan",
"repo_count": 1
},
{
"login": "opensci",
"repo_count": 1
},
{
"login": "dongeliu",
"repo_count": 1
},
{
"login": "clj111",
"repo_count": 1
},
{
"login": "njuiselab",
"repo_count": 1
}
],
"meta": {
"repo_count": 13,
"issue_count": 2,
"pr_count": 0,
"scholar_count": 35,
"discussion_count": 0,
"topic_count": 10
}
}

View File

@ -0,0 +1,50 @@
# 🔬 科研热点追踪报告
> 关键词:深度学习
> 扫描时间2026-07-07
> 覆盖仓库13 个 · 讨论 0 条 · 主题 10 个 · 学者 35 位
## 🔥 飙升项目 Top 5
| # | 仓库 | 语言 | 👁 访问 | ★ Star | ⑂ Fork | 热度 | 更新 |
|---|------|------|---------|--------|--------|------|------|
| 1 | `Edgedev/Edge-Computing-Engine` | C++ | 592 | 3 | 1 | 64 | 2021-07-13 |
| 2 | `CocytusXRS/AI_test` | Jupyter notebook | 548 | 0 | 0 | 54 | 2022-12-02 |
| 3 | `AIEven/AIkun` | Python | 382 | 0 | 0 | 38 | 2025-08-09 |
| 4 | `shenyan/machineLearningTemplate` | Python | 309 | 1 | 0 | 31 | 2021-10-22 |
| 5 | `opensci/pDeep` | Python | 292 | 0 | 0 | 29 | 2021-03-19 |
## 📊 热门主题
- **deep_learning** — 15 个仓库 ███████████████
- **scientific_computing** — 7 个仓库 ███████
- **computer_vision** — 6 个仓库 ██████
- **machine_learning** — 4 个仓库 ████
- **database** — 3 个仓库 ███
- **time_series** — 3 个仓库 ███
- **generative_ai** — 3 个仓库 ███
- **reinforcement_learning** — 2 个仓库 ██
- **nlp** — 2 个仓库 ██
- **autonomous_systems** — 2 个仓库 ██
## 👥 核心学者
- **Edge** — 关联 2 个仓库
- **junru shao** — 关联 2 个仓库
- **Edgedev** — 关联 1 个仓库
- **cloudy1225** — 关联 1 个仓库
- **CocytusXRS** — 关联 1 个仓库
## 🏛 活跃组织/团队
- **Edgedev** — 1 个仓库
- **CocytusXRS** — 1 个仓库
- **AIEven** — 1 个仓库
- **shenyan** — 1 个仓库
- **opensci** — 1 个仓库
- **dongeliu** — 1 个仓库
- **clj111** — 1 个仓库
- **njuiselab** — 1 个仓库
---
*由 gitlink-research-hotspot 自动生成*

View File

@ -0,0 +1,131 @@
{
"scenario": "inspire",
"mode": "repo",
"repo": "caoweiqiong/zwf",
"gap_topics": [
"computer_vision",
"generative_ai",
"devops",
"database",
"security"
],
"needed_languages": [
"Batchfile",
"CSS",
"HTML",
"JavaScript",
"Python",
"Shell",
"TypeScript",
"python",
"r",
"typescript"
],
"gap_signals": [],
"candidates": [
{
"login": "dev",
"score": 17.8,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
},
{
"login": "LegendC",
"score": 16.2,
"topic_overlap": 0.0,
"language_match": 0.1,
"activity_level": "high",
"repo_languages": [
"typescript"
],
"repo_count": 2,
"reasons": [
"语言匹配: typescript",
"本仓库活跃贡献者"
]
},
{
"login": "huster42",
"score": 15.4,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
},
{
"login": "whale",
"score": 14.6,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
},
{
"login": "pxz2fgtcv",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"无明显主题/语言重叠"
]
},
{
"login": "pepox4cvf",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [
"markdown"
],
"repo_count": 1,
"reasons": [
"无明显主题/语言重叠"
]
},
{
"login": "pfmy8cv3n",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"无明显主题/语言重叠"
]
},
{
"login": "mcvzf42hi",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"无明显主题/语言重叠"
]
}
],
"innovation_points": [],
"idea": null,
"llm_used": false
}

View File

@ -0,0 +1,19 @@
# 💡 创新启发报告
> 焦点仓库:`caoweiqiong/zwf`
> LLM 建议:⏭ 未启用(无 DEEPSEEK_API_KEY
## 🎯 缺口主题
`computer_vision`, `generative_ai`, `devops`, `database`, `security`
## 🤝 可合作学者 Top 5
| 学者 | 契合度 | 主题重叠 | 语言匹配 | 活跃 | 理由 |
|---|---|---|---|---|---|
| `dev` | 17.8 | 0.0 | 0.0 | high | 本仓库活跃贡献者 |
| `LegendC` | 16.2 | 0.0 | 0.1 | high | 语言匹配: typescript;本仓库活跃贡献者 |
| `huster42` | 15.4 | 0.0 | 0.0 | high | 本仓库活跃贡献者 |
| `whale` | 14.6 | 0.0 | 0.0 | high | 本仓库活跃贡献者 |
| `pxz2fgtcv` | 8.0 | 0.0 | 0.0 | medium | 无明显主题/语言重叠 |
---
*由 gitlink-research-inspire 生成*

View File

@ -0,0 +1,226 @@
digraph G {
rankdir=LR;
graph [fontname="Helvetica"];
node [fontname="Helvetica", style="filled"];
edge [fontname="Helvetica"];
repo_AIEven_AIkun [label="AIEven/AIkun", fillcolor="#4C78A8"];
repo_CocytusXRS_AI_test [label="CocytusXRS/AI_test", fillcolor="#4C78A8"];
repo_Edgedev_Edge_Computing_Engine [label="Edgedev/Edge-Computing-Engine", fillcolor="#4C78A8"];
repo_Hua135_sam_optimizers [label="Hua135/sam-optimizers", fillcolor="#4C78A8"];
repo_aaasdasd_aa [label="aaasdasd/aa", fillcolor="#4C78A8"];
repo_ashh_jittor_chanshiguan_track2_straightpcf_denoise [label="ashh/jittor-chanshiguan-track2-straightpcf-denoise", fillcolor="#4C78A8"];
repo_clj111_Edge_Computing_Engine [label="clj111/Edge-Computing-Engine", fillcolor="#4C78A8"];
repo_co63oc_mcTVM [label="co63oc/mcTVM", fillcolor="#4C78A8"];
repo_dongeliu_dlvc [label="dongeliu/dlvc", fillcolor="#4C78A8"];
repo_ly15927029790_CodeRecommendation [label="ly15927029790/CodeRecommendation", fillcolor="#4C78A8"];
repo_njuiselab_Gandalf [label="njuiselab/Gandalf", fillcolor="#4C78A8"];
repo_opensci_pDeep [label="opensci/pDeep", fillcolor="#4C78A8"];
repo_shenyan_machineLearningTemplate [label="shenyan/machineLearningTemplate", fillcolor="#4C78A8"];
scholar_404notfound233 [label="404notfound233", fillcolor="#F58518"];
scholar_AIEven [label="AIEven", fillcolor="#F58518"];
scholar_CocytusXRS [label="CocytusXRS", fillcolor="#F58518"];
scholar_Edge [label="Edge", fillcolor="#F58518"];
scholar_Edgedev [label="Edgedev", fillcolor="#F58518"];
scholar_Hua135 [label="Hua135", fillcolor="#F58518"];
scholar_aaasdasd [label="aaasdasd", fillcolor="#F58518"];
scholar_andrew reusch [label="andrew reusch", fillcolor="#F58518"];
scholar_ash [label="ash", fillcolor="#F58518"];
scholar_ashh [label="ashh", fillcolor="#F58518"];
scholar_beginner401 [label="beginner401", fillcolor="#F58518"];
scholar_cloudy1225 [label="cloudy1225", fillcolor="#F58518"];
scholar_cody yu [label="cody yu", fillcolor="#F58518"];
scholar_dong liu [label="dong liu", fillcolor="#F58518"];
scholar_driazati [label="driazati", fillcolor="#F58518"];
scholar_eric lunderberg [label="eric lunderberg", fillcolor="#F58518"];
scholar_gandalf401 [label="gandalf401", fillcolor="#F58518"];
scholar_haichen shen [label="haichen shen", fillcolor="#F58518"];
scholar_jalew [label="jalew", fillcolor="#F58518"];
scholar_junru shao [label="junru shao", fillcolor="#F58518"];
scholar_krzysztof parzyszek [label="krzysztof parzyszek", fillcolor="#F58518"];
scholar_luke hutton [label="luke hutton", fillcolor="#F58518"];
scholar_ly15927029790 [label="ly15927029790", fillcolor="#F58518"];
scholar_masahi [label="masahi", fillcolor="#F58518"];
scholar_matthew brookhart [label="matthew brookhart", fillcolor="#F58518"];
scholar_mehrdad hessar [label="mehrdad hessar", fillcolor="#F58518"];
scholar_ruihang lai [label="ruihang lai", fillcolor="#F58518"];
scholar_dong liu -> repo_dongeliu_dlvc [label="contributes_to"];
scholar_eric lunderberg -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_eric lunderberg -> scholar_andrew reusch [label="collaborates_with"];
scholar_eric lunderberg -> scholar_cody yu [label="collaborates_with"];
scholar_eric lunderberg -> scholar_driazati [label="collaborates_with"];
scholar_eric lunderberg -> scholar_haichen shen [label="collaborates_with"];
scholar_eric lunderberg -> scholar_junru shao [label="collaborates_with"];
scholar_eric lunderberg -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_eric lunderberg -> scholar_luke hutton [label="collaborates_with"];
scholar_eric lunderberg -> scholar_masahi [label="collaborates_with"];
scholar_eric lunderberg -> scholar_matthew brookhart [label="collaborates_with"];
scholar_eric lunderberg -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_eric lunderberg -> scholar_ruihang lai [label="collaborates_with"];
scholar_masahi -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_masahi -> scholar_andrew reusch [label="collaborates_with"];
scholar_masahi -> scholar_cody yu [label="collaborates_with"];
scholar_masahi -> scholar_driazati [label="collaborates_with"];
scholar_masahi -> scholar_eric lunderberg [label="collaborates_with"];
scholar_masahi -> scholar_haichen shen [label="collaborates_with"];
scholar_masahi -> scholar_junru shao [label="collaborates_with"];
scholar_masahi -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_masahi -> scholar_luke hutton [label="collaborates_with"];
scholar_masahi -> scholar_matthew brookhart [label="collaborates_with"];
scholar_masahi -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_masahi -> scholar_ruihang lai [label="collaborates_with"];
scholar_ruihang lai -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_ruihang lai -> scholar_andrew reusch [label="collaborates_with"];
scholar_ruihang lai -> scholar_cody yu [label="collaborates_with"];
scholar_ruihang lai -> scholar_driazati [label="collaborates_with"];
scholar_ruihang lai -> scholar_eric lunderberg [label="collaborates_with"];
scholar_ruihang lai -> scholar_haichen shen [label="collaborates_with"];
scholar_ruihang lai -> scholar_junru shao [label="collaborates_with"];
scholar_ruihang lai -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_ruihang lai -> scholar_luke hutton [label="collaborates_with"];
scholar_ruihang lai -> scholar_masahi [label="collaborates_with"];
scholar_ruihang lai -> scholar_matthew brookhart [label="collaborates_with"];
scholar_ruihang lai -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_driazati -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_driazati -> scholar_andrew reusch [label="collaborates_with"];
scholar_driazati -> scholar_cody yu [label="collaborates_with"];
scholar_driazati -> scholar_eric lunderberg [label="collaborates_with"];
scholar_driazati -> scholar_haichen shen [label="collaborates_with"];
scholar_driazati -> scholar_junru shao [label="collaborates_with"];
scholar_driazati -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_driazati -> scholar_luke hutton [label="collaborates_with"];
scholar_driazati -> scholar_masahi [label="collaborates_with"];
scholar_driazati -> scholar_matthew brookhart [label="collaborates_with"];
scholar_driazati -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_driazati -> scholar_ruihang lai [label="collaborates_with"];
scholar_krzysztof parzyszek -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_krzysztof parzyszek -> scholar_andrew reusch [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_cody yu [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_driazati [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_eric lunderberg [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_haichen shen [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_junru shao [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_luke hutton [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_masahi [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_matthew brookhart [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_krzysztof parzyszek -> scholar_ruihang lai [label="collaborates_with"];
scholar_mehrdad hessar -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_mehrdad hessar -> scholar_andrew reusch [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_cody yu [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_driazati [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_eric lunderberg [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_haichen shen [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_junru shao [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_luke hutton [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_masahi [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_matthew brookhart [label="collaborates_with"];
scholar_mehrdad hessar -> scholar_ruihang lai [label="collaborates_with"];
scholar_junru shao -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_junru shao -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_junru shao -> scholar_andrew reusch [label="collaborates_with"];
scholar_junru shao -> scholar_cody yu [label="collaborates_with"];
scholar_junru shao -> scholar_driazati [label="collaborates_with"];
scholar_junru shao -> scholar_eric lunderberg [label="collaborates_with"];
scholar_junru shao -> scholar_haichen shen [label="collaborates_with"];
scholar_junru shao -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_junru shao -> scholar_luke hutton [label="collaborates_with"];
scholar_junru shao -> scholar_masahi [label="collaborates_with"];
scholar_junru shao -> scholar_matthew brookhart [label="collaborates_with"];
scholar_junru shao -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_junru shao -> scholar_ruihang lai [label="collaborates_with"];
scholar_matthew brookhart -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_matthew brookhart -> scholar_andrew reusch [label="collaborates_with"];
scholar_matthew brookhart -> scholar_cody yu [label="collaborates_with"];
scholar_matthew brookhart -> scholar_driazati [label="collaborates_with"];
scholar_matthew brookhart -> scholar_eric lunderberg [label="collaborates_with"];
scholar_matthew brookhart -> scholar_haichen shen [label="collaborates_with"];
scholar_matthew brookhart -> scholar_junru shao [label="collaborates_with"];
scholar_matthew brookhart -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_matthew brookhart -> scholar_luke hutton [label="collaborates_with"];
scholar_matthew brookhart -> scholar_masahi [label="collaborates_with"];
scholar_matthew brookhart -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_matthew brookhart -> scholar_ruihang lai [label="collaborates_with"];
scholar_haichen shen -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_haichen shen -> scholar_andrew reusch [label="collaborates_with"];
scholar_haichen shen -> scholar_cody yu [label="collaborates_with"];
scholar_haichen shen -> scholar_driazati [label="collaborates_with"];
scholar_haichen shen -> scholar_eric lunderberg [label="collaborates_with"];
scholar_haichen shen -> scholar_junru shao [label="collaborates_with"];
scholar_haichen shen -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_haichen shen -> scholar_luke hutton [label="collaborates_with"];
scholar_haichen shen -> scholar_masahi [label="collaborates_with"];
scholar_haichen shen -> scholar_matthew brookhart [label="collaborates_with"];
scholar_haichen shen -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_haichen shen -> scholar_ruihang lai [label="collaborates_with"];
scholar_luke hutton -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_luke hutton -> scholar_andrew reusch [label="collaborates_with"];
scholar_luke hutton -> scholar_cody yu [label="collaborates_with"];
scholar_luke hutton -> scholar_driazati [label="collaborates_with"];
scholar_luke hutton -> scholar_eric lunderberg [label="collaborates_with"];
scholar_luke hutton -> scholar_haichen shen [label="collaborates_with"];
scholar_luke hutton -> scholar_junru shao [label="collaborates_with"];
scholar_luke hutton -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_luke hutton -> scholar_masahi [label="collaborates_with"];
scholar_luke hutton -> scholar_matthew brookhart [label="collaborates_with"];
scholar_luke hutton -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_luke hutton -> scholar_ruihang lai [label="collaborates_with"];
scholar_andrew reusch -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_andrew reusch -> scholar_cody yu [label="collaborates_with"];
scholar_andrew reusch -> scholar_driazati [label="collaborates_with"];
scholar_andrew reusch -> scholar_eric lunderberg [label="collaborates_with"];
scholar_andrew reusch -> scholar_haichen shen [label="collaborates_with"];
scholar_andrew reusch -> scholar_junru shao [label="collaborates_with"];
scholar_andrew reusch -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_andrew reusch -> scholar_luke hutton [label="collaborates_with"];
scholar_andrew reusch -> scholar_masahi [label="collaborates_with"];
scholar_andrew reusch -> scholar_matthew brookhart [label="collaborates_with"];
scholar_andrew reusch -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_andrew reusch -> scholar_ruihang lai [label="collaborates_with"];
scholar_cody yu -> repo_co63oc_mcTVM [label="contributes_to"];
scholar_cody yu -> scholar_andrew reusch [label="collaborates_with"];
scholar_cody yu -> scholar_driazati [label="collaborates_with"];
scholar_cody yu -> scholar_eric lunderberg [label="collaborates_with"];
scholar_cody yu -> scholar_haichen shen [label="collaborates_with"];
scholar_cody yu -> scholar_junru shao [label="collaborates_with"];
scholar_cody yu -> scholar_krzysztof parzyszek [label="collaborates_with"];
scholar_cody yu -> scholar_luke hutton [label="collaborates_with"];
scholar_cody yu -> scholar_masahi [label="collaborates_with"];
scholar_cody yu -> scholar_matthew brookhart [label="collaborates_with"];
scholar_cody yu -> scholar_mehrdad hessar [label="collaborates_with"];
scholar_cody yu -> scholar_ruihang lai [label="collaborates_with"];
scholar_jalew -> repo_opensci_pDeep [label="contributes_to"];
scholar_Edge -> repo_Edgedev_Edge_Computing_Engine [label="contributes_to"];
scholar_Edge -> repo_clj111_Edge_Computing_Engine [label="contributes_to"];
scholar_Edge -> scholar_Edgedev [label="collaborates_with"];
scholar_Edgedev -> repo_Edgedev_Edge_Computing_Engine [label="contributes_to"];
scholar_Edgedev -> repo_Edgedev_Edge_Computing_Engine [label="owns"];
scholar_Edgedev -> scholar_Edge [label="collaborates_with"];
scholar_AIEven -> repo_AIEven_AIkun [label="contributes_to"];
scholar_AIEven -> repo_AIEven_AIkun [label="owns"];
scholar_aaasdasd -> repo_aaasdasd_aa [label="contributes_to"];
scholar_aaasdasd -> repo_aaasdasd_aa [label="owns"];
scholar_404notfound233 -> repo_njuiselab_Gandalf [label="contributes_to"];
scholar_404notfound233 -> scholar_beginner401 [label="collaborates_with"];
scholar_404notfound233 -> scholar_gandalf401 [label="collaborates_with"];
scholar_beginner401 -> repo_njuiselab_Gandalf [label="contributes_to"];
scholar_beginner401 -> scholar_404notfound233 [label="collaborates_with"];
scholar_beginner401 -> scholar_gandalf401 [label="collaborates_with"];
scholar_gandalf401 -> repo_njuiselab_Gandalf [label="contributes_to"];
scholar_gandalf401 -> scholar_404notfound233 [label="collaborates_with"];
scholar_gandalf401 -> scholar_beginner401 [label="collaborates_with"];
scholar_cloudy1225 -> repo_CocytusXRS_AI_test [label="contributes_to"];
scholar_cloudy1225 -> scholar_CocytusXRS [label="collaborates_with"];
scholar_CocytusXRS -> repo_CocytusXRS_AI_test [label="contributes_to"];
scholar_CocytusXRS -> repo_CocytusXRS_AI_test [label="owns"];
scholar_CocytusXRS -> scholar_cloudy1225 [label="collaborates_with"];
scholar_ly15927029790 -> repo_ly15927029790_CodeRecommendation [label="contributes_to"];
scholar_ly15927029790 -> repo_ly15927029790_CodeRecommendation [label="owns"];
scholar_Hua135 -> repo_Hua135_sam_optimizers [label="contributes_to"];
scholar_Hua135 -> repo_Hua135_sam_optimizers [label="owns"];
scholar_ash -> repo_ashh_jittor_chanshiguan_track2_straightpcf_denoise [label="contributes_to"];
scholar_ash -> scholar_ashh [label="collaborates_with"];
scholar_ashh -> repo_ashh_jittor_chanshiguan_track2_straightpcf_denoise [label="contributes_to"];
scholar_ashh -> repo_ashh_jittor_chanshiguan_track2_straightpcf_denoise [label="owns"];
scholar_ashh -> scholar_ash [label="collaborates_with"];
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,265 @@
```mermaid
graph TD
classDef repoNode fill:#4C78A8,stroke:#333,color:#fff;
classDef scholarNode fill:#F58518,stroke:#333,color:#fff;
classDef topicNode fill:#54A24B,stroke:#333,color:#fff;
repo_AIEven_AIkun["AIEven/AIkun"]
class repo_AIEven_AIkun repoNode;
repo_CocytusXRS_AI_test["CocytusXRS/AI_test"]
class repo_CocytusXRS_AI_test repoNode;
repo_Edgedev_Edge_Computing_Engine["Edgedev/Edge-Computing-Engine"]
class repo_Edgedev_Edge_Computing_Engine repoNode;
repo_Hua135_sam_optimizers["Hua135/sam-optimizers"]
class repo_Hua135_sam_optimizers repoNode;
repo_aaasdasd_aa["aaasdasd/aa"]
class repo_aaasdasd_aa repoNode;
repo_ashh_jittor_chanshiguan_track2_straightpcf_denoise["ashh/jittor-chanshiguan-track2-straightpcf-denoise"]
class repo_ashh_jittor_chanshiguan_track2_straightpcf_denoise repoNode;
repo_clj111_Edge_Computing_Engine["clj111/Edge-Computing-Engine"]
class repo_clj111_Edge_Computing_Engine repoNode;
repo_co63oc_mcTVM["co63oc/mcTVM"]
class repo_co63oc_mcTVM repoNode;
repo_dongeliu_dlvc["dongeliu/dlvc"]
class repo_dongeliu_dlvc repoNode;
repo_ly15927029790_CodeRecommendation["ly15927029790/CodeRecommendation"]
class repo_ly15927029790_CodeRecommendation repoNode;
repo_njuiselab_Gandalf["njuiselab/Gandalf"]
class repo_njuiselab_Gandalf repoNode;
repo_opensci_pDeep["opensci/pDeep"]
class repo_opensci_pDeep repoNode;
repo_shenyan_machineLearningTemplate["shenyan/machineLearningTemplate"]
class repo_shenyan_machineLearningTemplate repoNode;
scholar_404notfound233["404notfound233"]
class scholar_404notfound233 scholarNode;
scholar_AIEven["AIEven"]
class scholar_AIEven scholarNode;
scholar_CocytusXRS["CocytusXRS"]
class scholar_CocytusXRS scholarNode;
scholar_Edge["Edge"]
class scholar_Edge scholarNode;
scholar_Edgedev["Edgedev"]
class scholar_Edgedev scholarNode;
scholar_Hua135["Hua135"]
class scholar_Hua135 scholarNode;
scholar_aaasdasd["aaasdasd"]
class scholar_aaasdasd scholarNode;
scholar_andrew reusch["andrew reusch"]
class scholar_andrew reusch scholarNode;
scholar_ash["ash"]
class scholar_ash scholarNode;
scholar_ashh["ashh"]
class scholar_ashh scholarNode;
scholar_beginner401["beginner401"]
class scholar_beginner401 scholarNode;
scholar_cloudy1225["cloudy1225"]
class scholar_cloudy1225 scholarNode;
scholar_cody yu["cody yu"]
class scholar_cody yu scholarNode;
scholar_dong liu["dong liu"]
class scholar_dong liu scholarNode;
scholar_driazati["driazati"]
class scholar_driazati scholarNode;
scholar_eric lunderberg["eric lunderberg"]
class scholar_eric lunderberg scholarNode;
scholar_gandalf401["gandalf401"]
class scholar_gandalf401 scholarNode;
scholar_haichen shen["haichen shen"]
class scholar_haichen shen scholarNode;
scholar_jalew["jalew"]
class scholar_jalew scholarNode;
scholar_junru shao["junru shao"]
class scholar_junru shao scholarNode;
scholar_krzysztof parzyszek["krzysztof parzyszek"]
class scholar_krzysztof parzyszek scholarNode;
scholar_luke hutton["luke hutton"]
class scholar_luke hutton scholarNode;
scholar_ly15927029790["ly15927029790"]
class scholar_ly15927029790 scholarNode;
scholar_masahi["masahi"]
class scholar_masahi scholarNode;
scholar_matthew brookhart["matthew brookhart"]
class scholar_matthew brookhart scholarNode;
scholar_mehrdad hessar["mehrdad hessar"]
class scholar_mehrdad hessar scholarNode;
scholar_ruihang lai["ruihang lai"]
class scholar_ruihang lai scholarNode;
scholar_dong liu -- "contributes_to(1.00)" --> repo_dongeliu_dlvc
scholar_eric lunderberg -- "contributes_to(0.05)" --> repo_co63oc_mcTVM
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_driazati
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_masahi
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_eric lunderberg -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_masahi -- "contributes_to(0.03)" --> repo_co63oc_mcTVM
scholar_masahi -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_masahi -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_masahi -- "collaborates_with(1.00)" --> scholar_driazati
scholar_masahi -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_masahi -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_masahi -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_masahi -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_masahi -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_masahi -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_masahi -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_masahi -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_ruihang lai -- "contributes_to(0.02)" --> repo_co63oc_mcTVM
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_driazati
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_masahi
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_ruihang lai -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_driazati -- "contributes_to(0.02)" --> repo_co63oc_mcTVM
scholar_driazati -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_driazati -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_driazati -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_driazati -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_driazati -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_driazati -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_driazati -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_driazati -- "collaborates_with(1.00)" --> scholar_masahi
scholar_driazati -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_driazati -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_driazati -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_krzysztof parzyszek -- "contributes_to(0.02)" --> repo_co63oc_mcTVM
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_driazati
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_masahi
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_krzysztof parzyszek -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_mehrdad hessar -- "contributes_to(0.01)" --> repo_co63oc_mcTVM
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_driazati
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_masahi
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_mehrdad hessar -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_junru shao -- "contributes_to(0.01)" --> repo_co63oc_mcTVM
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_driazati
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_masahi
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_junru shao -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_matthew brookhart -- "contributes_to(0.01)" --> repo_co63oc_mcTVM
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_driazati
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_masahi
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_matthew brookhart -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_haichen shen -- "contributes_to(0.01)" --> repo_co63oc_mcTVM
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_driazati
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_masahi
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_haichen shen -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_luke hutton -- "contributes_to(0.01)" --> repo_co63oc_mcTVM
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_driazati
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_masahi
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_luke hutton -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_andrew reusch -- "contributes_to(0.01)" --> repo_co63oc_mcTVM
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_cody yu
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_driazati
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_masahi
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_andrew reusch -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_cody yu -- "contributes_to(0.01)" --> repo_co63oc_mcTVM
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_andrew reusch
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_driazati
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_eric lunderberg
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_haichen shen
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_junru shao
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_krzysztof parzyszek
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_luke hutton
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_masahi
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_matthew brookhart
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_mehrdad hessar
scholar_cody yu -- "collaborates_with(1.00)" --> scholar_ruihang lai
scholar_jalew -- "contributes_to(0.96)" --> repo_opensci_pDeep
scholar_Edge -- "contributes_to(0.75)" --> repo_Edgedev_Edge_Computing_Engine
scholar_Edge -- "contributes_to(1.00)" --> repo_clj111_Edge_Computing_Engine
scholar_Edge -- "collaborates_with(1.00)" --> scholar_Edgedev
scholar_Edgedev -- "contributes_to(0.25)" --> repo_Edgedev_Edge_Computing_Engine
scholar_Edgedev -- "owns(1.00)" --> repo_Edgedev_Edge_Computing_Engine
scholar_Edgedev -- "collaborates_with(1.00)" --> scholar_Edge
scholar_AIEven -- "contributes_to(1.00)" --> repo_AIEven_AIkun
scholar_AIEven -- "owns(1.00)" --> repo_AIEven_AIkun
scholar_aaasdasd -- "contributes_to(1.00)" --> repo_aaasdasd_aa
scholar_aaasdasd -- "owns(1.00)" --> repo_aaasdasd_aa
scholar_404notfound233 -- "contributes_to(0.50)" --> repo_njuiselab_Gandalf
scholar_404notfound233 -- "collaborates_with(1.00)" --> scholar_beginner401
scholar_404notfound233 -- "collaborates_with(1.00)" --> scholar_gandalf401
scholar_beginner401 -- "contributes_to(0.42)" --> repo_njuiselab_Gandalf
scholar_beginner401 -- "collaborates_with(1.00)" --> scholar_404notfound233
scholar_beginner401 -- "collaborates_with(1.00)" --> scholar_gandalf401
scholar_gandalf401 -- "contributes_to(0.08)" --> repo_njuiselab_Gandalf
scholar_gandalf401 -- "collaborates_with(1.00)" --> scholar_404notfound233
scholar_gandalf401 -- "collaborates_with(1.00)" --> scholar_beginner401
scholar_cloudy1225 -- "contributes_to(0.50)" --> repo_CocytusXRS_AI_test
scholar_cloudy1225 -- "collaborates_with(1.00)" --> scholar_CocytusXRS
scholar_CocytusXRS -- "contributes_to(0.50)" --> repo_CocytusXRS_AI_test
scholar_CocytusXRS -- "owns(1.00)" --> repo_CocytusXRS_AI_test
scholar_CocytusXRS -- "collaborates_with(1.00)" --> scholar_cloudy1225
scholar_ly15927029790 -- "contributes_to(1.00)" --> repo_ly15927029790_CodeRecommendation
scholar_ly15927029790 -- "owns(1.00)" --> repo_ly15927029790_CodeRecommendation
scholar_Hua135 -- "contributes_to(1.00)" --> repo_Hua135_sam_optimizers
scholar_Hua135 -- "owns(1.00)" --> repo_Hua135_sam_optimizers
scholar_ash -- "contributes_to(0.75)" --> repo_ashh_jittor_chanshiguan_track2_straightpcf_denoise
scholar_ash -- "collaborates_with(1.00)" --> scholar_ashh
scholar_ashh -- "contributes_to(0.25)" --> repo_ashh_jittor_chanshiguan_track2_straightpcf_denoise
scholar_ashh -- "owns(1.00)" --> repo_ashh_jittor_chanshiguan_track2_straightpcf_denoise
scholar_ashh -- "collaborates_with(1.00)" --> scholar_ash
```

View File

@ -0,0 +1,68 @@
# 科研热点追踪与知识图谱报告
> 场景 S2 · 子赛题四「应用 GitLink 辅助科研」
**关键词**: 深度学习
## 一、图谱概览
- 仓库节点: **13**
- 学者节点: **35**
- 主题节点: **13**
- 节点总数: **61**
- 边总数: **553**
## 二、主题热度榜(基于全部仓库 description
| 排名 | 主题 | 覆盖仓库数 |
|------|------|-----------|
| 1 | `deep_learning` | 6 |
| 2 | `scientific_computing` | 3 |
| 3 | `machine_learning` | 2 |
| 4 | `time_series` | 1 |
| 5 | `generative_ai` | 1 |
| 6 | `autonomous_systems` | 1 |
| 7 | `nlp` | 1 |
## 三、核心学者(按出现仓库数排序)
| 排名 | 学者 | 关联仓库数 |
|------|------|-----------|
| 1 | `Edge` | 2 |
| 2 | `404notfound233` | 1 |
| 3 | `AIEven` | 1 |
| 4 | `CocytusXRS` | 1 |
| 5 | `Edgedev` | 1 |
| 6 | `Hua135` | 1 |
| 7 | `aaasdasd` | 1 |
| 8 | `andrew reusch` | 1 |
| 9 | `ash` | 1 |
| 10 | `ashh` | 1 |
## 四、核心团队(组织型仓库拥有者)
(该批仓库均由个人账号拥有,无组织型团队)
## 五、热门 / 飙升项目(热度排序)
| 仓库 | 语言 | ★ | ⑂ | 日均★ | 最近更新 |
|------|------|---:|---:|---:|----------|
| `Edgedev/Edge-Computing-Engine` | C++ | 4 | 1 | 0.0 | — |
| `shenyan/machineLearningTemplate` | Python | 1 | 0 | 0.0 | — |
| `dongeliu/dlvc` | C++ | 0 | 0 | 0.0 | — |
| `co63oc/mcTVM` | Python | 0 | 0 | 0.0 | — |
| `opensci/pDeep` | Python | 0 | 0 | 0.0 | — |
| `clj111/Edge-Computing-Engine` | C++ | 0 | 0 | 0.0 | — |
| `AIEven/AIkun` | Python | 0 | 0 | 0.0 | — |
| `aaasdasd/aa` | Python3.6 | 0 | 0 | 0.0 | — |
| `njuiselab/Gandalf` | Python | 0 | 0 | 0.0 | — |
| `CocytusXRS/AI_test` | Jupyter notebook | 0 | 0 | 0.0 | — |
## 六、活跃讨论(评论最多的 Issue / PR
# | 类型 | 仓库 | 标题 | 评论 |
|-|------|------|------|---:|
| 1 | issue | `Edgedev/Edge-Computing-Engine` | 实现基本矩阵类和深度学习pipeline测试 | 0 |
| 2 | issue | `Edgedev/Edge-Computing-Engine` | welcome功能 | 0 |
_配套产物graph.json结构化+ graph.mmdMermaid+ graph.dotGraphviz DOT_

View File

@ -0,0 +1,4 @@
```mermaid
gitGraph
commit id: "master 起点"
```

View File

@ -0,0 +1,58 @@
{
"scenario": "S1_repository_research_insight",
"repo": "caoweiqiong/zwf",
"default_branch": "master",
"commit_timeline": [
{
"date": "2026-05-09",
"count": 7
},
{
"date": "2026-05-10",
"count": 8
},
{
"date": "2026-06-11",
"count": 1
},
{
"date": "2026-06-23",
"count": 2
},
{
"date": "2026-07-03",
"count": 6
},
{
"date": "2026-07-04",
"count": 4
},
{
"date": "2026-07-06",
"count": 2
}
],
"branch_map": [
{
"name": "master",
"commits": 30,
"last_active": "2026-07-06",
"is_default": true
}
],
"pr_merge_patterns": [],
"doc_evolution": [
{
"file": "superpowers",
"last_date": ""
}
],
"experiment_files": [],
"innovation_points": [],
"meta": {
"commit_count": 30,
"merged_pr_count": 0,
"doc_count": 1,
"experiment_file_count": 0
}
}

View File

@ -0,0 +1,40 @@
# 仓库级科研项目洞悉报告 — caoweiqiong/zwf
> 场景 S1 · 子赛题四「应用 GitLink 辅助科研」· 项目谱系lineage分析
## 一、基础信息
- **默认分支**: `master`
- **采样提交**: 30 条(默认分支,最多 10×100
- **已合并 PR**: 0 个
- **文档文件**: 1 个
- **实验/评测文件**: 0 个
## 二、提交活跃度时间线
- 时间跨度: 2026-05-09 → 2026-07-06共 7 个有提交的日期)
- 峰值: 2026-05-10 当日 8 次提交
## 三、分支地图
| 分支 | 提交数 | 最后活跃 | 是否默认 |
|------|:------:|----------|:--------:|
| `master` | 30 | 2026-07-06 | 是 |
## 四、合并 PR 演进模式(高影响合并预览)
- (无已合并 PR
## 五、创新/里程碑点
- (未识别到明显高影响合并)
## 六、文档演进docs/*
| 文档 | 近似最后日期 |
|------|--------------|
| superpowers | — |
## 七、实验/评测文件组织
- (未在仓库树中识别到 experiment/benchmark/eval/test/data 目录)

View File

@ -0,0 +1,155 @@
{
"scenario": "S4_collaboration_matching",
"repo": "caoweiqiong/zwf",
"gap_topics": [
"computer_vision",
"generative_ai",
"devops",
"database",
"security"
],
"needed_languages": [
"Batchfile",
"CSS",
"HTML",
"JavaScript",
"Python",
"Shell",
"TypeScript",
"python",
"r",
"typescript"
],
"gap_signals": [],
"candidates": [
{
"login": "dev",
"score": 17.8,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
},
{
"login": "LegendC",
"score": 16.2,
"topic_overlap": 0.0,
"language_match": 0.1,
"activity_level": "high",
"repo_languages": [
"typescript"
],
"repo_count": 2,
"reasons": [
"语言匹配: typescript",
"本仓库活跃贡献者"
]
},
{
"login": "huster42",
"score": 15.4,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
},
{
"login": "whale",
"score": 14.6,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
},
{
"login": "pxz2fgtcv",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"无明显主题/语言重叠"
]
},
{
"login": "pepox4cvf",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [
"markdown"
],
"repo_count": 1,
"reasons": [
"无明显主题/语言重叠"
]
},
{
"login": "pfmy8cv3n",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"无明显主题/语言重叠"
]
},
{
"login": "mcvzf42hi",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"无明显主题/语言重叠"
]
},
{
"login": "pbfzcvkfl",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"无明显主题/语言重叠"
]
},
{
"login": "pcvyk8fg2",
"score": 8.0,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "medium",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"无明显主题/语言重叠"
]
}
],
"meta": {
"pool_size": 15,
"issue_sample": 100
}
}

View File

@ -0,0 +1,20 @@
```mermaid
graph TD
R["caoweiqiong/zwf<br/>(目标仓库)"]
C1["dev<br/>17.8分"]
R -- "0.0" --> C1
C2["LegendC<br/>16.2分"]
R -- "0.0" --> C2
C3["huster42<br/>15.4分"]
R -- "0.0" --> C3
C4["whale<br/>14.6分"]
R -- "0.0" --> C4
C5["pxz2fgtcv<br/>8.0分"]
R -- "0.0" --> C5
C6["pepox4cvf<br/>8.0分"]
R -- "0.0" --> C6
C7["pfmy8cv3n<br/>8.0分"]
R -- "0.0" --> C7
C8["mcvzf42hi<br/>8.0分"]
R -- "0.0" --> C8
```

View File

@ -0,0 +1,29 @@
# 科研协作智能匹配报告 — caoweiqiong/zwf
> 场景 S4 · 子赛题四「应用 GitLink 辅助科研」
## 一、仓库技术缺口分析
- **缺口主题**: computer_vision, generative_ai, devops, database, security
- **需求语言**: Batchfile, CSS, HTML, JavaScript, Python, Shell, TypeScript, python, r, typescript
- **缺口信号样本**: 0 条未解决 Issue/PR 主题证据
| 缺口主题 | 证据Issue/PR | 优先级 |
|----------|------------------|--------|
## 二、推荐协作伙伴(按综合匹配分排序)
| 排名 | 用户 | 匹配分 | 主题重叠 | 语言匹配 | 活跃度 | 匹配理由 |
|------|------|--------|----------|----------|--------|----------|
| 1 | `dev` | 17.8 | 0.0 | 0.0 | high | 本仓库活跃贡献者 |
| 2 | `LegendC` | 16.2 | 0.0 | 0.1 | high | 语言匹配: typescript; 本仓库活跃贡献者 |
| 3 | `huster42` | 15.4 | 0.0 | 0.0 | high | 本仓库活跃贡献者 |
| 4 | `whale` | 14.6 | 0.0 | 0.0 | high | 本仓库活跃贡献者 |
| 5 | `pxz2fgtcv` | 8.0 | 0.0 | 0.0 | medium | 无明显主题/语言重叠 |
| 6 | `pepox4cvf` | 8.0 | 0.0 | 0.0 | medium | 无明显主题/语言重叠 |
| 7 | `pfmy8cv3n` | 8.0 | 0.0 | 0.0 | medium | 无明显主题/语言重叠 |
| 8 | `mcvzf42hi` | 8.0 | 0.0 | 0.0 | medium | 无明显主题/语言重叠 |
| 9 | `pbfzcvkfl` | 8.0 | 0.0 | 0.0 | medium | 无明显主题/语言重叠 |
| 10 | `pcvyk8fg2` | 8.0 | 0.0 | 0.0 | medium | 无明显主题/语言重叠 |
_候选池规模 15issue 采样 100_

View File

@ -0,0 +1,60 @@
{
"scenario": "profile",
"mode": "project",
"profiles": [
{
"type": "project",
"repo": "caoweiqiong/zwf",
"name": "ZhiWenCraft",
"description": "",
"topics": [
{
"topic": "computer_vision",
"count": 1
},
{
"topic": "generative_ai",
"count": 1
},
{
"topic": "devops",
"count": 1
},
{
"topic": "database",
"count": 1
},
{
"topic": "security",
"count": 1
}
],
"languages": [
"Batchfile",
"CSS",
"HTML",
"JavaScript",
"Python",
"Shell",
"TypeScript"
],
"stars": 2,
"forks": 0,
"visits": 0,
"contributors_count": 4,
"top_contributors": [
"dev",
"huster42",
"whale",
"LegendC"
],
"score": {
"doc": 5,
"license": 0,
"collab": 4,
"impact": 4
},
"score_total": 13
}
]
}

View File

@ -0,0 +1,10 @@
# 🪪 主体画像报告
## 📦 ZhiWenCraft (`caoweiqiong/zwf`)
- ★2 ⑂0 👁0 · 贡献者 4 · 研究维度评分 **13/40**
- 主题:`computer_vision`、`generative_ai`、`devops`、`database`、`security`
- 核心贡献者:`dev`、`huster42`、`whale`、`LegendC`
---
*由 gitlink-research-profile 生成*

View File

@ -0,0 +1,56 @@
{
"scenario": "S5_progress_tracking",
"repo": "caoweiqiong/zwf",
"generated_at": "2026-07-07T12:39:04.575941+00:00",
"week_stats": {
"this_week": {
"commits": 12,
"issues_opened": 0,
"issues_closed": 0,
"issues_stale": 0,
"prs_opened": 0,
"prs_merged": 0,
"prs_open_stale": 0,
"contributors_active": 4,
"contributors_active_logins": [
"Dev",
"HUSTER42",
"LegendC",
"whale"
]
},
"last_week": {
"commits": 0,
"issues_opened": 0,
"issues_closed": 0,
"issues_stale": 0,
"prs_opened": 0,
"prs_merged": 0,
"prs_open_stale": 0,
"contributors_active": 0,
"contributors_active_logins": []
},
"window": {
"this_week_start": "2026-06-30T12:39:04.575941+00:00",
"now": "2026-07-07T12:39:04.575941+00:00",
"last_week_start": "2026-06-23T12:39:04.575941+00:00",
"last_week_end": "2026-06-30T12:39:04.575941+00:00"
},
"total_contributors": 4
},
"trend": {
"commit_delta_pct": 100.0,
"activity_level": "increasing",
"this_week_commits": 12,
"last_week_commits": 0
},
"milestones": [],
"risk_warnings": [],
"meta": {
"commits_fetched": 30,
"issues_fetched": 0,
"prs_fetched": 0,
"milestones_fetched": 0,
"contributors_fetched": 4
}
}

View File

@ -0,0 +1,32 @@
# 科研进度智能跟踪周报 — caoweiqiong/zwf
> 场景 S5 · 子赛题四「应用 GitLink 辅助科研」· 生成于 2026-07-07T12:39:04.575941+00:00
## 一、本周 / 上周活动对比
| 指标 | 本周 | 上周 |
|------|------|------|
| 提交 commits | 12 | 0 |
| Issue 新增 | 0 | 0 |
| Issue 关闭 | 0 | 0 |
| 开放 stale issue (>30天) | 0 | 0 |
| PR 新增 | 0 | 0 |
| PR 合并 | 0 | 0 |
| 开放 stale PR (>14天) | 0 | 0 |
| 活跃贡献者 | 4 | 0 |
- **趋势**commit 周环比 **100.0%**,活跃度等级 `increasing`
## 二、里程碑进度
_仓库无里程碑数据_
## 三、风险预警
_未触发风险阈值进度正常_
## 四、附
- 取数commits=30 issues=0 prs=0 milestones=0 contributors=4
- 窗口:本周 [2026-06-30T12:39:04.575941+00:00, 2026-07-07T12:39:04.575941+00:00];上周 [2026-06-23T12:39:04.575941+00:00, 2026-06-30T12:39:04.575941+00:00)
- 阈值stale_issue>30天 / stale_pr>14天 / 低活跃<3次/ / bus_factor>50%

View File

@ -0,0 +1,49 @@
# 科研项目合规与复现性检查报告 — caoweiqiong/zwf
> 场景 S3 · 子赛题四「应用 GitLink 辅助科研」
- **默认分支**: `master`
- **识别许可证**: `None`
- **复现性评分**: **7.0/10**(及格)
- **合规性评分**: **6.2/10**(及格)
## 一、复现性检查清单
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| CI 配置 | FAIL | 0/2 | 未找到 .gitea/.github/.gitlab 等 CI 配置 |
| 依赖锁文件 | PASS | 2/2 | 存在 lockfile: package-lock.json |
| README 复现说明 | PASS | 2/2 | README 含复现关键词 11 个: install, 环境, 依赖, build, 构建 |
| 版本 tag | FAIL | 1/2 | repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本 |
| 容器化环境 | PASS | 2/2 | 存在容器配置: docker-compose.yml |
## 二、合规性检查清单
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| LICENSE 文件 | FAIL | 0/2 | 缺少 LICENSE 文件 |
| 安全策略 SECURITY.md | FAIL | 0/2 | 缺少 SECURITY.md无安全披露流程 |
| 版权声明 | FAIL | 1/2 | 未在 LICENSE/README 中发现版权声明(建议源文件头补 Copyright 注释) |
| 依赖清单声明 | PASS | 2/2 | 存在依赖管理文件(建议核对各依赖许可证兼容性) |
| 贡献指南 | FAIL | 1/2 | 缺少 CONTRIBUTING.md |
## 三、数据隐私检查
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| 数据目录入库 | PASS | 2/2 | 未发现 data/ 目录入库 |
| .env 入库 | PASS | 2/2 | .env 未入库 |
| .gitignore 忽略 .env | PASS | 2/2 | .gitignore 已配置忽略 .env |
## 四、风险项(按严重程度排序)
| 级别 | 类别 | 名称 | 文件:行 | 证据 |
|:----:|------|------|---------|------|
| medium | repro/compliance | CI 配置 | | 未找到 .gitea/.github/.gitlab 等 CI 配置 |
| medium | repro/compliance | 版本 tag | | repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本 |
| medium | repro/compliance | LICENSE 文件 | | 缺少 LICENSE 文件 |
| medium | repro/compliance | 安全策略 SECURITY.md | | 缺少 SECURITY.md无安全披露流程 |
| medium | repro/compliance | 版权声明 | | 未在 LICENSE/README 中发现版权声明(建议源文件头补 Copyright 注释) |
| medium | repro/compliance | 贡献指南 | | 缺少 CONTRIBUTING.md |
_复现分 7.0/10 · 合规分 6.2/10 · 树节点 22_

View File

@ -0,0 +1,148 @@
{
"scenario": "S3_compliance_reproducibility",
"repo": "caoweiqiong/zwf",
"default_branch": "master",
"license": "None",
"repro_items": [
{
"name": "CI 配置",
"pass": false,
"score": 0,
"evidence": "未找到 .gitea/.github/.gitlab 等 CI 配置"
},
{
"name": "依赖锁文件",
"pass": true,
"score": 2,
"evidence": "存在 lockfile: package-lock.json"
},
{
"name": "README 复现说明",
"pass": true,
"score": 2,
"evidence": "README 含复现关键词 11 个: install, 环境, 依赖, build, 构建"
},
{
"name": "版本 tag",
"pass": false,
"score": 1,
"evidence": "repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本"
},
{
"name": "容器化环境",
"pass": true,
"score": 2,
"evidence": "存在容器配置: docker-compose.yml"
}
],
"compliance_items": [
{
"name": "LICENSE 文件",
"pass": false,
"score": 0,
"evidence": "缺少 LICENSE 文件"
},
{
"name": "安全策略 SECURITY.md",
"pass": false,
"score": 0,
"evidence": "缺少 SECURITY.md无安全披露流程"
},
{
"name": "版权声明",
"pass": false,
"score": 1,
"evidence": "未在 LICENSE/README 中发现版权声明(建议源文件头补 Copyright 注释)"
},
{
"name": "依赖清单声明",
"pass": true,
"score": 2,
"evidence": "存在依赖管理文件(建议核对各依赖许可证兼容性)"
},
{
"name": "贡献指南",
"pass": false,
"score": 1,
"evidence": "缺少 CONTRIBUTING.md"
}
],
"privacy_items": [
{
"name": "数据目录入库",
"pass": true,
"score": 2,
"evidence": "未发现 data/ 目录入库"
},
{
"name": ".env 入库",
"pass": true,
"score": 2,
"evidence": ".env 未入库"
},
{
"name": ".gitignore 忽略 .env",
"pass": true,
"score": 2,
"evidence": ".gitignore 已配置忽略 .env"
}
],
"secrets": [],
"risks": [
{
"area": "repro/compliance",
"name": "CI 配置",
"evidence": "未找到 .gitea/.github/.gitlab 等 CI 配置",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "版本 tag",
"evidence": "repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "LICENSE 文件",
"evidence": "缺少 LICENSE 文件",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "安全策略 SECURITY.md",
"evidence": "缺少 SECURITY.md无安全披露流程",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "版权声明",
"evidence": "未在 LICENSE/README 中发现版权声明(建议源文件头补 Copyright 注释)",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "贡献指南",
"evidence": "缺少 CONTRIBUTING.md",
"level": "medium"
}
],
"repro_score": 7.0,
"compliance_score": 6.2,
"meta": {
"key_files_found": [
".gitignore",
"README.md",
"package.json"
],
"tree_size": 22,
"languages": {
"Batchfile": "0.2%",
"CSS": "3.4%",
"HTML": "29.2%",
"JavaScript": "1.6%",
"Python": "21.1%",
"Shell": "0.7%",
"TypeScript": "43.8%"
}
}
}

View File

@ -0,0 +1,47 @@
# 科研成果可视化沉淀报告 — caoweiqiong/zwf
> 场景 S6 · 子赛题四「应用 GitLink 辅助科研」
## 一、活跃度概览(最近 26 周)
- 提交数: **30**(窗口内峰值 15 提交/周)
- 新增 Issue: **0**,新增 PR: **0**
- 贡献者: **4**,里程碑: **0**
## 二、开发节奏(最近 8 周快照)
| 周 | commits | issues | prs |
|----|---------|--------|-----|
| 2026-W21 | 0 | 0 | 0 |
| 2026-W22 | 0 | 0 | 0 |
| 2026-W23 | 0 | 0 | 0 |
| 2026-W24 | 1 | 0 | 0 |
| 2026-W25 | 0 | 0 | 0 |
| 2026-W26 | 2 | 0 | 0 |
| 2026-W27 | 10 | 0 | 0 |
| 2026-W28 | 2 | 0 | 0 |
## 三、核心贡献者热力(贡献者 × 周提交数)
| 贡献者 | 窗口内提交 |
|--------|-----------|
| `dev` | 0 |
| `huster42` | 0 |
| `whale` | 3 |
| `LegendC` | 1 |
| `HUSTER42` | 5 |
| `Dev` | 19 |
## 四、科研产物分类
- 论文/笔记 (paper): **0**
- 数据集 (dataset): **0**
- 模型 (model): **0**
- 基准 (benchmark): **0**
## 五、抽取到的论文引用
_未在 README/提交信息中发现 arXiv 或 DOI 引用_
_交互可视化见 visual.html或原始数据 visual.json_

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,352 @@
{
"scenario": "S6_research_visualization",
"repo": "caoweiqiong/zwf",
"weeks": 26,
"timeline": {
"labels": [
"2026-W03",
"2026-W04",
"2026-W05",
"2026-W06",
"2026-W07",
"2026-W08",
"2026-W09",
"2026-W10",
"2026-W11",
"2026-W12",
"2026-W13",
"2026-W14",
"2026-W15",
"2026-W16",
"2026-W17",
"2026-W18",
"2026-W19",
"2026-W20",
"2026-W21",
"2026-W22",
"2026-W23",
"2026-W24",
"2026-W25",
"2026-W26",
"2026-W27",
"2026-W28"
],
"commits": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
15,
0,
0,
0,
0,
1,
0,
2,
10,
2
],
"issues": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"prs": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
]
},
"heatmap": {
"users": [
"dev",
"huster42",
"whale",
"LegendC",
"HUSTER42",
"Dev"
],
"weeks": [
"2026-W03",
"2026-W04",
"2026-W05",
"2026-W06",
"2026-W07",
"2026-W08",
"2026-W09",
"2026-W10",
"2026-W11",
"2026-W12",
"2026-W13",
"2026-W14",
"2026-W15",
"2026-W16",
"2026-W17",
"2026-W18",
"2026-W19",
"2026-W20",
"2026-W21",
"2026-W22",
"2026-W23",
"2026-W24",
"2026-W25",
"2026-W26",
"2026-W27",
"2026-W28"
],
"matrix": [
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
3
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
15,
0,
0,
0,
0,
1,
0,
2,
1
]
]
},
"languages": {
"Batchfile": "0.2%",
"CSS": "3.4%",
"HTML": "29.2%",
"JavaScript": "1.6%",
"Python": "21.1%",
"Shell": "0.7%",
"TypeScript": "43.8%"
},
"milestones": [],
"paper_links": [],
"artifacts": [],
"artifact_summary": {
"paper": 0,
"dataset": 0,
"model": 0,
"benchmark": 0
},
"meta": {
"commit_count": 30,
"issue_count": 0,
"pr_count": 0,
"milestone_count": 0,
"contributor_count": 4
}
}

View File

@ -0,0 +1,34 @@
```mermaid
gitGraph
commit id: "master 起点"
commit
commit
commit
commit id: "#5" tag: "2026-05-29"
commit
commit
commit
commit id: "#12 创新点" tag: "2026-06-01"
commit
commit
commit
commit id: "#14 创新点" tag: "2026-06-03"
commit
commit
commit
commit id: "#18 创新点" tag: "2026-06-15"
commit
commit
commit
commit id: "#21" tag: "2026-06-29"
commit
commit
commit
commit id: "#31 创新点" tag: "2026-07-07"
commit
commit
commit
commit id: "#28" tag: "2026-07-07"
commit
commit
```

View File

@ -0,0 +1,281 @@
{
"scenario": "S1_repository_research_insight",
"repo": "whale_hihihi/gitlink-cli",
"default_branch": "master",
"commit_timeline": [
{
"date": "2026-06-23",
"count": 2
},
{
"date": "2026-06-24",
"count": 2
},
{
"date": "2026-06-29",
"count": 2
},
{
"date": "2026-07-02",
"count": 5
},
{
"date": "2026-07-04",
"count": 1
},
{
"date": "2026-07-05",
"count": 7
},
{
"date": "2026-07-06",
"count": 8
},
{
"date": "2026-07-07",
"count": 23
}
],
"branch_map": [
{
"name": "master",
"commits": 50,
"last_active": "2026-07-07",
"is_default": true
}
],
"pr_merge_patterns": [
{
"number": 2,
"title": "本次实现search +issues — 搜索 Issue 功能",
"status": "merged",
"merged_time": "2026-05-25",
"changed_files": 4
},
{
"number": 3,
"title": "创建 webhook 领域 + 实现 `+update`",
"status": "merged",
"merged_time": "2026-05-28",
"changed_files": 2
},
{
"number": 5,
"title": "release download 功能(新增) 在 release.go 的 Shortcuts() 中新增第 5 个快捷命令 download 参数:-",
"status": "merged",
"merged_time": "2026-05-29",
"changed_files": 7
},
{
"number": 4,
"title": "label 领域原来只有 3 个命令list/create/delete现在新增了 update 命令。",
"status": "merged",
"merged_time": "2026-05-29",
"changed_files": 3
},
{
"number": 6,
"title": "release download 命令 新增 download 快捷命令、错误消息统一化",
"status": "merged",
"merged_time": "2026-05-30",
"changed_files": 8
},
{
"number": 12,
"title": "feat: 实现 batch issue 批量操作命令",
"status": "merged",
"merged_time": "2026-06-01",
"changed_files": 14
},
{
"number": 8,
"title": "文件描述符泄漏等修改",
"status": "merged",
"merged_time": "2026-06-01",
"changed_files": 5
},
{
"number": 7,
"title": "代码片段管理功能",
"status": "merged",
"merged_time": "2026-06-01",
"changed_files": 5
},
{
"number": 14,
"title": "feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理",
"status": "merged",
"merged_time": "2026-06-03",
"changed_files": 31
},
{
"number": 15,
"title": "修改编译",
"status": "merged",
"merged_time": "2026-06-04",
"changed_files": 9
},
{
"number": 16,
"title": "新增skills",
"status": "merged",
"merged_time": "2026-06-12",
"changed_files": 26
},
{
"number": 18,
"title": "feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化",
"status": "merged",
"merged_time": "2026-06-15",
"changed_files": 151
},
{
"number": 19,
"title": "新增skills",
"status": "merged",
"merged_time": "2026-06-23",
"changed_files": 7
},
{
"number": 20,
"title": "注册重编激活 25 域、新增 6 个 Skill、补全索引与示例、产出任务三/四的端到端工作流",
"status": "merged",
"merged_time": "2026-06-24",
"changed_files": 5
},
{
"number": 21,
"title": "验证部分内容,作出相关修改",
"status": "merged",
"merged_time": "2026-06-29",
"changed_files": 1
},
{
"number": 22,
"title": "修改了两个skills的命令使用",
"status": "merged",
"merged_time": "2026-07-02",
"changed_files": 2
},
{
"number": 24,
"title": "新增demo",
"status": "merged",
"merged_time": "2026-07-06",
"changed_files": 19
},
{
"number": 31,
"title": "修改知识图谱构建方法",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 111
},
{
"number": 30,
"title": "fix(sweep): wiki 发布链路修复 + 端到端验证",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 7
},
{
"number": 29,
"title": "feat: 统一全链路科研分析页面 + Dockerfile 修复",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 13
},
{
"number": 28,
"title": "feat(demo): 调整 demo 前端展示(合并 surponess_br 第二批)",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 2
},
{
"number": 27,
"title": "feat(demo): 优化 demo 前端展示(合并 surponess_br",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 3
},
{
"number": 26,
"title": "chore: move community-ops-sweep workflow to project root workflows/",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 8
}
],
"doc_evolution": [
{
"file": "i18n.md",
"last_date": ""
},
{
"file": "pr-draft.md",
"last_date": ""
},
{
"file": "workflow-agent-design.md",
"last_date": ""
},
{
"file": "workflow-agent-test-report.md",
"last_date": ""
}
],
"experiment_files": [
"docs/workflow-agent-test-report.md",
"main_test.go",
"pr-test-file.txt"
],
"innovation_points": [
{
"description": "feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化",
"evidence": "PR #18 「feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化」 改动 151 文件,合并于 2026-06-15",
"category": "大规模重构/新特性"
},
{
"description": "修改知识图谱构建方法",
"evidence": "PR #31 「修改知识图谱构建方法」 改动 111 文件,合并于 2026-07-07",
"category": "大规模重构/新特性"
},
{
"description": "feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理",
"evidence": "PR #14 「feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理」 改动 31 文件,合并于 2026-06-03",
"category": "大规模重构/新特性"
},
{
"description": "新增skills",
"evidence": "PR #16 「新增skills」 改动 26 文件,合并于 2026-06-12",
"category": "大规模重构/新特性"
},
{
"description": "新增demo",
"evidence": "PR #24 「新增demo」 改动 19 文件,合并于 2026-07-06",
"category": "大规模重构/新特性"
},
{
"description": "feat: 实现 batch issue 批量操作命令",
"evidence": "PR #12 「feat: 实现 batch issue 批量操作命令」 改动 14 文件,合并于 2026-06-01",
"category": "大规模重构/新特性"
},
{
"description": "feat: 统一全链路科研分析页面 + Dockerfile 修复",
"evidence": "PR #29 「feat: 统一全链路科研分析页面 + Dockerfile 修复」 改动 13 文件,合并于 2026-07-07",
"category": "大规模重构/新特性"
},
{
"description": "release download 命令 新增 download 快捷命令、错误消息统一化",
"evidence": "PR #6 「release download 命令 新增 download 快捷命令、错误消息统一化」 改动 8 文件,合并于 2026-05-30",
"category": "特性引入"
}
],
"meta": {
"commit_count": 50,
"merged_pr_count": 23,
"doc_count": 4,
"experiment_file_count": 3
}
}

View File

@ -0,0 +1,71 @@
# 仓库级科研项目洞悉报告 — whale_hihihi/gitlink-cli
> 场景 S1 · 子赛题四「应用 GitLink 辅助科研」· 项目谱系lineage分析
## 一、基础信息
- **默认分支**: `master`
- **采样提交**: 50 条(默认分支,最多 10×100
- **已合并 PR**: 23 个
- **文档文件**: 4 个
- **实验/评测文件**: 3 个
## 二、提交活跃度时间线
- 时间跨度: 2026-06-23 → 2026-07-07共 8 个有提交的日期)
- 峰值: 2026-07-07 当日 23 次提交
## 三、分支地图
| 分支 | 提交数 | 最后活跃 | 是否默认 |
|------|:------:|----------|:--------:|
| `master` | 50 | 2026-07-07 | 是 |
## 四、合并 PR 演进模式(高影响合并预览)
| PR | 标题 | 改动文件 | 合并时间 |
|----|------|:--------:|----------|
| #2 | 本次实现search +issues — 搜索 Issue 功能 | 4 | 2026-05-25 |
| #3 | 创建 webhook 领域 + 实现 `+update` | 2 | 2026-05-28 |
| #5 | release download 功能(新增) 在 release.go 的 Shortcuts() 中新增第 5 个快捷命令 download 参数:- | 7 | 2026-05-29 |
| #4 | label 领域原来只有 3 个命令list/create/delete现在新增了 update 命令。 | 3 | 2026-05-29 |
| #6 | release download 命令 新增 download 快捷命令、错误消息统一化 | 8 | 2026-05-30 |
| #12 | feat: 实现 batch issue 批量操作命令 | 14 | 2026-06-01 |
| #8 | 文件描述符泄漏等修改 | 5 | 2026-06-01 |
| #7 | 代码片段管理功能 | 5 | 2026-06-01 |
| #14 | feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理 | 31 | 2026-06-03 |
| #15 | 修改编译 | 9 | 2026-06-04 |
## 五、创新/里程碑点
1. **[大规模重构/新特性]** feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化
- 证据: PR #18 「feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化」 改动 151 文件,合并于 2026-06-15
2. **[大规模重构/新特性]** 修改知识图谱构建方法
- 证据: PR #31 「修改知识图谱构建方法」 改动 111 文件,合并于 2026-07-07
3. **[大规模重构/新特性]** feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理
- 证据: PR #14 「feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理」 改动 31 文件,合并于 2026-06-03
4. **[大规模重构/新特性]** 新增skills
- 证据: PR #16 「新增skills」 改动 26 文件,合并于 2026-06-12
5. **[大规模重构/新特性]** 新增demo
- 证据: PR #24 「新增demo」 改动 19 文件,合并于 2026-07-06
6. **[大规模重构/新特性]** feat: 实现 batch issue 批量操作命令
- 证据: PR #12 「feat: 实现 batch issue 批量操作命令」 改动 14 文件,合并于 2026-06-01
7. **[大规模重构/新特性]** feat: 统一全链路科研分析页面 + Dockerfile 修复
- 证据: PR #29 「feat: 统一全链路科研分析页面 + Dockerfile 修复」 改动 13 文件,合并于 2026-07-07
8. **[特性引入]** release download 命令 新增 download 快捷命令、错误消息统一化
- 证据: PR #6 「release download 命令 新增 download 快捷命令、错误消息统一化」 改动 8 文件,合并于 2026-05-30
## 六、文档演进docs/*
| 文档 | 近似最后日期 |
|------|--------------|
| i18n.md | — |
| pr-draft.md | — |
| workflow-agent-design.md | — |
| workflow-agent-test-report.md | — |
## 七、实验/评测文件组织
- `docs/workflow-agent-test-report.md`
- `main_test.go`
- `pr-test-file.txt`

View File

@ -0,0 +1,389 @@
{
"scenario": "hotspot",
"keywords": [
"深度学习"
],
"category": "",
"trending_repos": [
{
"repo": "Edgedev/Edge-Computing-Engine",
"description": "Edge : 一个开源的科学计算引擎",
"language": "C++",
"stars": 3,
"forks": 1,
"visits": 593,
"score": 64,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-07-13",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "CocytusXRS/AI_test",
"description": "",
"language": "Jupyter notebook",
"stars": 0,
"forks": 0,
"visits": 550,
"score": 55,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2022-12-02",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "AIEven/AIkun",
"description": "",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 382,
"score": 38,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2025-08-09",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "shenyan/machineLearningTemplate",
"description": "基于pytorch lightning的机器学习模板, 用于对机器学习算法进行训练, 验证, 测试等, 目前实现了神经网路, 深度学习, k折交叉, 自动保存训练信息等. ",
"language": "Python",
"stars": 1,
"forks": 0,
"visits": 309,
"score": 31,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-10-22",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "opensci/pDeep",
"description": "pDeep是一种基于深度学习的质谱预测系统。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 292,
"score": 29,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-03-19",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "dongeliu/dlvc",
"description": "一种视频编解码原型系统,内嵌深度学习编码工具显著提高压缩效率。",
"language": "C++",
"stars": 0,
"forks": 0,
"visits": 276,
"score": 27,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-03-19",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "Hua135/sam-optimizers",
"description": "深度神经网络的泛化能力是机器学习领域的核心问题之一。传统优化算法如随机梯度下降SGD和Adam仅最小化训练损失值容易导致模型收敛到尖锐的最小值点从而影响泛化性能。近年来锐度感知最小化Sharpness-Aware Minimization, SAM通过同时最小化损失值和损失锐度有效提升了模型的泛化能力但其计算开销约为传统优化器的两倍。本文系统研究了SAM及其两种高效变体——ESA",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 64,
"score": 26,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-06-23",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "ashh/jittor-chanshiguan-track2-straightpcf-denoise",
"description": "赛道二三维点云降噪项目,基于 StraightPCF 复现并改进三阶段耦合速度场方法:单速度预训练、双速度耦合训练、距离缩放模块精调。采用 patch 级迭代推理与稳健重建保证输入输出点数一致。最佳提交成绩72.63CD 60.31 / P2S 84.96)。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 41,
"score": 24,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-06-27",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "clj111/Edge-Computing-Engine",
"description": "Edge : 一个开源的科学计算引擎",
"language": "C++",
"stars": 0,
"forks": 0,
"visits": 186,
"score": 18,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-06-16",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "njuiselab/Gandalf",
"description": "",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 189,
"score": 18,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2024-10-11",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "ly15927029790/CodeRecommendation",
"description": "代码生成式补全工具",
"language": "Java",
"stars": 0,
"forks": 0,
"visits": 177,
"score": 17,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2020-10-12",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "co63oc/mcTVM",
"description": "mcTVM是MetaX-MACA生态下的开源深度学习编译框架项目基于Apache TVM v0.18.0版本进行扩展开发新增对沐曦MetaXGPU的专属支持打通沐曦GPU与TVM框架的适配通道实现深度学习模型在沐曦GPU上的高效编译、优化与部署。mcTVM助力完善沐曦GPU的软件生态为开发者提供便捷、高效的深度学习模型部署解决方案适用于人工智能、异构计算等相关领域的研发与应用场景。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 66,
"score": 16,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-04-15",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "aaasdasd/aa",
"description": "",
"language": "Python3.6",
"stars": 0,
"forks": 0,
"visits": 146,
"score": 14,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2023-07-15",
"contributors_count": 0,
"releases_count": 0
}
],
"active_discussions": [],
"topic_heat": [
{
"topic": "deep_learning",
"count": 15
},
{
"topic": "scientific_computing",
"count": 7
},
{
"topic": "computer_vision",
"count": 6
},
{
"topic": "machine_learning",
"count": 4
},
{
"topic": "database",
"count": 3
},
{
"topic": "time_series",
"count": 3
},
{
"topic": "generative_ai",
"count": 3
},
{
"topic": "reinforcement_learning",
"count": 2
},
{
"topic": "nlp",
"count": 2
},
{
"topic": "autonomous_systems",
"count": 2
}
],
"core_scholars": [
{
"login": "Edge",
"repo_count": 2,
"repos": [
"Edgedev/Edge-Computing-Engine",
"clj111/Edge-Computing-Engine"
]
},
{
"login": "junru shao",
"repo_count": 2,
"repos": [
"co63oc/mcTVM"
]
},
{
"login": "Edgedev",
"repo_count": 1,
"repos": [
"Edgedev/Edge-Computing-Engine"
]
},
{
"login": "cloudy1225",
"repo_count": 1,
"repos": [
"CocytusXRS/AI_test"
]
},
{
"login": "CocytusXRS",
"repo_count": 1,
"repos": [
"CocytusXRS/AI_test"
]
},
{
"login": "AIEven",
"repo_count": 1,
"repos": [
"AIEven/AIkun"
]
},
{
"login": "shenyan",
"repo_count": 1,
"repos": [
"shenyan/machineLearningTemplate"
]
},
{
"login": "jalew",
"repo_count": 1,
"repos": [
"opensci/pDeep"
]
},
{
"login": "wen-feng zeng",
"repo_count": 1,
"repos": [
"opensci/pDeep"
]
},
{
"login": "dong liu",
"repo_count": 1,
"repos": [
"dongeliu/dlvc"
]
},
{
"login": "404notfound233",
"repo_count": 1,
"repos": [
"njuiselab/Gandalf"
]
},
{
"login": "beginner401",
"repo_count": 1,
"repos": [
"njuiselab/Gandalf"
]
}
],
"core_teams": [
{
"login": "Edgedev",
"repo_count": 1
},
{
"login": "CocytusXRS",
"repo_count": 1
},
{
"login": "AIEven",
"repo_count": 1
},
{
"login": "shenyan",
"repo_count": 1
},
{
"login": "opensci",
"repo_count": 1
},
{
"login": "dongeliu",
"repo_count": 1
},
{
"login": "clj111",
"repo_count": 1
},
{
"login": "njuiselab",
"repo_count": 1
}
],
"meta": {
"repo_count": 13,
"issue_count": 2,
"pr_count": 0,
"scholar_count": 35,
"discussion_count": 0,
"topic_count": 10
}
}

View File

@ -0,0 +1,50 @@
# 🔬 科研热点追踪报告
> 关键词:深度学习
> 扫描时间2026-07-08
> 覆盖仓库13 个 · 讨论 0 条 · 主题 10 个 · 学者 35 位
## 🔥 飙升项目 Top 5
| # | 仓库 | 语言 | 👁 访问 | ★ Star | ⑂ Fork | 热度 | 更新 |
|---|------|------|---------|--------|--------|------|------|
| 1 | `Edgedev/Edge-Computing-Engine` | C++ | 593 | 3 | 1 | 64 | 2021-07-13 |
| 2 | `CocytusXRS/AI_test` | Jupyter notebook | 550 | 0 | 0 | 55 | 2022-12-02 |
| 3 | `AIEven/AIkun` | Python | 382 | 0 | 0 | 38 | 2025-08-09 |
| 4 | `shenyan/machineLearningTemplate` | Python | 309 | 1 | 0 | 31 | 2021-10-22 |
| 5 | `opensci/pDeep` | Python | 292 | 0 | 0 | 29 | 2021-03-19 |
## 📊 热门主题
- **deep_learning** — 15 个仓库 ███████████████
- **scientific_computing** — 7 个仓库 ███████
- **computer_vision** — 6 个仓库 ██████
- **machine_learning** — 4 个仓库 ████
- **database** — 3 个仓库 ███
- **time_series** — 3 个仓库 ███
- **generative_ai** — 3 个仓库 ███
- **reinforcement_learning** — 2 个仓库 ██
- **nlp** — 2 个仓库 ██
- **autonomous_systems** — 2 个仓库 ██
## 👥 核心学者
- **Edge** — 关联 2 个仓库
- **junru shao** — 关联 2 个仓库
- **Edgedev** — 关联 1 个仓库
- **cloudy1225** — 关联 1 个仓库
- **CocytusXRS** — 关联 1 个仓库
## 🏛 活跃组织/团队
- **Edgedev** — 1 个仓库
- **CocytusXRS** — 1 个仓库
- **AIEven** — 1 个仓库
- **shenyan** — 1 个仓库
- **opensci** — 1 个仓库
- **dongeliu** — 1 个仓库
- **clj111** — 1 个仓库
- **njuiselab** — 1 个仓库
---
*由 gitlink-research-hotspot 自动生成*

View File

@ -0,0 +1,184 @@
{
"scenario": "inspire",
"mode": "repo",
"repo": "whale_hihihi/gitlink-cli",
"gap_topics": [
"reinforcement_learning",
"devops"
],
"needed_languages": [
"Dockerfile",
"Go",
"HTML",
"JavaScript",
"Mermaid",
"Python",
"Shell",
"go"
],
"gap_signals": [],
"candidates": [
{
"login": "wbtiger",
"score": 47.9,
"topic_overlap": 0.707,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [
"java",
"shell"
],
"repo_count": 15,
"reasons": [
"覆盖缺口主题: devops",
"本仓库活跃贡献者"
]
},
{
"login": "Mengz",
"score": 30.9,
"topic_overlap": 0.0,
"language_match": 0.091,
"activity_level": "high",
"repo_languages": [
"c++",
"go",
"markdown",
"python"
],
"repo_count": 15,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=5)"
]
},
{
"login": "muel",
"score": 28.4,
"topic_overlap": 0.0,
"language_match": 0.111,
"activity_level": "high",
"repo_languages": [
"go",
"typescript"
],
"repo_count": 5,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=4)"
]
},
{
"login": "puygob236",
"score": 22.4,
"topic_overlap": 0.0,
"language_match": 0.111,
"activity_level": "high",
"repo_languages": [
"go",
"typescript"
],
"repo_count": 3,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=2)"
]
},
{
"login": "baoerjun",
"score": 22.3,
"topic_overlap": 0.0,
"language_match": 0.111,
"activity_level": "high",
"repo_languages": [
"go",
"javascript"
],
"repo_count": 4,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=2)"
]
},
{
"login": "Surponess",
"score": 19.6,
"topic_overlap": 0.0,
"language_match": 0.1,
"activity_level": "high",
"repo_languages": [
"go",
"javascript",
"markdown"
],
"repo_count": 3,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=1)"
]
},
{
"login": "whale",
"score": 14.8,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
},
{
"login": "wauxing",
"score": 14.7,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
}
],
"innovation_points": [
{
"description": "feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化",
"evidence": "PR #18 「feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化」 改动 151 文件,合并于 2026-06-15",
"category": "大规模重构/新特性"
},
{
"description": "修改知识图谱构建方法",
"evidence": "PR #31 「修改知识图谱构建方法」 改动 111 文件,合并于 2026-07-07",
"category": "大规模重构/新特性"
},
{
"description": "feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理",
"evidence": "PR #14 「feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理」 改动 31 文件,合并于 2026-06-03",
"category": "大规模重构/新特性"
},
{
"description": "新增skills",
"evidence": "PR #16 「新增skills」 改动 26 文件,合并于 2026-06-12",
"category": "大规模重构/新特性"
},
{
"description": "新增demo",
"evidence": "PR #24 「新增demo」 改动 19 文件,合并于 2026-07-06",
"category": "大规模重构/新特性"
},
{
"description": "feat: 实现 batch issue 批量操作命令",
"evidence": "PR #12 「feat: 实现 batch issue 批量操作命令」 改动 14 文件,合并于 2026-06-01",
"category": "大规模重构/新特性"
}
],
"idea": null,
"llm_used": false
}

View File

@ -0,0 +1,26 @@
# 💡 创新启发报告
> 焦点仓库:`whale_hihihi/gitlink-cli`
> LLM 建议:⏭ 未启用(无 DEEPSEEK_API_KEY
## 🎯 缺口主题
`reinforcement_learning`, `devops`
## 🤝 可合作学者 Top 5
| 学者 | 契合度 | 主题重叠 | 语言匹配 | 活跃 | 理由 |
|---|---|---|---|---|---|
| `wbtiger` | 47.9 | 0.707 | 0.0 | high | 覆盖缺口主题: devops;本仓库活跃贡献者 |
| `Mengz` | 30.9 | 0.0 | 0.091 | high | 语言匹配: go;本仓库活跃贡献者 |
| `muel` | 28.4 | 0.0 | 0.111 | high | 语言匹配: go;本仓库活跃贡献者 |
| `puygob236` | 22.4 | 0.0 | 0.111 | high | 语言匹配: go;本仓库活跃贡献者 |
| `baoerjun` | 22.3 | 0.0 | 0.111 | high | 语言匹配: go;本仓库活跃贡献者 |
## 🌟 近期创新点
- feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化 _(大规模重构/新特性)_
- 修改知识图谱构建方法 _(大规模重构/新特性)_
- feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理 _(大规模重构/新特性)_
- 新增skills _(大规模重构/新特性)_
- 新增demo _(大规模重构/新特性)_
---
*由 gitlink-research-inspire 生成*

View File

@ -0,0 +1,34 @@
```mermaid
gitGraph
commit id: "master 起点"
commit
commit
commit
commit id: "#5" tag: "2026-05-29"
commit
commit
commit
commit id: "#12 创新点" tag: "2026-06-01"
commit
commit
commit
commit id: "#14 创新点" tag: "2026-06-03"
commit
commit
commit
commit id: "#18 创新点" tag: "2026-06-15"
commit
commit
commit
commit id: "#21" tag: "2026-06-29"
commit
commit
commit
commit id: "#31 创新点" tag: "2026-07-07"
commit
commit
commit
commit id: "#28" tag: "2026-07-07"
commit
commit
```

View File

@ -0,0 +1,281 @@
{
"scenario": "S1_repository_research_insight",
"repo": "whale_hihihi/gitlink-cli",
"default_branch": "master",
"commit_timeline": [
{
"date": "2026-06-23",
"count": 2
},
{
"date": "2026-06-24",
"count": 2
},
{
"date": "2026-06-29",
"count": 2
},
{
"date": "2026-07-02",
"count": 5
},
{
"date": "2026-07-04",
"count": 1
},
{
"date": "2026-07-05",
"count": 7
},
{
"date": "2026-07-06",
"count": 8
},
{
"date": "2026-07-07",
"count": 23
}
],
"branch_map": [
{
"name": "master",
"commits": 50,
"last_active": "2026-07-07",
"is_default": true
}
],
"pr_merge_patterns": [
{
"number": 2,
"title": "本次实现search +issues — 搜索 Issue 功能",
"status": "merged",
"merged_time": "2026-05-25",
"changed_files": 4
},
{
"number": 3,
"title": "创建 webhook 领域 + 实现 `+update`",
"status": "merged",
"merged_time": "2026-05-28",
"changed_files": 2
},
{
"number": 5,
"title": "release download 功能(新增) 在 release.go 的 Shortcuts() 中新增第 5 个快捷命令 download 参数:-",
"status": "merged",
"merged_time": "2026-05-29",
"changed_files": 7
},
{
"number": 4,
"title": "label 领域原来只有 3 个命令list/create/delete现在新增了 update 命令。",
"status": "merged",
"merged_time": "2026-05-29",
"changed_files": 3
},
{
"number": 6,
"title": "release download 命令 新增 download 快捷命令、错误消息统一化",
"status": "merged",
"merged_time": "2026-05-30",
"changed_files": 8
},
{
"number": 12,
"title": "feat: 实现 batch issue 批量操作命令",
"status": "merged",
"merged_time": "2026-06-01",
"changed_files": 14
},
{
"number": 8,
"title": "文件描述符泄漏等修改",
"status": "merged",
"merged_time": "2026-06-01",
"changed_files": 5
},
{
"number": 7,
"title": "代码片段管理功能",
"status": "merged",
"merged_time": "2026-06-01",
"changed_files": 5
},
{
"number": 14,
"title": "feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理",
"status": "merged",
"merged_time": "2026-06-03",
"changed_files": 31
},
{
"number": 15,
"title": "修改编译",
"status": "merged",
"merged_time": "2026-06-04",
"changed_files": 9
},
{
"number": 16,
"title": "新增skills",
"status": "merged",
"merged_time": "2026-06-12",
"changed_files": 26
},
{
"number": 18,
"title": "feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化",
"status": "merged",
"merged_time": "2026-06-15",
"changed_files": 151
},
{
"number": 19,
"title": "新增skills",
"status": "merged",
"merged_time": "2026-06-23",
"changed_files": 7
},
{
"number": 20,
"title": "注册重编激活 25 域、新增 6 个 Skill、补全索引与示例、产出任务三/四的端到端工作流",
"status": "merged",
"merged_time": "2026-06-24",
"changed_files": 5
},
{
"number": 21,
"title": "验证部分内容,作出相关修改",
"status": "merged",
"merged_time": "2026-06-29",
"changed_files": 1
},
{
"number": 22,
"title": "修改了两个skills的命令使用",
"status": "merged",
"merged_time": "2026-07-02",
"changed_files": 2
},
{
"number": 24,
"title": "新增demo",
"status": "merged",
"merged_time": "2026-07-06",
"changed_files": 19
},
{
"number": 31,
"title": "修改知识图谱构建方法",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 111
},
{
"number": 30,
"title": "fix(sweep): wiki 发布链路修复 + 端到端验证",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 7
},
{
"number": 29,
"title": "feat: 统一全链路科研分析页面 + Dockerfile 修复",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 13
},
{
"number": 28,
"title": "feat(demo): 调整 demo 前端展示(合并 surponess_br 第二批)",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 2
},
{
"number": 27,
"title": "feat(demo): 优化 demo 前端展示(合并 surponess_br",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 3
},
{
"number": 26,
"title": "chore: move community-ops-sweep workflow to project root workflows/",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 8
}
],
"doc_evolution": [
{
"file": "i18n.md",
"last_date": ""
},
{
"file": "pr-draft.md",
"last_date": ""
},
{
"file": "workflow-agent-design.md",
"last_date": ""
},
{
"file": "workflow-agent-test-report.md",
"last_date": ""
}
],
"experiment_files": [
"docs/workflow-agent-test-report.md",
"main_test.go",
"pr-test-file.txt"
],
"innovation_points": [
{
"description": "feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化",
"evidence": "PR #18 「feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化」 改动 151 文件,合并于 2026-06-15",
"category": "大规模重构/新特性"
},
{
"description": "修改知识图谱构建方法",
"evidence": "PR #31 「修改知识图谱构建方法」 改动 111 文件,合并于 2026-07-07",
"category": "大规模重构/新特性"
},
{
"description": "feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理",
"evidence": "PR #14 「feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理」 改动 31 文件,合并于 2026-06-03",
"category": "大规模重构/新特性"
},
{
"description": "新增skills",
"evidence": "PR #16 「新增skills」 改动 26 文件,合并于 2026-06-12",
"category": "大规模重构/新特性"
},
{
"description": "新增demo",
"evidence": "PR #24 「新增demo」 改动 19 文件,合并于 2026-07-06",
"category": "大规模重构/新特性"
},
{
"description": "feat: 实现 batch issue 批量操作命令",
"evidence": "PR #12 「feat: 实现 batch issue 批量操作命令」 改动 14 文件,合并于 2026-06-01",
"category": "大规模重构/新特性"
},
{
"description": "feat: 统一全链路科研分析页面 + Dockerfile 修复",
"evidence": "PR #29 「feat: 统一全链路科研分析页面 + Dockerfile 修复」 改动 13 文件,合并于 2026-07-07",
"category": "大规模重构/新特性"
},
{
"description": "release download 命令 新增 download 快捷命令、错误消息统一化",
"evidence": "PR #6 「release download 命令 新增 download 快捷命令、错误消息统一化」 改动 8 文件,合并于 2026-05-30",
"category": "特性引入"
}
],
"meta": {
"commit_count": 50,
"merged_pr_count": 23,
"doc_count": 4,
"experiment_file_count": 3
}
}

View File

@ -0,0 +1,71 @@
# 仓库级科研项目洞悉报告 — whale_hihihi/gitlink-cli
> 场景 S1 · 子赛题四「应用 GitLink 辅助科研」· 项目谱系lineage分析
## 一、基础信息
- **默认分支**: `master`
- **采样提交**: 50 条(默认分支,最多 10×100
- **已合并 PR**: 23 个
- **文档文件**: 4 个
- **实验/评测文件**: 3 个
## 二、提交活跃度时间线
- 时间跨度: 2026-06-23 → 2026-07-07共 8 个有提交的日期)
- 峰值: 2026-07-07 当日 23 次提交
## 三、分支地图
| 分支 | 提交数 | 最后活跃 | 是否默认 |
|------|:------:|----------|:--------:|
| `master` | 50 | 2026-07-07 | 是 |
## 四、合并 PR 演进模式(高影响合并预览)
| PR | 标题 | 改动文件 | 合并时间 |
|----|------|:--------:|----------|
| #2 | 本次实现search +issues — 搜索 Issue 功能 | 4 | 2026-05-25 |
| #3 | 创建 webhook 领域 + 实现 `+update` | 2 | 2026-05-28 |
| #5 | release download 功能(新增) 在 release.go 的 Shortcuts() 中新增第 5 个快捷命令 download 参数:- | 7 | 2026-05-29 |
| #4 | label 领域原来只有 3 个命令list/create/delete现在新增了 update 命令。 | 3 | 2026-05-29 |
| #6 | release download 命令 新增 download 快捷命令、错误消息统一化 | 8 | 2026-05-30 |
| #12 | feat: 实现 batch issue 批量操作命令 | 14 | 2026-06-01 |
| #8 | 文件描述符泄漏等修改 | 5 | 2026-06-01 |
| #7 | 代码片段管理功能 | 5 | 2026-06-01 |
| #14 | feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理 | 31 | 2026-06-03 |
| #15 | 修改编译 | 9 | 2026-06-04 |
## 五、创新/里程碑点
1. **[大规模重构/新特性]** feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化
- 证据: PR #18 「feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化」 改动 151 文件,合并于 2026-06-15
2. **[大规模重构/新特性]** 修改知识图谱构建方法
- 证据: PR #31 「修改知识图谱构建方法」 改动 111 文件,合并于 2026-07-07
3. **[大规模重构/新特性]** feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理
- 证据: PR #14 「feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理」 改动 31 文件,合并于 2026-06-03
4. **[大规模重构/新特性]** 新增skills
- 证据: PR #16 「新增skills」 改动 26 文件,合并于 2026-06-12
5. **[大规模重构/新特性]** 新增demo
- 证据: PR #24 「新增demo」 改动 19 文件,合并于 2026-07-06
6. **[大规模重构/新特性]** feat: 实现 batch issue 批量操作命令
- 证据: PR #12 「feat: 实现 batch issue 批量操作命令」 改动 14 文件,合并于 2026-06-01
7. **[大规模重构/新特性]** feat: 统一全链路科研分析页面 + Dockerfile 修复
- 证据: PR #29 「feat: 统一全链路科研分析页面 + Dockerfile 修复」 改动 13 文件,合并于 2026-07-07
8. **[特性引入]** release download 命令 新增 download 快捷命令、错误消息统一化
- 证据: PR #6 「release download 命令 新增 download 快捷命令、错误消息统一化」 改动 8 文件,合并于 2026-05-30
## 六、文档演进docs/*
| 文档 | 近似最后日期 |
|------|--------------|
| i18n.md | — |
| pr-draft.md | — |
| workflow-agent-design.md | — |
| workflow-agent-test-report.md | — |
## 七、实验/评测文件组织
- `docs/workflow-agent-test-report.md`
- `main_test.go`
- `pr-test-file.txt`

View File

@ -0,0 +1,52 @@
{
"scenario": "profile",
"mode": "project",
"profiles": [
{
"type": "project",
"repo": "whale_hihihi/gitlink-cli",
"name": "gitlink-cli",
"description": "",
"topics": [
{
"topic": "reinforcement_learning",
"count": 1
},
{
"topic": "devops",
"count": 1
}
],
"languages": [
"Dockerfile",
"Go",
"HTML",
"JavaScript",
"Mermaid",
"Python",
"Shell"
],
"stars": 0,
"forks": 0,
"visits": 0,
"contributors_count": 20,
"top_contributors": [
"wbtiger",
"whale",
"wauxing",
"Surponess",
"wangyue789",
"tiger",
"muel",
"puygob236"
],
"score": {
"doc": 5,
"license": 0,
"collab": 10,
"impact": 0
},
"score_total": 15
}
]
}

View File

@ -0,0 +1,10 @@
# 🪪 主体画像报告
## 📦 gitlink-cli (`whale_hihihi/gitlink-cli`)
- ★0 ⑂0 👁0 · 贡献者 20 · 研究维度评分 **15/40**
- 主题:`reinforcement_learning`、`devops`
- 核心贡献者:`wbtiger`、`whale`、`wauxing`、`Surponess`、`wangyue789`、`tiger`
---
*由 gitlink-research-profile 生成*

View File

@ -0,0 +1,80 @@
{
"scenario": "S5_progress_tracking",
"repo": "whale_hihihi/gitlink-cli",
"generated_at": "2026-07-08T00:12:31.323273+00:00",
"week_stats": {
"this_week": {
"commits": 44,
"issues_opened": 0,
"issues_closed": 0,
"issues_stale": 0,
"prs_opened": 9,
"prs_merged": 8,
"prs_open_stale": 0,
"contributors_active": 7,
"contributors_active_logins": [
"Surponess",
"baoerjun",
"wauxing",
"wbtiger",
"whale",
"whale_hihihi",
"yangsai01"
]
},
"last_week": {
"commits": 4,
"issues_opened": 0,
"issues_closed": 0,
"issues_stale": 0,
"prs_opened": 2,
"prs_merged": 2,
"prs_open_stale": 0,
"contributors_active": 1,
"contributors_active_logins": [
"Surponess"
]
},
"window": {
"this_week_start": "2026-07-01T00:12:31.323273+00:00",
"now": "2026-07-08T00:12:31.323273+00:00",
"last_week_start": "2026-06-24T00:12:31.323273+00:00",
"last_week_end": "2026-07-01T00:12:31.323273+00:00"
},
"total_contributors": 20
},
"trend": {
"commit_delta_pct": 1000.0,
"activity_level": "increasing",
"this_week_commits": 44,
"last_week_commits": 4
},
"milestones": [
{
"name": "完成批量成员邀请",
"open": 0,
"closed": 0,
"total": 0,
"completion_pct": 0.0,
"due_date": "2026-06-04T00:00:00+00:00",
"overdue": true,
"status": "open"
}
],
"risk_warnings": [
{
"level": "critical",
"type": "overdue_milestone",
"message": "里程碑「完成批量成员邀请」已逾期due 2026-06-04T00:00:00+00:00完成率 0.0%",
"metric": 0.0,
"suggestion": "重新评估范围或顺延 deadline并同步干系人。"
}
],
"meta": {
"commits_fetched": 50,
"issues_fetched": 0,
"prs_fetched": 30,
"milestones_fetched": 1,
"contributors_fetched": 20
}
}

View File

@ -0,0 +1,36 @@
# 科研进度智能跟踪周报 — whale_hihihi/gitlink-cli
> 场景 S5 · 子赛题四「应用 GitLink 辅助科研」· 生成于 2026-07-08T00:12:31.323273+00:00
## 一、本周 / 上周活动对比
| 指标 | 本周 | 上周 |
|------|------|------|
| 提交 commits | 44 | 4 |
| Issue 新增 | 0 | 0 |
| Issue 关闭 | 0 | 0 |
| 开放 stale issue (>30天) | 0 | 0 |
| PR 新增 | 9 | 2 |
| PR 合并 | 8 | 2 |
| 开放 stale PR (>14天) | 0 | 0 |
| 活跃贡献者 | 7 | 1 |
- **趋势**commit 周环比 **1000.0%**,活跃度等级 `increasing`
## 二、里程碑进度
| 里程碑 | 完成/总数 | 完成率 | due_date | 状态 |
|--------|-----------|--------|----------|------|
| 完成批量成员邀请 ⚠️逾期 | 0/0 | 0.0% | 2026-06-04T00:00:00+00:00 | open |
## 三、风险预警
| 级别 | 类型 | 说明 | 建议 |
|------|------|------|------|
| critical | overdue_milestone | 里程碑「完成批量成员邀请」已逾期due 2026-06-04T00:00:00+00:00完成率 0.0% | 重新评估范围或顺延 deadline并同步干系人。 |
## 四、附
- 取数commits=50 issues=0 prs=30 milestones=1 contributors=20
- 窗口:本周 [2026-07-01T00:12:31.323273+00:00, 2026-07-08T00:12:31.323273+00:00];上周 [2026-06-24T00:12:31.323273+00:00, 2026-07-01T00:12:31.323273+00:00)
- 阈值stale_issue>30天 / stale_pr>14天 / 低活跃<3次/ / bus_factor>50%

View File

@ -0,0 +1,48 @@
# 科研项目合规与复现性检查报告 — whale_hihihi/gitlink-cli
> 场景 S3 · 子赛题四「应用 GitLink 辅助科研」
- **默认分支**: `master`
- **识别许可证**: `MulanPSL-2.0`
- **复现性评分**: **9.0/10**(良好)
- **合规性评分**: **7.5/10**(及格)
## 一、复现性检查清单
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| CI 配置 | PASS | 2/2 | 检测到 CI 配置: .devops, .gitea, .github |
| 依赖锁文件 | PASS | 2/2 | 存在 lockfile: go.sum |
| README 复现说明 | PASS | 2/2 | README 含复现关键词 10 个: install, setup, build, 运行, run |
| 版本 tag | FAIL | 1/2 | repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本 |
| 容器化环境 | PASS | 2/2 | 存在容器配置: Dockerfile |
## 二、合规性检查清单
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| LICENSE 文件 | PASS | 2/2 | LICENSE 声明为 MulanPSL-2.0 |
| 安全策略 SECURITY.md | FAIL | 0/2 | 缺少 SECURITY.md无安全披露流程 |
| 版权声明 | PASS | 2/2 | LICENSE/README 中含 copyright/版权 声明 |
| 依赖清单声明 | PASS | 2/2 | 存在依赖管理文件(建议核对各依赖许可证兼容性) |
| 贡献指南 | FAIL | 1/2 | 缺少 CONTRIBUTING.md |
## 三、数据隐私检查
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| 数据目录入库 | PASS | 2/2 | 未发现 data/ 目录入库 |
| .env 入库 | PASS | 2/2 | .env 未入库 |
| .gitignore 忽略 .env | FAIL | 1/2 | .gitignore 未忽略 .env建议添加 .env |
## 四、风险项(按严重程度排序)
| 级别 | 类别 | 名称 | 文件:行 | 证据 |
|:----:|------|------|---------|------|
| high | privacy | 数据隐私 | | .gitignore 未忽略 .env预防性建议 |
| medium | repro/compliance | 版本 tag | | repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本 |
| medium | repro/compliance | 安全策略 SECURITY.md | | 缺少 SECURITY.md无安全披露流程 |
| medium | repro/compliance | 贡献指南 | | 缺少 CONTRIBUTING.md |
| medium | repro/compliance | .gitignore 忽略 .env | | .gitignore 未忽略 .env建议添加 .env |
_复现分 9.0/10 · 合规分 7.5/10 · 树节点 31_

View File

@ -0,0 +1,143 @@
{
"scenario": "S3_compliance_reproducibility",
"repo": "whale_hihihi/gitlink-cli",
"default_branch": "master",
"license": "MulanPSL-2.0",
"repro_items": [
{
"name": "CI 配置",
"pass": true,
"score": 2,
"evidence": "检测到 CI 配置: .devops, .gitea, .github"
},
{
"name": "依赖锁文件",
"pass": true,
"score": 2,
"evidence": "存在 lockfile: go.sum"
},
{
"name": "README 复现说明",
"pass": true,
"score": 2,
"evidence": "README 含复现关键词 10 个: install, setup, build, 运行, run"
},
{
"name": "版本 tag",
"pass": false,
"score": 1,
"evidence": "repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本"
},
{
"name": "容器化环境",
"pass": true,
"score": 2,
"evidence": "存在容器配置: Dockerfile"
}
],
"compliance_items": [
{
"name": "LICENSE 文件",
"pass": true,
"score": 2,
"evidence": "LICENSE 声明为 MulanPSL-2.0"
},
{
"name": "安全策略 SECURITY.md",
"pass": false,
"score": 0,
"evidence": "缺少 SECURITY.md无安全披露流程"
},
{
"name": "版权声明",
"pass": true,
"score": 2,
"evidence": "LICENSE/README 中含 copyright/版权 声明"
},
{
"name": "依赖清单声明",
"pass": true,
"score": 2,
"evidence": "存在依赖管理文件(建议核对各依赖许可证兼容性)"
},
{
"name": "贡献指南",
"pass": false,
"score": 1,
"evidence": "缺少 CONTRIBUTING.md"
}
],
"privacy_items": [
{
"name": "数据目录入库",
"pass": true,
"score": 2,
"evidence": "未发现 data/ 目录入库"
},
{
"name": ".env 入库",
"pass": true,
"score": 2,
"evidence": ".env 未入库"
},
{
"name": ".gitignore 忽略 .env",
"pass": false,
"score": 1,
"evidence": ".gitignore 未忽略 .env建议添加 .env"
}
],
"secrets": [],
"risks": [
{
"area": "privacy",
"name": "数据隐私",
"evidence": ".gitignore 未忽略 .env预防性建议",
"level": "high"
},
{
"area": "repro/compliance",
"name": "版本 tag",
"evidence": "repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "安全策略 SECURITY.md",
"evidence": "缺少 SECURITY.md无安全披露流程",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "贡献指南",
"evidence": "缺少 CONTRIBUTING.md",
"level": "medium"
},
{
"area": "repro/compliance",
"name": ".gitignore 忽略 .env",
"evidence": ".gitignore 未忽略 .env建议添加 .env",
"level": "medium"
}
],
"repro_score": 9.0,
"compliance_score": 7.5,
"meta": {
"key_files_found": [
".gitignore",
"LICENSE",
"README.md",
"go.mod"
],
"tree_size": 31,
"languages": {
"Dockerfile": "0.1%",
"Go": "60.5%",
"HTML": "8.2%",
"JavaScript": "1.9%",
"Mermaid": "3.7%",
"Python": "22.4%",
"Shell": "3.2%"
}
}
}

View File

@ -0,0 +1,51 @@
# 科研成果可视化沉淀报告 — whale_hihihi/gitlink-cli
> 场景 S6 · 子赛题四「应用 GitLink 辅助科研」
## 一、活跃度概览(最近 26 周)
- 提交数: **50**(窗口内峰值 31 提交/周)
- 新增 Issue: **0**,新增 PR: **30**
- 贡献者: **20**,里程碑: **1**
## 二、开发节奏(最近 8 周快照)
| 周 | commits | issues | prs |
|----|---------|--------|-----|
| 2026-W21 | 0 | 0 | 0 |
| 2026-W22 | 0 | 0 | 6 |
| 2026-W23 | 0 | 0 | 9 |
| 2026-W24 | 0 | 0 | 1 |
| 2026-W25 | 0 | 0 | 2 |
| 2026-W26 | 4 | 0 | 2 |
| 2026-W27 | 15 | 0 | 2 |
| 2026-W28 | 31 | 0 | 8 |
## 三、核心贡献者热力(贡献者 × 周提交数)
| 贡献者 | 窗口内提交 |
|--------|-----------|
| `wbtiger` | 1 |
| `whale` | 9 |
| `wauxing` | 0 |
| `Surponess` | 8 |
| `wangyue789` | 0 |
| `tiger` | 0 |
| `muel` | 0 |
| `puygob236` | 0 |
| `wbavon` | 0 |
| `Mengz` | 0 |
## 四、科研产物分类
- 论文/笔记 (paper): **0**
- 数据集 (dataset): **0**
- 模型 (model): **0**
- 基准 (benchmark): **0**
## 五、抽取到的论文引用
_未在 README/提交信息中发现 arXiv 或 DOI 引用_
_交互可视化见 visual.html或原始数据 visual.json_

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,532 @@
{
"scenario": "S6_research_visualization",
"repo": "whale_hihihi/gitlink-cli",
"weeks": 26,
"timeline": {
"labels": [
"2026-W03",
"2026-W04",
"2026-W05",
"2026-W06",
"2026-W07",
"2026-W08",
"2026-W09",
"2026-W10",
"2026-W11",
"2026-W12",
"2026-W13",
"2026-W14",
"2026-W15",
"2026-W16",
"2026-W17",
"2026-W18",
"2026-W19",
"2026-W20",
"2026-W21",
"2026-W22",
"2026-W23",
"2026-W24",
"2026-W25",
"2026-W26",
"2026-W27",
"2026-W28"
],
"commits": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
15,
31
],
"issues": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"prs": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
6,
9,
1,
2,
2,
2,
8
]
},
"heatmap": {
"users": [
"wbtiger",
"whale",
"wauxing",
"Surponess",
"wangyue789",
"tiger",
"muel",
"puygob236",
"wbavon",
"Mengz",
"baoerjun",
"yangsai01"
],
"weeks": [
"2026-W03",
"2026-W04",
"2026-W05",
"2026-W06",
"2026-W07",
"2026-W08",
"2026-W09",
"2026-W10",
"2026-W11",
"2026-W12",
"2026-W13",
"2026-W14",
"2026-W15",
"2026-W16",
"2026-W17",
"2026-W18",
"2026-W19",
"2026-W20",
"2026-W21",
"2026-W22",
"2026-W23",
"2026-W24",
"2026-W25",
"2026-W26",
"2026-W27",
"2026-W28"
],
"matrix": [
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
9
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
4
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1
]
]
},
"languages": {
"Dockerfile": "0.1%",
"Go": "60.5%",
"HTML": "8.2%",
"JavaScript": "1.9%",
"Mermaid": "3.7%",
"Python": "22.4%",
"Shell": "3.2%"
},
"milestones": [
{
"title": "完成批量成员邀请",
"start": 1779321600.0,
"due": 1780531200.0
}
],
"paper_links": [],
"artifacts": [],
"artifact_summary": {
"paper": 0,
"dataset": 0,
"model": 0,
"benchmark": 0
},
"meta": {
"commit_count": 50,
"issue_count": 0,
"pr_count": 30,
"milestone_count": 1,
"contributor_count": 20
}
}

View File

@ -0,0 +1,389 @@
{
"scenario": "hotspot",
"keywords": [
"深度学习"
],
"category": "",
"trending_repos": [
{
"repo": "Edgedev/Edge-Computing-Engine",
"description": "Edge : 一个开源的科学计算引擎",
"language": "C++",
"stars": 3,
"forks": 1,
"visits": 593,
"score": 64,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-07-13",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "CocytusXRS/AI_test",
"description": "",
"language": "Jupyter notebook",
"stars": 0,
"forks": 0,
"visits": 550,
"score": 55,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2022-12-02",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "AIEven/AIkun",
"description": "",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 382,
"score": 38,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2025-08-09",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "shenyan/machineLearningTemplate",
"description": "基于pytorch lightning的机器学习模板, 用于对机器学习算法进行训练, 验证, 测试等, 目前实现了神经网路, 深度学习, k折交叉, 自动保存训练信息等. ",
"language": "Python",
"stars": 1,
"forks": 0,
"visits": 309,
"score": 31,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-10-22",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "opensci/pDeep",
"description": "pDeep是一种基于深度学习的质谱预测系统。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 292,
"score": 29,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-03-19",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "dongeliu/dlvc",
"description": "一种视频编解码原型系统,内嵌深度学习编码工具显著提高压缩效率。",
"language": "C++",
"stars": 0,
"forks": 0,
"visits": 276,
"score": 27,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-03-19",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "Hua135/sam-optimizers",
"description": "深度神经网络的泛化能力是机器学习领域的核心问题之一。传统优化算法如随机梯度下降SGD和Adam仅最小化训练损失值容易导致模型收敛到尖锐的最小值点从而影响泛化性能。近年来锐度感知最小化Sharpness-Aware Minimization, SAM通过同时最小化损失值和损失锐度有效提升了模型的泛化能力但其计算开销约为传统优化器的两倍。本文系统研究了SAM及其两种高效变体——ESA",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 64,
"score": 26,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-06-23",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "ashh/jittor-chanshiguan-track2-straightpcf-denoise",
"description": "赛道二三维点云降噪项目,基于 StraightPCF 复现并改进三阶段耦合速度场方法:单速度预训练、双速度耦合训练、距离缩放模块精调。采用 patch 级迭代推理与稳健重建保证输入输出点数一致。最佳提交成绩72.63CD 60.31 / P2S 84.96)。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 41,
"score": 24,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-06-27",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "clj111/Edge-Computing-Engine",
"description": "Edge : 一个开源的科学计算引擎",
"language": "C++",
"stars": 0,
"forks": 0,
"visits": 186,
"score": 18,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2021-06-16",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "njuiselab/Gandalf",
"description": "",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 189,
"score": 18,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2024-10-11",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "ly15927029790/CodeRecommendation",
"description": "代码生成式补全工具",
"language": "Java",
"stars": 0,
"forks": 0,
"visits": 177,
"score": 17,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2020-10-12",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "co63oc/mcTVM",
"description": "mcTVM是MetaX-MACA生态下的开源深度学习编译框架项目基于Apache TVM v0.18.0版本进行扩展开发新增对沐曦MetaXGPU的专属支持打通沐曦GPU与TVM框架的适配通道实现深度学习模型在沐曦GPU上的高效编译、优化与部署。mcTVM助力完善沐曦GPU的软件生态为开发者提供便捷、高效的深度学习模型部署解决方案适用于人工智能、异构计算等相关领域的研发与应用场景。",
"language": "Python",
"stars": 0,
"forks": 0,
"visits": 66,
"score": 16,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2026-04-15",
"contributors_count": 0,
"releases_count": 0
},
{
"repo": "aaasdasd/aa",
"description": "",
"language": "Python3.6",
"stars": 0,
"forks": 0,
"visits": 146,
"score": 14,
"velocity": 0.0,
"matched_keywords": [
"深度学习"
],
"updated": "2023-07-15",
"contributors_count": 0,
"releases_count": 0
}
],
"active_discussions": [],
"topic_heat": [
{
"topic": "deep_learning",
"count": 15
},
{
"topic": "scientific_computing",
"count": 7
},
{
"topic": "computer_vision",
"count": 6
},
{
"topic": "machine_learning",
"count": 4
},
{
"topic": "database",
"count": 3
},
{
"topic": "time_series",
"count": 3
},
{
"topic": "generative_ai",
"count": 3
},
{
"topic": "reinforcement_learning",
"count": 2
},
{
"topic": "nlp",
"count": 2
},
{
"topic": "autonomous_systems",
"count": 2
}
],
"core_scholars": [
{
"login": "Edge",
"repo_count": 2,
"repos": [
"Edgedev/Edge-Computing-Engine",
"clj111/Edge-Computing-Engine"
]
},
{
"login": "junru shao",
"repo_count": 2,
"repos": [
"co63oc/mcTVM"
]
},
{
"login": "Edgedev",
"repo_count": 1,
"repos": [
"Edgedev/Edge-Computing-Engine"
]
},
{
"login": "cloudy1225",
"repo_count": 1,
"repos": [
"CocytusXRS/AI_test"
]
},
{
"login": "CocytusXRS",
"repo_count": 1,
"repos": [
"CocytusXRS/AI_test"
]
},
{
"login": "AIEven",
"repo_count": 1,
"repos": [
"AIEven/AIkun"
]
},
{
"login": "shenyan",
"repo_count": 1,
"repos": [
"shenyan/machineLearningTemplate"
]
},
{
"login": "jalew",
"repo_count": 1,
"repos": [
"opensci/pDeep"
]
},
{
"login": "wen-feng zeng",
"repo_count": 1,
"repos": [
"opensci/pDeep"
]
},
{
"login": "dong liu",
"repo_count": 1,
"repos": [
"dongeliu/dlvc"
]
},
{
"login": "404notfound233",
"repo_count": 1,
"repos": [
"njuiselab/Gandalf"
]
},
{
"login": "beginner401",
"repo_count": 1,
"repos": [
"njuiselab/Gandalf"
]
}
],
"core_teams": [
{
"login": "Edgedev",
"repo_count": 1
},
{
"login": "CocytusXRS",
"repo_count": 1
},
{
"login": "AIEven",
"repo_count": 1
},
{
"login": "shenyan",
"repo_count": 1
},
{
"login": "opensci",
"repo_count": 1
},
{
"login": "dongeliu",
"repo_count": 1
},
{
"login": "clj111",
"repo_count": 1
},
{
"login": "njuiselab",
"repo_count": 1
}
],
"meta": {
"repo_count": 13,
"issue_count": 2,
"pr_count": 0,
"scholar_count": 35,
"discussion_count": 0,
"topic_count": 10
}
}

View File

@ -0,0 +1,50 @@
# 🔬 科研热点追踪报告
> 关键词:深度学习
> 扫描时间2026-07-08
> 覆盖仓库13 个 · 讨论 0 条 · 主题 10 个 · 学者 35 位
## 🔥 飙升项目 Top 5
| # | 仓库 | 语言 | 👁 访问 | ★ Star | ⑂ Fork | 热度 | 更新 |
|---|------|------|---------|--------|--------|------|------|
| 1 | `Edgedev/Edge-Computing-Engine` | C++ | 593 | 3 | 1 | 64 | 2021-07-13 |
| 2 | `CocytusXRS/AI_test` | Jupyter notebook | 550 | 0 | 0 | 55 | 2022-12-02 |
| 3 | `AIEven/AIkun` | Python | 382 | 0 | 0 | 38 | 2025-08-09 |
| 4 | `shenyan/machineLearningTemplate` | Python | 309 | 1 | 0 | 31 | 2021-10-22 |
| 5 | `opensci/pDeep` | Python | 292 | 0 | 0 | 29 | 2021-03-19 |
## 📊 热门主题
- **deep_learning** — 15 个仓库 ███████████████
- **scientific_computing** — 7 个仓库 ███████
- **computer_vision** — 6 个仓库 ██████
- **machine_learning** — 4 个仓库 ████
- **database** — 3 个仓库 ███
- **time_series** — 3 个仓库 ███
- **generative_ai** — 3 个仓库 ███
- **reinforcement_learning** — 2 个仓库 ██
- **nlp** — 2 个仓库 ██
- **autonomous_systems** — 2 个仓库 ██
## 👥 核心学者
- **Edge** — 关联 2 个仓库
- **junru shao** — 关联 2 个仓库
- **Edgedev** — 关联 1 个仓库
- **cloudy1225** — 关联 1 个仓库
- **CocytusXRS** — 关联 1 个仓库
## 🏛 活跃组织/团队
- **Edgedev** — 1 个仓库
- **CocytusXRS** — 1 个仓库
- **AIEven** — 1 个仓库
- **shenyan** — 1 个仓库
- **opensci** — 1 个仓库
- **dongeliu** — 1 个仓库
- **clj111** — 1 个仓库
- **njuiselab** — 1 个仓库
---
*由 gitlink-research-hotspot 自动生成*

View File

@ -0,0 +1,52 @@
{
"scenario": "profile",
"mode": "project",
"profiles": [
{
"type": "project",
"repo": "whale_hihihi/gitlink-cli",
"name": "gitlink-cli",
"description": "",
"topics": [
{
"topic": "reinforcement_learning",
"count": 1
},
{
"topic": "devops",
"count": 1
}
],
"languages": [
"Dockerfile",
"Go",
"HTML",
"JavaScript",
"Mermaid",
"Python",
"Shell"
],
"stars": 0,
"forks": 0,
"visits": 0,
"contributors_count": 20,
"top_contributors": [
"wbtiger",
"whale",
"wauxing",
"Surponess",
"wangyue789",
"tiger",
"muel",
"puygob236"
],
"score": {
"doc": 5,
"license": 0,
"collab": 10,
"impact": 0
},
"score_total": 15
}
]
}

View File

@ -0,0 +1,10 @@
# 🪪 主体画像报告
## 📦 gitlink-cli (`whale_hihihi/gitlink-cli`)
- ★0 ⑂0 👁0 · 贡献者 20 · 研究维度评分 **15/40**
- 主题:`reinforcement_learning`、`devops`
- 核心贡献者:`wbtiger`、`whale`、`wauxing`、`Surponess`、`wangyue789`、`tiger`
---
*由 gitlink-research-profile 生成*

View File

@ -0,0 +1,80 @@
{
"scenario": "S5_progress_tracking",
"repo": "whale_hihihi/gitlink-cli",
"generated_at": "2026-07-08T00:27:31.149904+00:00",
"week_stats": {
"this_week": {
"commits": 44,
"issues_opened": 0,
"issues_closed": 0,
"issues_stale": 0,
"prs_opened": 9,
"prs_merged": 8,
"prs_open_stale": 0,
"contributors_active": 7,
"contributors_active_logins": [
"Surponess",
"baoerjun",
"wauxing",
"wbtiger",
"whale",
"whale_hihihi",
"yangsai01"
]
},
"last_week": {
"commits": 4,
"issues_opened": 0,
"issues_closed": 0,
"issues_stale": 0,
"prs_opened": 2,
"prs_merged": 2,
"prs_open_stale": 0,
"contributors_active": 1,
"contributors_active_logins": [
"Surponess"
]
},
"window": {
"this_week_start": "2026-07-01T00:27:31.149904+00:00",
"now": "2026-07-08T00:27:31.149904+00:00",
"last_week_start": "2026-06-24T00:27:31.149904+00:00",
"last_week_end": "2026-07-01T00:27:31.149904+00:00"
},
"total_contributors": 20
},
"trend": {
"commit_delta_pct": 1000.0,
"activity_level": "increasing",
"this_week_commits": 44,
"last_week_commits": 4
},
"milestones": [
{
"name": "完成批量成员邀请",
"open": 0,
"closed": 0,
"total": 0,
"completion_pct": 0.0,
"due_date": "2026-06-04T00:00:00+00:00",
"overdue": true,
"status": "open"
}
],
"risk_warnings": [
{
"level": "critical",
"type": "overdue_milestone",
"message": "里程碑「完成批量成员邀请」已逾期due 2026-06-04T00:00:00+00:00完成率 0.0%",
"metric": 0.0,
"suggestion": "重新评估范围或顺延 deadline并同步干系人。"
}
],
"meta": {
"commits_fetched": 50,
"issues_fetched": 0,
"prs_fetched": 30,
"milestones_fetched": 1,
"contributors_fetched": 20
}
}

View File

@ -0,0 +1,36 @@
# 科研进度智能跟踪周报 — whale_hihihi/gitlink-cli
> 场景 S5 · 子赛题四「应用 GitLink 辅助科研」· 生成于 2026-07-08T00:27:31.149904+00:00
## 一、本周 / 上周活动对比
| 指标 | 本周 | 上周 |
|------|------|------|
| 提交 commits | 44 | 4 |
| Issue 新增 | 0 | 0 |
| Issue 关闭 | 0 | 0 |
| 开放 stale issue (>30天) | 0 | 0 |
| PR 新增 | 9 | 2 |
| PR 合并 | 8 | 2 |
| 开放 stale PR (>14天) | 0 | 0 |
| 活跃贡献者 | 7 | 1 |
- **趋势**commit 周环比 **1000.0%**,活跃度等级 `increasing`
## 二、里程碑进度
| 里程碑 | 完成/总数 | 完成率 | due_date | 状态 |
|--------|-----------|--------|----------|------|
| 完成批量成员邀请 ⚠️逾期 | 0/0 | 0.0% | 2026-06-04T00:00:00+00:00 | open |
## 三、风险预警
| 级别 | 类型 | 说明 | 建议 |
|------|------|------|------|
| critical | overdue_milestone | 里程碑「完成批量成员邀请」已逾期due 2026-06-04T00:00:00+00:00完成率 0.0% | 重新评估范围或顺延 deadline并同步干系人。 |
## 四、附
- 取数commits=50 issues=0 prs=30 milestones=1 contributors=20
- 窗口:本周 [2026-07-01T00:27:31.149904+00:00, 2026-07-08T00:27:31.149904+00:00];上周 [2026-06-24T00:27:31.149904+00:00, 2026-07-01T00:27:31.149904+00:00)
- 阈值stale_issue>30天 / stale_pr>14天 / 低活跃<3次/ / bus_factor>50%

View File

@ -0,0 +1,48 @@
# 科研项目合规与复现性检查报告 — whale_hihihi/gitlink-cli
> 场景 S3 · 子赛题四「应用 GitLink 辅助科研」
- **默认分支**: `master`
- **识别许可证**: `MulanPSL-2.0`
- **复现性评分**: **9.0/10**(良好)
- **合规性评分**: **7.5/10**(及格)
## 一、复现性检查清单
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| CI 配置 | PASS | 2/2 | 检测到 CI 配置: .devops, .gitea, .github |
| 依赖锁文件 | PASS | 2/2 | 存在 lockfile: go.sum |
| README 复现说明 | PASS | 2/2 | README 含复现关键词 10 个: install, setup, build, 运行, run |
| 版本 tag | FAIL | 1/2 | repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本 |
| 容器化环境 | PASS | 2/2 | 存在容器配置: Dockerfile |
## 二、合规性检查清单
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| LICENSE 文件 | PASS | 2/2 | LICENSE 声明为 MulanPSL-2.0 |
| 安全策略 SECURITY.md | FAIL | 0/2 | 缺少 SECURITY.md无安全披露流程 |
| 版权声明 | PASS | 2/2 | LICENSE/README 中含 copyright/版权 声明 |
| 依赖清单声明 | PASS | 2/2 | 存在依赖管理文件(建议核对各依赖许可证兼容性) |
| 贡献指南 | FAIL | 1/2 | 缺少 CONTRIBUTING.md |
## 三、数据隐私检查
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| 数据目录入库 | PASS | 2/2 | 未发现 data/ 目录入库 |
| .env 入库 | PASS | 2/2 | .env 未入库 |
| .gitignore 忽略 .env | FAIL | 1/2 | .gitignore 未忽略 .env建议添加 .env |
## 四、风险项(按严重程度排序)
| 级别 | 类别 | 名称 | 文件:行 | 证据 |
|:----:|------|------|---------|------|
| high | privacy | 数据隐私 | | .gitignore 未忽略 .env预防性建议 |
| medium | repro/compliance | 版本 tag | | repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本 |
| medium | repro/compliance | 安全策略 SECURITY.md | | 缺少 SECURITY.md无安全披露流程 |
| medium | repro/compliance | 贡献指南 | | 缺少 CONTRIBUTING.md |
| medium | repro/compliance | .gitignore 忽略 .env | | .gitignore 未忽略 .env建议添加 .env |
_复现分 9.0/10 · 合规分 7.5/10 · 树节点 31_

View File

@ -0,0 +1,143 @@
{
"scenario": "S3_compliance_reproducibility",
"repo": "whale_hihihi/gitlink-cli",
"default_branch": "master",
"license": "MulanPSL-2.0",
"repro_items": [
{
"name": "CI 配置",
"pass": true,
"score": 2,
"evidence": "检测到 CI 配置: .devops, .gitea, .github"
},
{
"name": "依赖锁文件",
"pass": true,
"score": 2,
"evidence": "存在 lockfile: go.sum"
},
{
"name": "README 复现说明",
"pass": true,
"score": 2,
"evidence": "README 含复现关键词 10 个: install, setup, build, 运行, run"
},
{
"name": "版本 tag",
"pass": false,
"score": 1,
"evidence": "repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本"
},
{
"name": "容器化环境",
"pass": true,
"score": 2,
"evidence": "存在容器配置: Dockerfile"
}
],
"compliance_items": [
{
"name": "LICENSE 文件",
"pass": true,
"score": 2,
"evidence": "LICENSE 声明为 MulanPSL-2.0"
},
{
"name": "安全策略 SECURITY.md",
"pass": false,
"score": 0,
"evidence": "缺少 SECURITY.md无安全披露流程"
},
{
"name": "版权声明",
"pass": true,
"score": 2,
"evidence": "LICENSE/README 中含 copyright/版权 声明"
},
{
"name": "依赖清单声明",
"pass": true,
"score": 2,
"evidence": "存在依赖管理文件(建议核对各依赖许可证兼容性)"
},
{
"name": "贡献指南",
"pass": false,
"score": 1,
"evidence": "缺少 CONTRIBUTING.md"
}
],
"privacy_items": [
{
"name": "数据目录入库",
"pass": true,
"score": 2,
"evidence": "未发现 data/ 目录入库"
},
{
"name": ".env 入库",
"pass": true,
"score": 2,
"evidence": ".env 未入库"
},
{
"name": ".gitignore 忽略 .env",
"pass": false,
"score": 1,
"evidence": ".gitignore 未忽略 .env建议添加 .env"
}
],
"secrets": [],
"risks": [
{
"area": "privacy",
"name": "数据隐私",
"evidence": ".gitignore 未忽略 .env预防性建议",
"level": "high"
},
{
"area": "repro/compliance",
"name": "版本 tag",
"evidence": "repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "安全策略 SECURITY.md",
"evidence": "缺少 SECURITY.md无安全披露流程",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "贡献指南",
"evidence": "缺少 CONTRIBUTING.md",
"level": "medium"
},
{
"area": "repro/compliance",
"name": ".gitignore 忽略 .env",
"evidence": ".gitignore 未忽略 .env建议添加 .env",
"level": "medium"
}
],
"repro_score": 9.0,
"compliance_score": 7.5,
"meta": {
"key_files_found": [
".gitignore",
"LICENSE",
"README.md",
"go.mod"
],
"tree_size": 31,
"languages": {
"Dockerfile": "0.1%",
"Go": "60.5%",
"HTML": "8.2%",
"JavaScript": "1.9%",
"Mermaid": "3.7%",
"Python": "22.4%",
"Shell": "3.2%"
}
}
}

View File

@ -0,0 +1,51 @@
# 科研成果可视化沉淀报告 — whale_hihihi/gitlink-cli
> 场景 S6 · 子赛题四「应用 GitLink 辅助科研」
## 一、活跃度概览(最近 26 周)
- 提交数: **27**(窗口内峰值 15 提交/周)
- 新增 Issue: **0**,新增 PR: **30**
- 贡献者: **20**,里程碑: **1**
## 二、开发节奏(最近 8 周快照)
| 周 | commits | issues | prs |
|----|---------|--------|-----|
| 2026-W21 | 0 | 0 | 0 |
| 2026-W22 | 0 | 0 | 6 |
| 2026-W23 | 0 | 0 | 9 |
| 2026-W24 | 0 | 0 | 1 |
| 2026-W25 | 0 | 0 | 2 |
| 2026-W26 | 0 | 0 | 2 |
| 2026-W27 | 0 | 0 | 2 |
| 2026-W28 | 0 | 0 | 8 |
## 三、核心贡献者热力(贡献者 × 周提交数)
| 贡献者 | 窗口内提交 |
|--------|-----------|
| `wbtiger` | 17 |
| `whale` | 0 |
| `wauxing` | 0 |
| `Surponess` | 0 |
| `wangyue789` | 1 |
| `tiger` | 0 |
| `muel` | 0 |
| `puygob236` | 0 |
| `wbavon` | 8 |
| `Mengz` | 0 |
## 四、科研产物分类
- 论文/笔记 (paper): **0**
- 数据集 (dataset): **0**
- 模型 (model): **0**
- 基准 (benchmark): **0**
## 五、抽取到的论文引用
_未在 README/提交信息中发现 arXiv 或 DOI 引用_
_交互可视化见 visual.html或原始数据 visual.json_

View File

@ -0,0 +1,532 @@
{
"scenario": "S6_research_visualization",
"repo": "whale_hihihi/gitlink-cli",
"weeks": 26,
"timeline": {
"labels": [
"2026-W03",
"2026-W04",
"2026-W05",
"2026-W06",
"2026-W07",
"2026-W08",
"2026-W09",
"2026-W10",
"2026-W11",
"2026-W12",
"2026-W13",
"2026-W14",
"2026-W15",
"2026-W16",
"2026-W17",
"2026-W18",
"2026-W19",
"2026-W20",
"2026-W21",
"2026-W22",
"2026-W23",
"2026-W24",
"2026-W25",
"2026-W26",
"2026-W27",
"2026-W28"
],
"commits": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
15,
0,
1,
0,
11,
0,
0,
0,
0,
0,
0,
0,
0
],
"issues": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"prs": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
6,
9,
1,
2,
2,
2,
8
]
},
"heatmap": {
"users": [
"wbtiger",
"whale",
"wauxing",
"Surponess",
"wangyue789",
"tiger",
"muel",
"puygob236",
"wbavon",
"Mengz",
"baoerjun",
"yangsai01"
],
"weeks": [
"2026-W03",
"2026-W04",
"2026-W05",
"2026-W06",
"2026-W07",
"2026-W08",
"2026-W09",
"2026-W10",
"2026-W11",
"2026-W12",
"2026-W13",
"2026-W14",
"2026-W15",
"2026-W16",
"2026-W17",
"2026-W18",
"2026-W19",
"2026-W20",
"2026-W21",
"2026-W22",
"2026-W23",
"2026-W24",
"2026-W25",
"2026-W26",
"2026-W27",
"2026-W28"
],
"matrix": [
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
7,
0,
0,
0,
10,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
]
]
},
"languages": {
"Dockerfile": "0.1%",
"Go": "60.5%",
"HTML": "8.2%",
"JavaScript": "1.9%",
"Mermaid": "3.7%",
"Python": "22.4%",
"Shell": "3.2%"
},
"milestones": [
{
"title": "完成批量成员邀请",
"start": 1779321600.0,
"due": 1780531200.0
}
],
"paper_links": [],
"artifacts": [],
"artifact_summary": {
"paper": 0,
"dataset": 0,
"model": 0,
"benchmark": 0
},
"meta": {
"commit_count": 27,
"issue_count": 0,
"pr_count": 30,
"milestone_count": 1,
"contributor_count": 20
}
}

View File

@ -0,0 +1,181 @@
{
"scenario": "inspire",
"mode": "repo",
"repo": "whale_hihihi/gitlink-cli",
"gap_topics": [
"reinforcement_learning",
"devops"
],
"needed_languages": [
"Dockerfile",
"Go",
"HTML",
"JavaScript",
"Mermaid",
"Python",
"Shell",
"go"
],
"gap_signals": [],
"candidates": [
{
"login": "wbtiger",
"score": 47.9,
"topic_overlap": 0.707,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 15,
"reasons": [
"覆盖缺口主题: devops",
"本仓库活跃贡献者"
]
},
{
"login": "Mengz",
"score": 30.9,
"topic_overlap": 0.0,
"language_match": 0.091,
"activity_level": "high",
"repo_languages": [
"c++",
"go",
"markdown",
"python"
],
"repo_count": 15,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=5)"
]
},
{
"login": "muel",
"score": 28.4,
"topic_overlap": 0.0,
"language_match": 0.111,
"activity_level": "high",
"repo_languages": [
"go",
"typescript"
],
"repo_count": 5,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=4)"
]
},
{
"login": "puygob236",
"score": 22.4,
"topic_overlap": 0.0,
"language_match": 0.111,
"activity_level": "high",
"repo_languages": [
"go",
"typescript"
],
"repo_count": 3,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=2)"
]
},
{
"login": "baoerjun",
"score": 22.3,
"topic_overlap": 0.0,
"language_match": 0.111,
"activity_level": "high",
"repo_languages": [
"go",
"javascript"
],
"repo_count": 4,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=2)"
]
},
{
"login": "Surponess",
"score": 19.6,
"topic_overlap": 0.0,
"language_match": 0.1,
"activity_level": "high",
"repo_languages": [
"go",
"javascript",
"markdown"
],
"repo_count": 3,
"reasons": [
"语言匹配: go",
"本仓库活跃贡献者",
"协作开放度高(fork=1)"
]
},
{
"login": "whale",
"score": 14.8,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
},
{
"login": "wauxing",
"score": 14.7,
"topic_overlap": 0.0,
"language_match": 0.0,
"activity_level": "high",
"repo_languages": [],
"repo_count": 0,
"reasons": [
"本仓库活跃贡献者"
]
}
],
"innovation_points": [
{
"description": "feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化",
"evidence": "PR #18 「feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化」 改动 151 文件,合并于 2026-06-15",
"category": "大规模重构/新特性"
},
{
"description": "修改知识图谱构建方法",
"evidence": "PR #31 「修改知识图谱构建方法」 改动 111 文件,合并于 2026-07-07",
"category": "大规模重构/新特性"
},
{
"description": "feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理",
"evidence": "PR #14 「feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理」 改动 31 文件,合并于 2026-06-03",
"category": "大规模重构/新特性"
},
{
"description": "新增skills",
"evidence": "PR #16 「新增skills」 改动 26 文件,合并于 2026-06-12",
"category": "大规模重构/新特性"
},
{
"description": "新增demo",
"evidence": "PR #24 「新增demo」 改动 19 文件,合并于 2026-07-06",
"category": "大规模重构/新特性"
},
{
"description": "feat: 实现 batch issue 批量操作命令",
"evidence": "PR #12 「feat: 实现 batch issue 批量操作命令」 改动 14 文件,合并于 2026-06-01",
"category": "大规模重构/新特性"
}
],
"idea": null,
"llm_used": false
}

View File

@ -0,0 +1,26 @@
# 💡 创新启发报告
> 焦点仓库:`whale_hihihi/gitlink-cli`
> LLM 建议:⏭ 未启用(无 DEEPSEEK_API_KEY
## 🎯 缺口主题
`reinforcement_learning`, `devops`
## 🤝 可合作学者 Top 5
| 学者 | 契合度 | 主题重叠 | 语言匹配 | 活跃 | 理由 |
|---|---|---|---|---|---|
| `wbtiger` | 47.9 | 0.707 | 0.0 | high | 覆盖缺口主题: devops;本仓库活跃贡献者 |
| `Mengz` | 30.9 | 0.0 | 0.091 | high | 语言匹配: go;本仓库活跃贡献者 |
| `muel` | 28.4 | 0.0 | 0.111 | high | 语言匹配: go;本仓库活跃贡献者 |
| `puygob236` | 22.4 | 0.0 | 0.111 | high | 语言匹配: go;本仓库活跃贡献者 |
| `baoerjun` | 22.3 | 0.0 | 0.111 | high | 语言匹配: go;本仓库活跃贡献者 |
## 🌟 近期创新点
- feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化 _(大规模重构/新特性)_
- 修改知识图谱构建方法 _(大规模重构/新特性)_
- feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理 _(大规模重构/新特性)_
- 新增skills _(大规模重构/新特性)_
- 新增demo _(大规模重构/新特性)_
---
*由 gitlink-research-inspire 生成*

View File

@ -0,0 +1,34 @@
```mermaid
gitGraph
commit id: "main 起点"
commit
commit
commit
commit id: "#5" tag: "2026-05-29"
commit
commit
commit
commit id: "#12 创新点" tag: "2026-06-01"
commit
commit
commit
commit id: "#14 创新点" tag: "2026-06-03"
commit
commit
commit
commit id: "#18 创新点" tag: "2026-06-15"
commit
commit
commit
commit id: "#21" tag: "2026-06-29"
commit
commit
commit
commit id: "#31 创新点" tag: "2026-07-07"
commit
commit
commit
commit id: "#28" tag: "2026-07-07"
commit
commit
```

View File

@ -0,0 +1,271 @@
{
"scenario": "S1_repository_research_insight",
"repo": "whale_hihihi/gitlink-cli",
"default_branch": "main",
"commit_timeline": [
{
"date": "2026-04-17",
"count": 10
},
{
"date": "2026-04-18",
"count": 5
},
{
"date": "2026-04-28",
"count": 1
},
{
"date": "2026-05-11",
"count": 1
},
{
"date": "2026-05-12",
"count": 6
},
{
"date": "2026-05-13",
"count": 1
},
{
"date": "2026-05-14",
"count": 2
},
{
"date": "2026-05-17",
"count": 1
}
],
"branch_map": [
{
"name": "main",
"commits": 27,
"last_active": "2026-05-17",
"is_default": true
}
],
"pr_merge_patterns": [
{
"number": 2,
"title": "本次实现search +issues — 搜索 Issue 功能",
"status": "merged",
"merged_time": "2026-05-25",
"changed_files": 4
},
{
"number": 3,
"title": "创建 webhook 领域 + 实现 `+update`",
"status": "merged",
"merged_time": "2026-05-28",
"changed_files": 2
},
{
"number": 5,
"title": "release download 功能(新增) 在 release.go 的 Shortcuts() 中新增第 5 个快捷命令 download 参数:-",
"status": "merged",
"merged_time": "2026-05-29",
"changed_files": 7
},
{
"number": 4,
"title": "label 领域原来只有 3 个命令list/create/delete现在新增了 update 命令。",
"status": "merged",
"merged_time": "2026-05-29",
"changed_files": 3
},
{
"number": 6,
"title": "release download 命令 新增 download 快捷命令、错误消息统一化",
"status": "merged",
"merged_time": "2026-05-30",
"changed_files": 8
},
{
"number": 12,
"title": "feat: 实现 batch issue 批量操作命令",
"status": "merged",
"merged_time": "2026-06-01",
"changed_files": 14
},
{
"number": 8,
"title": "文件描述符泄漏等修改",
"status": "merged",
"merged_time": "2026-06-01",
"changed_files": 5
},
{
"number": 7,
"title": "代码片段管理功能",
"status": "merged",
"merged_time": "2026-06-01",
"changed_files": 5
},
{
"number": 14,
"title": "feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理",
"status": "merged",
"merged_time": "2026-06-03",
"changed_files": 31
},
{
"number": 15,
"title": "修改编译",
"status": "merged",
"merged_time": "2026-06-04",
"changed_files": 9
},
{
"number": 16,
"title": "新增skills",
"status": "merged",
"merged_time": "2026-06-12",
"changed_files": 26
},
{
"number": 18,
"title": "feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化",
"status": "merged",
"merged_time": "2026-06-15",
"changed_files": 151
},
{
"number": 19,
"title": "新增skills",
"status": "merged",
"merged_time": "2026-06-23",
"changed_files": 7
},
{
"number": 20,
"title": "注册重编激活 25 域、新增 6 个 Skill、补全索引与示例、产出任务三/四的端到端工作流",
"status": "merged",
"merged_time": "2026-06-24",
"changed_files": 5
},
{
"number": 21,
"title": "验证部分内容,作出相关修改",
"status": "merged",
"merged_time": "2026-06-29",
"changed_files": 1
},
{
"number": 22,
"title": "修改了两个skills的命令使用",
"status": "merged",
"merged_time": "2026-07-02",
"changed_files": 2
},
{
"number": 24,
"title": "新增demo",
"status": "merged",
"merged_time": "2026-07-06",
"changed_files": 19
},
{
"number": 31,
"title": "修改知识图谱构建方法",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 111
},
{
"number": 30,
"title": "fix(sweep): wiki 发布链路修复 + 端到端验证",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 7
},
{
"number": 29,
"title": "feat: 统一全链路科研分析页面 + Dockerfile 修复",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 13
},
{
"number": 28,
"title": "feat(demo): 调整 demo 前端展示(合并 surponess_br 第二批)",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 2
},
{
"number": 27,
"title": "feat(demo): 优化 demo 前端展示(合并 surponess_br",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 3
},
{
"number": 26,
"title": "chore: move community-ops-sweep workflow to project root workflows/",
"status": "merged",
"merged_time": "2026-07-07",
"changed_files": 8
}
],
"doc_evolution": [
{
"file": "README.md",
"last_date": ""
},
{
"file": "README.zh-CN.md",
"last_date": ""
}
],
"experiment_files": [
"pr-test-file.txt"
],
"innovation_points": [
{
"description": "feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化",
"evidence": "PR #18 「feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化」 改动 151 文件,合并于 2026-06-15",
"category": "大规模重构/新特性"
},
{
"description": "修改知识图谱构建方法",
"evidence": "PR #31 「修改知识图谱构建方法」 改动 111 文件,合并于 2026-07-07",
"category": "大规模重构/新特性"
},
{
"description": "feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理",
"evidence": "PR #14 「feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理」 改动 31 文件,合并于 2026-06-03",
"category": "大规模重构/新特性"
},
{
"description": "新增skills",
"evidence": "PR #16 「新增skills」 改动 26 文件,合并于 2026-06-12",
"category": "大规模重构/新特性"
},
{
"description": "新增demo",
"evidence": "PR #24 「新增demo」 改动 19 文件,合并于 2026-07-06",
"category": "大规模重构/新特性"
},
{
"description": "feat: 实现 batch issue 批量操作命令",
"evidence": "PR #12 「feat: 实现 batch issue 批量操作命令」 改动 14 文件,合并于 2026-06-01",
"category": "大规模重构/新特性"
},
{
"description": "feat: 统一全链路科研分析页面 + Dockerfile 修复",
"evidence": "PR #29 「feat: 统一全链路科研分析页面 + Dockerfile 修复」 改动 13 文件,合并于 2026-07-07",
"category": "大规模重构/新特性"
},
{
"description": "release download 命令 新增 download 快捷命令、错误消息统一化",
"evidence": "PR #6 「release download 命令 新增 download 快捷命令、错误消息统一化」 改动 8 文件,合并于 2026-05-30",
"category": "特性引入"
}
],
"meta": {
"commit_count": 27,
"merged_pr_count": 23,
"doc_count": 2,
"experiment_file_count": 1
}
}

View File

@ -0,0 +1,67 @@
# 仓库级科研项目洞悉报告 — whale_hihihi/gitlink-cli
> 场景 S1 · 子赛题四「应用 GitLink 辅助科研」· 项目谱系lineage分析
## 一、基础信息
- **默认分支**: `main`
- **采样提交**: 27 条(默认分支,最多 10×100
- **已合并 PR**: 23 个
- **文档文件**: 2 个
- **实验/评测文件**: 1 个
## 二、提交活跃度时间线
- 时间跨度: 2026-04-17 → 2026-05-17共 8 个有提交的日期)
- 峰值: 2026-04-17 当日 10 次提交
## 三、分支地图
| 分支 | 提交数 | 最后活跃 | 是否默认 |
|------|:------:|----------|:--------:|
| `main` | 27 | 2026-05-17 | 是 |
## 四、合并 PR 演进模式(高影响合并预览)
| PR | 标题 | 改动文件 | 合并时间 |
|----|------|:--------:|----------|
| #2 | 本次实现search +issues — 搜索 Issue 功能 | 4 | 2026-05-25 |
| #3 | 创建 webhook 领域 + 实现 `+update` | 2 | 2026-05-28 |
| #5 | release download 功能(新增) 在 release.go 的 Shortcuts() 中新增第 5 个快捷命令 download 参数:- | 7 | 2026-05-29 |
| #4 | label 领域原来只有 3 个命令list/create/delete现在新增了 update 命令。 | 3 | 2026-05-29 |
| #6 | release download 命令 新增 download 快捷命令、错误消息统一化 | 8 | 2026-05-30 |
| #12 | feat: 实现 batch issue 批量操作命令 | 14 | 2026-06-01 |
| #8 | 文件描述符泄漏等修改 | 5 | 2026-06-01 |
| #7 | 代码片段管理功能 | 5 | 2026-06-01 |
| #14 | feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理 | 31 | 2026-06-03 |
| #15 | 修改编译 | 9 | 2026-06-04 |
## 五、创新/里程碑点
1. **[大规模重构/新特性]** feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化
- 证据: PR #18 「feat: 合并 upstream/master 并对齐风格 — 行为修复 + i18n 化」 改动 151 文件,合并于 2026-06-15
2. **[大规模重构/新特性]** 修改知识图谱构建方法
- 证据: PR #31 「修改知识图谱构建方法」 改动 111 文件,合并于 2026-07-07
3. **[大规模重构/新特性]** feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理
- 证据: PR #14 「feat: 补全 21 个 Shortcut + 修正批量操作 + 文档/代码全面清理」 改动 31 文件,合并于 2026-06-03
4. **[大规模重构/新特性]** 新增skills
- 证据: PR #16 「新增skills」 改动 26 文件,合并于 2026-06-12
5. **[大规模重构/新特性]** 新增demo
- 证据: PR #24 「新增demo」 改动 19 文件,合并于 2026-07-06
6. **[大规模重构/新特性]** feat: 实现 batch issue 批量操作命令
- 证据: PR #12 「feat: 实现 batch issue 批量操作命令」 改动 14 文件,合并于 2026-06-01
7. **[大规模重构/新特性]** feat: 统一全链路科研分析页面 + Dockerfile 修复
- 证据: PR #29 「feat: 统一全链路科研分析页面 + Dockerfile 修复」 改动 13 文件,合并于 2026-07-07
8. **[特性引入]** release download 命令 新增 download 快捷命令、错误消息统一化
- 证据: PR #6 「release download 命令 新增 download 快捷命令、错误消息统一化」 改动 8 文件,合并于 2026-05-30
## 六、文档演进docs/*
| 文档 | 近似最后日期 |
|------|--------------|
| README.md | — |
| README.zh-CN.md | — |
## 七、实验/评测文件组织
- `pr-test-file.txt`

View File

@ -0,0 +1,52 @@
{
"scenario": "profile",
"mode": "project",
"profiles": [
{
"type": "project",
"repo": "whale_hihihi/gitlink-cli",
"name": "gitlink-cli",
"description": "",
"topics": [
{
"topic": "reinforcement_learning",
"count": 1
},
{
"topic": "devops",
"count": 1
}
],
"languages": [
"Dockerfile",
"Go",
"HTML",
"JavaScript",
"Mermaid",
"Python",
"Shell"
],
"stars": 0,
"forks": 0,
"visits": 0,
"contributors_count": 20,
"top_contributors": [
"wbtiger",
"whale",
"wauxing",
"Surponess",
"wangyue789",
"tiger",
"muel",
"puygob236"
],
"score": {
"doc": 5,
"license": 0,
"collab": 10,
"impact": 0
},
"score_total": 15
}
]
}

View File

@ -0,0 +1,10 @@
# 🪪 主体画像报告
## 📦 gitlink-cli (`whale_hihihi/gitlink-cli`)
- ★0 ⑂0 👁0 · 贡献者 20 · 研究维度评分 **15/40**
- 主题:`reinforcement_learning`、`devops`
- 核心贡献者:`wbtiger`、`whale`、`wauxing`、`Surponess`、`wangyue789`、`tiger`
---
*由 gitlink-research-profile 生成*

View File

@ -0,0 +1,80 @@
{
"scenario": "S5_progress_tracking",
"repo": "whale_hihihi/gitlink-cli",
"generated_at": "2026-07-08T00:35:06.265226+00:00",
"week_stats": {
"this_week": {
"commits": 44,
"issues_opened": 0,
"issues_closed": 0,
"issues_stale": 0,
"prs_opened": 9,
"prs_merged": 8,
"prs_open_stale": 0,
"contributors_active": 7,
"contributors_active_logins": [
"Surponess",
"baoerjun",
"wauxing",
"wbtiger",
"whale",
"whale_hihihi",
"yangsai01"
]
},
"last_week": {
"commits": 4,
"issues_opened": 0,
"issues_closed": 0,
"issues_stale": 0,
"prs_opened": 2,
"prs_merged": 2,
"prs_open_stale": 0,
"contributors_active": 1,
"contributors_active_logins": [
"Surponess"
]
},
"window": {
"this_week_start": "2026-07-01T00:35:06.265226+00:00",
"now": "2026-07-08T00:35:06.265226+00:00",
"last_week_start": "2026-06-24T00:35:06.265226+00:00",
"last_week_end": "2026-07-01T00:35:06.265226+00:00"
},
"total_contributors": 20
},
"trend": {
"commit_delta_pct": 1000.0,
"activity_level": "increasing",
"this_week_commits": 44,
"last_week_commits": 4
},
"milestones": [
{
"name": "完成批量成员邀请",
"open": 0,
"closed": 0,
"total": 0,
"completion_pct": 0.0,
"due_date": "2026-06-04T00:00:00+00:00",
"overdue": true,
"status": "open"
}
],
"risk_warnings": [
{
"level": "critical",
"type": "overdue_milestone",
"message": "里程碑「完成批量成员邀请」已逾期due 2026-06-04T00:00:00+00:00完成率 0.0%",
"metric": 0.0,
"suggestion": "重新评估范围或顺延 deadline并同步干系人。"
}
],
"meta": {
"commits_fetched": 50,
"issues_fetched": 0,
"prs_fetched": 30,
"milestones_fetched": 1,
"contributors_fetched": 20
}
}

View File

@ -0,0 +1,36 @@
# 科研进度智能跟踪周报 — whale_hihihi/gitlink-cli
> 场景 S5 · 子赛题四「应用 GitLink 辅助科研」· 生成于 2026-07-08T00:35:06.265226+00:00
## 一、本周 / 上周活动对比
| 指标 | 本周 | 上周 |
|------|------|------|
| 提交 commits | 44 | 4 |
| Issue 新增 | 0 | 0 |
| Issue 关闭 | 0 | 0 |
| 开放 stale issue (>30天) | 0 | 0 |
| PR 新增 | 9 | 2 |
| PR 合并 | 8 | 2 |
| 开放 stale PR (>14天) | 0 | 0 |
| 活跃贡献者 | 7 | 1 |
- **趋势**commit 周环比 **1000.0%**,活跃度等级 `increasing`
## 二、里程碑进度
| 里程碑 | 完成/总数 | 完成率 | due_date | 状态 |
|--------|-----------|--------|----------|------|
| 完成批量成员邀请 ⚠️逾期 | 0/0 | 0.0% | 2026-06-04T00:00:00+00:00 | open |
## 三、风险预警
| 级别 | 类型 | 说明 | 建议 |
|------|------|------|------|
| critical | overdue_milestone | 里程碑「完成批量成员邀请」已逾期due 2026-06-04T00:00:00+00:00完成率 0.0% | 重新评估范围或顺延 deadline并同步干系人。 |
## 四、附
- 取数commits=50 issues=0 prs=30 milestones=1 contributors=20
- 窗口:本周 [2026-07-01T00:35:06.265226+00:00, 2026-07-08T00:35:06.265226+00:00];上周 [2026-06-24T00:35:06.265226+00:00, 2026-07-01T00:35:06.265226+00:00)
- 阈值stale_issue>30天 / stale_pr>14天 / 低活跃<3次/ / bus_factor>50%

View File

@ -0,0 +1,48 @@
# 科研项目合规与复现性检查报告 — whale_hihihi/gitlink-cli
> 场景 S3 · 子赛题四「应用 GitLink 辅助科研」
- **默认分支**: `master`
- **识别许可证**: `MulanPSL-2.0`
- **复现性评分**: **9.0/10**(良好)
- **合规性评分**: **7.5/10**(及格)
## 一、复现性检查清单
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| CI 配置 | PASS | 2/2 | 检测到 CI 配置: .devops, .gitea, .github |
| 依赖锁文件 | PASS | 2/2 | 存在 lockfile: go.sum |
| README 复现说明 | PASS | 2/2 | README 含复现关键词 10 个: install, setup, build, 运行, run |
| 版本 tag | FAIL | 1/2 | repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本 |
| 容器化环境 | PASS | 2/2 | 存在容器配置: Dockerfile |
## 二、合规性检查清单
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| LICENSE 文件 | PASS | 2/2 | LICENSE 声明为 MulanPSL-2.0 |
| 安全策略 SECURITY.md | FAIL | 0/2 | 缺少 SECURITY.md无安全披露流程 |
| 版权声明 | PASS | 2/2 | LICENSE/README 中含 copyright/版权 声明 |
| 依赖清单声明 | PASS | 2/2 | 存在依赖管理文件(建议核对各依赖许可证兼容性) |
| 贡献指南 | FAIL | 1/2 | 缺少 CONTRIBUTING.md |
## 三、数据隐私检查
| 检查项 | 通过 | 得分 | 证据 |
|--------|:----:|:----:|------|
| 数据目录入库 | PASS | 2/2 | 未发现 data/ 目录入库 |
| .env 入库 | PASS | 2/2 | .env 未入库 |
| .gitignore 忽略 .env | FAIL | 1/2 | .gitignore 未忽略 .env建议添加 .env |
## 四、风险项(按严重程度排序)
| 级别 | 类别 | 名称 | 文件:行 | 证据 |
|:----:|------|------|---------|------|
| high | privacy | 数据隐私 | | .gitignore 未忽略 .env预防性建议 |
| medium | repro/compliance | 版本 tag | | repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本 |
| medium | repro/compliance | 安全策略 SECURITY.md | | 缺少 SECURITY.md无安全披露流程 |
| medium | repro/compliance | 贡献指南 | | 缺少 CONTRIBUTING.md |
| medium | repro/compliance | .gitignore 忽略 .env | | .gitignore 未忽略 .env建议添加 .env |
_复现分 9.0/10 · 合规分 7.5/10 · 树节点 31_

View File

@ -0,0 +1,143 @@
{
"scenario": "S3_compliance_reproducibility",
"repo": "whale_hihihi/gitlink-cli",
"default_branch": "master",
"license": "MulanPSL-2.0",
"repro_items": [
{
"name": "CI 配置",
"pass": true,
"score": 2,
"evidence": "检测到 CI 配置: .devops, .gitea, .github"
},
{
"name": "依赖锁文件",
"pass": true,
"score": 2,
"evidence": "存在 lockfile: go.sum"
},
{
"name": "README 复现说明",
"pass": true,
"score": 2,
"evidence": "README 含复现关键词 10 个: install, setup, build, 运行, run"
},
{
"name": "版本 tag",
"pass": false,
"score": 1,
"evidence": "repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本"
},
{
"name": "容器化环境",
"pass": true,
"score": 2,
"evidence": "存在容器配置: Dockerfile"
}
],
"compliance_items": [
{
"name": "LICENSE 文件",
"pass": true,
"score": 2,
"evidence": "LICENSE 声明为 MulanPSL-2.0"
},
{
"name": "安全策略 SECURITY.md",
"pass": false,
"score": 0,
"evidence": "缺少 SECURITY.md无安全披露流程"
},
{
"name": "版权声明",
"pass": true,
"score": 2,
"evidence": "LICENSE/README 中含 copyright/版权 声明"
},
{
"name": "依赖清单声明",
"pass": true,
"score": 2,
"evidence": "存在依赖管理文件(建议核对各依赖许可证兼容性)"
},
{
"name": "贡献指南",
"pass": false,
"score": 1,
"evidence": "缺少 CONTRIBUTING.md"
}
],
"privacy_items": [
{
"name": "数据目录入库",
"pass": true,
"score": 2,
"evidence": "未发现 data/ 目录入库"
},
{
"name": ".env 入库",
"pass": true,
"score": 2,
"evidence": ".env 未入库"
},
{
"name": ".gitignore 忽略 .env",
"pass": false,
"score": 1,
"evidence": ".gitignore 未忽略 .env建议添加 .env"
}
],
"secrets": [],
"risks": [
{
"area": "privacy",
"name": "数据隐私",
"evidence": ".gitignore 未忽略 .env预防性建议",
"level": "high"
},
{
"area": "repro/compliance",
"name": "版本 tag",
"evidence": "repo_info 无显式 tag 字段(默认分支: master建议打 tag 固定可复现版本",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "安全策略 SECURITY.md",
"evidence": "缺少 SECURITY.md无安全披露流程",
"level": "medium"
},
{
"area": "repro/compliance",
"name": "贡献指南",
"evidence": "缺少 CONTRIBUTING.md",
"level": "medium"
},
{
"area": "repro/compliance",
"name": ".gitignore 忽略 .env",
"evidence": ".gitignore 未忽略 .env建议添加 .env",
"level": "medium"
}
],
"repro_score": 9.0,
"compliance_score": 7.5,
"meta": {
"key_files_found": [
".gitignore",
"LICENSE",
"README.md",
"go.mod"
],
"tree_size": 31,
"languages": {
"Dockerfile": "0.1%",
"Go": "60.5%",
"HTML": "8.2%",
"JavaScript": "1.9%",
"Mermaid": "3.7%",
"Python": "22.4%",
"Shell": "3.2%"
}
}
}

View File

@ -0,0 +1,51 @@
# 科研成果可视化沉淀报告 — whale_hihihi/gitlink-cli
> 场景 S6 · 子赛题四「应用 GitLink 辅助科研」
## 一、活跃度概览(最近 26 周)
- 提交数: **27**(窗口内峰值 15 提交/周)
- 新增 Issue: **0**,新增 PR: **30**
- 贡献者: **20**,里程碑: **1**
## 二、开发节奏(最近 8 周快照)
| 周 | commits | issues | prs |
|----|---------|--------|-----|
| 2026-W21 | 0 | 0 | 0 |
| 2026-W22 | 0 | 0 | 6 |
| 2026-W23 | 0 | 0 | 9 |
| 2026-W24 | 0 | 0 | 1 |
| 2026-W25 | 0 | 0 | 2 |
| 2026-W26 | 0 | 0 | 2 |
| 2026-W27 | 0 | 0 | 2 |
| 2026-W28 | 0 | 0 | 8 |
## 三、核心贡献者热力(贡献者 × 周提交数)
| 贡献者 | 窗口内提交 |
|--------|-----------|
| `wbtiger` | 17 |
| `whale` | 0 |
| `wauxing` | 0 |
| `Surponess` | 0 |
| `wangyue789` | 1 |
| `tiger` | 0 |
| `muel` | 0 |
| `puygob236` | 0 |
| `wbavon` | 8 |
| `Mengz` | 0 |
## 四、科研产物分类
- 论文/笔记 (paper): **0**
- 数据集 (dataset): **0**
- 模型 (model): **0**
- 基准 (benchmark): **0**
## 五、抽取到的论文引用
_未在 README/提交信息中发现 arXiv 或 DOI 引用_
_交互可视化见 visual.html或原始数据 visual.json_

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