Update workflows and demo files on zzx_branch

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
狗gogo 2026-07-07 22:57:15 +08:00
parent de9bca30bb
commit 609a62c146
14 changed files with 1015 additions and 424 deletions

View File

@ -119,6 +119,18 @@
.sidebar-section .skills-header {
background: #fdf8ff;
}
.sidebar-section .mission3-header {
background: #eef5fc;
}
.sidebar-section .mission3-header:hover {
background: #dfeaf6;
}
.sidebar-section .mission4-header {
background: #eef7f0;
}
.sidebar-section .mission4-header:hover {
background: #dceee2;
}
/* ── Section collapse (top-level toggle) ── */
.sidebar-section .sidebar-header {
cursor: pointer;
@ -395,8 +407,8 @@
<div class="sidebar-header" onclick="toggleSection('cli-section')">
<span class="section-arrow"></span> 📋 CLI 命令 · 预设指令
<div class="mode-toggle" onclick="event.stopPropagation()">
<button id="cli-mode-direct" class="active" onclick="setCliExecMode('direct')">⚡ 直接运行</button>
<button id="cli-mode-input" onclick="setCliExecMode('input')">✎ 编辑模式</button>
<button id="cli-mode-direct" class="active" onclick="setSectionExecMode('cli','direct')">⚡ 直接运行</button>
<button id="cli-mode-input" onclick="setSectionExecMode('cli','input')">✎ 编辑模式</button>
</div>
</div>
<div class="modules" id="cli-modules-container">
@ -410,13 +422,13 @@
<span class="section-arrow"></span> 🤖 AGENT SKILLS
<span id="session-badge" style="display:none;font-size:10px;background:var(--purple);color:#fff;padding:1px 6px;border-radius:8px;margin-left:6px;" title="会话进行中">● 会话中</span>
<div class="agent-selector" onclick="event.stopPropagation()">
<button id="agent-claude" class="agent-claude active" onclick="setAgent('claude')">🤖 Claude Code</button>
<button id="agent-codex" class="agent-codex" onclick="setAgent('codex')">📟 Codex</button>
<button id="agent-zcode" class="agent-zcode" onclick="setAgent('zcode')">⚡ ZCode</button>
<button class="agent-btn agent-claude active" data-agent="claude" onclick="setAgent('claude')">🤖 Claude Code</button>
<button class="agent-btn agent-codex" data-agent="codex" onclick="setAgent('codex')">📟 Codex</button>
<button class="agent-btn agent-zcode" data-agent="zcode" onclick="setAgent('zcode')">⚡ ZCode</button>
</div>
<div class="mode-toggle" onclick="event.stopPropagation()">
<button id="skills-mode-direct" class="active" onclick="setSkillsExecMode('direct')">⚡ 直接运行</button>
<button id="skills-mode-input" onclick="setSkillsExecMode('input')">✎ 编辑模式</button>
<button id="skills-mode-direct" class="active" onclick="setSectionExecMode('skills','direct')">⚡ 直接运行</button>
<button id="skills-mode-input" onclick="setSectionExecMode('skills','input')">✎ 编辑模式</button>
</div>
</div>
<div class="modules" id="skills-modules-container">
@ -424,6 +436,44 @@
</div>
</div>
<!-- ── Section 3: 自动化控制流(子任务三) ── -->
<div class="sidebar-section" id="mission3-section">
<div class="sidebar-header mission3-header" onclick="toggleSection('mission3-section')">
<span class="section-arrow"></span> 🔧 自动化控制流
<div class="agent-selector" onclick="event.stopPropagation()">
<button class="agent-btn agent-claude active" data-agent="claude" onclick="setAgent('claude')">🤖 Claude Code</button>
<button class="agent-btn agent-codex" data-agent="codex" onclick="setAgent('codex')">📟 Codex</button>
<button class="agent-btn agent-zcode" data-agent="zcode" onclick="setAgent('zcode')">⚡ ZCode</button>
</div>
<div class="mode-toggle" onclick="event.stopPropagation()">
<button id="mission3-mode-direct" class="active" onclick="setSectionExecMode('mission3','direct')">⚡ 直接运行</button>
<button id="mission3-mode-input" onclick="setSectionExecMode('mission3','input')">✎ 编辑模式</button>
</div>
</div>
<div class="modules" id="mission3-modules-container">
<!-- filled by JS -->
</div>
</div>
<!-- ── Section 4: GitLink辅助科研场景子任务四 ── -->
<div class="sidebar-section" id="mission4-section">
<div class="sidebar-header mission4-header" onclick="toggleSection('mission4-section')">
<span class="section-arrow"></span> 🔬 GitLink 辅助科研场景
<div class="agent-selector" onclick="event.stopPropagation()">
<button class="agent-btn agent-claude active" data-agent="claude" onclick="setAgent('claude')">🤖 Claude Code</button>
<button class="agent-btn agent-codex" data-agent="codex" onclick="setAgent('codex')">📟 Codex</button>
<button class="agent-btn agent-zcode" data-agent="zcode" onclick="setAgent('zcode')">⚡ ZCode</button>
</div>
<div class="mode-toggle" onclick="event.stopPropagation()">
<button id="mission4-mode-direct" class="active" onclick="setSectionExecMode('mission4','direct')">⚡ 直接运行</button>
<button id="mission4-mode-input" onclick="setSectionExecMode('mission4','input')">✎ 编辑模式</button>
</div>
</div>
<div class="modules" id="mission4-modules-container">
<!-- filled by JS -->
</div>
</div>
</div>
<!-- RESIZER -->
@ -663,6 +713,309 @@ var SKILLS = [
];
var MISSION3 = [
{
id: "m3-env",
icon: "🔧",
name: "测试环境准备",
commands: [
{
label: "设置 UTF-8 控制台编码",
engine: "powershell",
cmd: "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\nWrite-Host \"当前控制台编码: $([Console]::OutputEncoding.WebName)\"\nWrite-Host \"(应为 utf-8否则含中文 JSON 解析会失败)\""
},
{
label: "确认 gitlink-cli 版本",
engine: "powershell",
cmd: ".\\gitlink-cli.exe version"
},
{
label: "确认认证状态",
engine: "powershell",
cmd: ".\\gitlink-cli.exe auth status"
},
{
label: "确认 JSON 输出正常",
engine: "powershell",
cmd: ".\\gitlink-cli.exe issue +list --owner zzx-coder --repo test-repo --state open --limit 3 --format json | ConvertFrom-Json"
},
{
label: "加载公共库 common.psm1",
engine: "powershell",
cmd: "Import-Module \".\\workflows\\lib\\common.psm1\" -Force -WarningAction SilentlyContinue\nCheck-Auth"
},
{
label: "确认测试仓库可访问",
engine: "powershell",
cmd: ".\\gitlink-cli.exe repo +info --owner zzx-coder --repo test-repo --format json | ConvertFrom-Json"
}
]
},
{
id: "m3-community",
icon: "🤝",
name: "社区运营自动化 (01-community-ops)",
commands: [
{
label: "基础只读模式验证 (DryRun)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\01-community-ops.ps1 -Owner zzx-coder -Repo test-repo -DryRun"
},
{
label: "查看命令行参数 (Help)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\01-community-ops.ps1 -Help"
},
{
label: "Issue 数据拉取验证",
engine: "powershell",
cmd: "# 拉取 open / closed Issue 与已合并 PR来自测试 2.1.3\n$openResult = .\\gitlink-cli.exe issue +list --owner zzx-coder --repo test-repo --state open --limit 100 --format json | ConvertFrom-Json\n$closedResult = .\\gitlink-cli.exe issue +list --owner zzx-coder --repo test-repo --state closed --limit 100 --format json | ConvertFrom-Json\n$prResult = .\\gitlink-cli.exe pr +list --owner zzx-coder --repo test-repo --state merged --limit 100 --format json | ConvertFrom-Json\n$prData = if ($prResult.data.issues) { @($prResult.data.issues) } else { @($prResult.data.pulls) }\nWrite-Host \"Open issues: $(@($openResult.data.issues).Count)\"\nWrite-Host \"Closed issues: $(@($closedResult.data.issues).Count)\"\nWrite-Host \"Merged PRs: $($prData.Count)\""
}
]
},
{
id: "m3-gate",
icon: "🛡",
name: "代码质量看门人 (02-code-quality-gatekeeper)",
commands: [
{
label: "审查所有 open PR (DryRun)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\02-code-quality-gatekeeper.ps1 -Owner zzx-coder -Repo test-repo -DryRun"
},
{
label: "审查指定 PR #13 (DryRun)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\02-code-quality-gatekeeper.ps1 -Owner zzx-coder -Repo test-repo -PrId 13 -DryRun"
},
{
label: "自定义质量阈值 70 (DryRun)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\02-code-quality-gatekeeper.ps1 -Owner zzx-coder -Repo test-repo -Threshold 70 -DryRun"
},
{
label: "查看帮助信息 (Help)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\02-code-quality-gatekeeper.ps1 -Help"
}
]
},
{
id: "m3-init",
icon: "🚀",
name: "项目一键初始化 (03-project-init)",
commands: [
{
label: "预览模式 (DryRun推荐首选)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\03-project-init.ps1 -Owner zzx-coder -Name test-init-dryrun -Description \"自动化测试仓库\" -Lang go -DryRun"
},
{
label: "底层命令逐步骤验证 (只读安全)",
engine: "powershell",
cmd: "# 底层命令逐步骤验证(只读安全,来自测试 2.3.2\nWrite-Host \"=== Step 1: List repos ===\" -ForegroundColor White\n$repoList = .\\gitlink-cli.exe repo +list --user zzx-coder --limit 5 --format json | ConvertFrom-Json\n$repoCount = if ($repoList.data.projects) { @($repoList.data.projects).Count } else { @($repoList.data).Count }\nWrite-Host \"Repos: $repoCount\" -ForegroundColor Green\n\nWrite-Host \"`n=== Step 2: Check Wiki access ===\" -ForegroundColor White\n$wikiResult = .\\gitlink-cli.exe wiki +list --owner zzx-coder --repo test-repo --format json | ConvertFrom-Json\nWrite-Host \"Wiki accessible: $($wikiResult.ok)\" -ForegroundColor Green\n\nWrite-Host \"`n=== Step 3: Check branch help ===\" -ForegroundColor White\n.\\gitlink-cli.exe branch --help\n\nWrite-Host \"`n=== Step 4: Check releases ===\" -ForegroundColor White\n$relResult = .\\gitlink-cli.exe release +list --owner zzx-coder --repo test-repo --limit 5 --format json | ConvertFrom-Json\nWrite-Host \"Release API accessible: $($relResult.ok)\" -ForegroundColor Green\n\nWrite-Host \"`n=== Step 5: Check milestone ===\" -ForegroundColor White\n.\\gitlink-cli.exe milestone --help"
},
{
label: "实际创建仓库 (可选·需谨慎)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\03-project-init.ps1 -Owner zzx-coder -Name \"test-init-real\" -Description \"测试仓库-可安全删除\" -Lang go"
}
]
},
{
id: "m3-multirepo",
icon: "🔗",
name: "多仓库协同 (04-multi-repo-collab)",
commands: [
{
label: "生成组织仪表盘",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\04-multi-repo-collab.ps1 -Org zzx-coder -Output dashboard.html"
},
{
label: "指定仓库列表过滤",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\04-multi-repo-collab.ps1 -Org zzx-coder -Repos \"test-repo\" -Output dashboard-filtered.html"
},
{
label: "查看帮助和参数",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\04-multi-repo-collab.ps1 -Help"
}
]
},
{
id: "m3-contrib",
icon: "🏆",
name: "贡献者成长体系 (05-contributor-growth)",
commands: [
{
label: "Dry-Run 预览模式",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\05-contributor-growth.ps1 -Owner zzx-coder -Repo test-repo -Sample 5 -DryRun"
},
{
label: "底层数据采集验证",
engine: "powershell",
cmd: "# 底层数据采集验证(来自测试 2.5.2\n$openIssues = .\\gitlink-cli.exe issue +list --owner zzx-coder --repo test-repo --state open --limit 100 --format json | ConvertFrom-Json\n$closedIssues = .\\gitlink-cli.exe issue +list --owner zzx-coder --repo test-repo --state closed --limit 100 --format json | ConvertFrom-Json\n$prsMerged = .\\gitlink-cli.exe pr +list --owner zzx-coder --repo test-repo --state merged --limit 100 --format json | ConvertFrom-Json\n$members = .\\gitlink-cli.exe repo +members --owner zzx-coder --repo test-repo --limit 100 --format json | ConvertFrom-Json\n$prData = if ($prsMerged.data.issues) { @($prsMerged.data.issues) } else { @($prsMerged.data.pulls) }\n$memberData = if ($members.data.members) { @($members.data.members) } else { @($members.data) }\nWrite-Host \"Issues - Open: $(@($openIssues.data.issues).Count), Closed: $(@($closedIssues.data.issues).Count)\" -ForegroundColor Green\nWrite-Host \"Merged PRs: $($prData.Count)\" -ForegroundColor Green\nWrite-Host \"Members: $($memberData.Count)\" -ForegroundColor Green\n$allIssues = @($openIssues.data.issues) + @($closedIssues.data.issues)\n$authors = @{}\nforeach ($issue in $allIssues) {\n $author = if ($issue.author.login) { $issue.author.login } elseif ($issue.author.username) { $issue.author.username } else { $null }\n if ($author) { if (-not $authors.ContainsKey($author)) { $authors[$author] = 0 }; $authors[$author]++ }\n}\nWrite-Host \"Unique contributors: $($authors.Count)\" -ForegroundColor Green\nforeach ($kv in ($authors.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 5)) {\n Write-Host \" @$($kv.Key): $($kv.Value) issues\"\n}"
},
{
label: "颁发徽章 (可选·需谨慎)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\05-contributor-growth.ps1 -Owner zzx-coder -Repo test-repo -Sample 5 -Award"
}
]
},
{
id: "m3-skill",
icon: "🤖",
name: "技能工作流 (Agent · gitlink-workflow)",
prompts: [
{
label: "工作流总入口(触发 7 选项菜单)",
engine: "claude",
prompt: "请帮我执行自动化工作流\n测试仓库zzx-coder/test-repo"
},
{
label: "快捷触发:社区运营",
engine: "claude",
prompt: "帮我跑一下社区运营\n测试仓库zzx-coder/test-repo"
},
{
label: "项目健康度报告 (gitlink-health)",
engine: "claude",
prompt: "请使用 gitlink-health Skill为 zzx-coder/test-repo 仓库生成项目健康度报告。"
},
{
label: "健康度路径规则验证",
engine: "claude",
prompt: "请把健康度报告保存到桌面上。\n测试仓库zzx-coder/test-repo"
},
{
label: "新人引导 AI 分析模式 (onboard)",
engine: "claude",
prompt: "请使用 gitlink-onboard Skill 的 AI 分析模式,扫描 zzx-coder/test-repo 的所有 open Issue\n识别适合新手贡献的 Good First Issue。\n展示分析结果表格后让我选择要对哪些 Issue 添加引导评论。"
},
{
label: "新人引导直接模式 (#11 dry-run)",
engine: "claude",
prompt: "请为 Issue #11 添加新人引导评论,先用 dry-run 预览。\n测试仓库zzx-coder/test-repo"
},
{
label: "FAQ 模式 A生成知识库",
engine: "claude",
prompt: "请使用 gitlink-faq Skill 的模式 A为 zzx-coder/test-repo 生成 Issue 知识库。\n同时采集 open + closed 所有 Issue合并去重逐批读取详情按类型分类和聚类\n生成知识库 Markdown 预览后等我确认再发布到 Wiki。"
},
{
label: "FAQ 模式 B重复检测",
engine: "claude",
prompt: "请检查 zzx-coder/test-repo 有没有和 \"登录功能\" 相关的已有 Issue看看是否有重复的。\n对找到的候选 Issue自动读取详情和 journals给出分析结论。"
},
{
label: "FAQ 模式 CWiki 增量更新",
engine: "claude",
prompt: "请把 Issue #11 补充到已有的 Issue 知识库 Wiki 页面中。\n测试仓库zzx-coder/test-repo"
}
]
},
{
id: "m3-smoke",
icon: "🧪",
name: "端到端冒烟测试 (15 步)",
commands: [
{
label: "运行冒烟测试(连通性验证)",
engine: "powershell",
cmd: "# 端到端冒烟测试(来自测试 5.115 步连通性验证)\n$ErrorActionPreference = \"Continue\"\n$owner = \"zzx-coder\"; $repo = \"test-repo\"\n$pass = 0; $fail = 0\nfunction Test-Step {\n param([string]$Name, [ScriptBlock]$Script)\n Write-Host \"[TEST] $Name ... \" -NoNewline -ForegroundColor Cyan\n try { $result = & $Script; if ($result) { Write-Host \"PASS\" -ForegroundColor Green; $global:pass++ } else { Write-Host \"FAIL\" -ForegroundColor Red; $global:fail++ } }\n catch { Write-Host \"FAIL ($($_.Exception.Message))\" -ForegroundColor Red; $global:fail++ }\n}\nWrite-Host \"`n====== GitLink CLI 子任务三冒烟测试 ======\" -ForegroundColor White\nWrite-Host \"Target: $owner/$repo`n\"\nTest-Step \"Auth status\" { $r = .\\gitlink-cli.exe auth status 2>&1 | Out-String; $r -match \"logged in\" -or $r -match \"token\" }\nTest-Step \"01-Community: issue +list open\" { $r = .\\gitlink-cli.exe issue +list --owner $owner --repo $repo --state open --limit 5 --format json | ConvertFrom-Json; $r.ok }\nTest-Step \"01-Community: pr +list merged\" { $r = .\\gitlink-cli.exe pr +list --owner $owner --repo $repo --state merged --limit 5 --format json | ConvertFrom-Json; $r.ok }\nTest-Step \"02-Gatekeeper: issue +view #11\" { $r = .\\gitlink-cli.exe issue +view --owner $owner --repo $repo --number 11 --format json | ConvertFrom-Json; $r.ok }\nTest-Step \"03-Init: repo +list\" { $r = .\\gitlink-cli.exe repo +list --user $owner --limit 5 --format json | ConvertFrom-Json; $r.ok }\nTest-Step \"03-Init: wiki +list\" { $r = .\\gitlink-cli.exe wiki +list --owner $owner --repo $repo --format json | ConvertFrom-Json; $r.ok }\nTest-Step \"04-MultiRepo: org repos\" { $r = .\\gitlink-cli.exe repo +list --user $owner --limit 10 --format json | ConvertFrom-Json; $r.ok }\nTest-Step \"04-MultiRepo: release +list\" { $r = .\\gitlink-cli.exe release +list --owner $owner --repo $repo --limit 5 --format json | ConvertFrom-Json; $r.ok }\nTest-Step \"05-Contrib: repo +members\" { $r = .\\gitlink-cli.exe repo +members --owner $owner --repo $repo --limit 50 --format json | ConvertFrom-Json; $r.ok }\nTest-Step \"CI: ci +builds\" { $r = .\\gitlink-cli.exe ci +builds --owner $owner --repo $repo --format json | ConvertFrom-Json; $r.ok }\nTest-Step \"Branch: branch help\" { $r = .\\gitlink-cli.exe branch --help 2>&1 | Out-String; $r -match \"Usage\" -or $r -match \"branch\" }\nTest-Step \"Milestone: milestone help\" { $r = .\\gitlink-cli.exe milestone --help 2>&1 | Out-String; $r -match \"Usage\" -or $r -match \"milestone\" }\nTest-Step \"Webhook: webhook help\" { $r = .\\gitlink-cli.exe webhook --help 2>&1 | Out-String; $r -match \"Usage\" -or $r -match \"webhook\" }\nTest-Step \"Research: search +repos\" { $r = .\\gitlink-cli.exe search +repos --q \"agent\" --limit 5 --format json | ConvertFrom-Json; $r.ok }\nWrite-Host \"`n====== Results ======\" -ForegroundColor White\nWrite-Host \" PASS: $pass\" -ForegroundColor Green\nWrite-Host \" FAIL: $fail\" -ForegroundColor Red\nWrite-Host \" TOTAL: $($pass + $fail)\" -ForegroundColor Cyan"
}
]
}
];
var MISSION4 = [
{
id: "m4-insights",
icon: "🔭",
name: "项目洞察 (06-research-insights)",
commands: [
{
label: "生成项目洞悉报告(热度/技术栈/活动)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\academic\\06-research-insights.ps1 -Owner zzx-coder -Repo test-repo"
}
]
},
{
id: "m4-compliance",
icon: "✅",
name: "合规与复现性检查 (08-research-compliance)",
commands: [
{
label: "生成 8 维复现性评分卡",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\academic\\08-research-compliance.ps1 -Owner zzx-coder -Repo test-repo"
}
]
},
{
id: "m4-progress",
icon: "📈",
name: "进度跟踪与预警 (10-research-progress)",
commands: [
{
label: "生成周度进度报告(含异常预警)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\academic\\10-research-progress.ps1 -Owner zzx-coder -Repo test-repo"
}
]
},
{
id: "m4-citation",
icon: "📄",
name: "论文引用生成 (11-research-citation)",
commands: [
{
label: "生成全部 5 种引用格式 (all)",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\academic\\11-research-citation.ps1 -Owner zzx-coder -Repo test-repo -Format all"
},
{
label: "BibTeX 格式",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\academic\\11-research-citation.ps1 -Owner zzx-coder -Repo test-repo -Format bibtex"
},
{
label: "APA 格式",
engine: "powershell",
cmd: "powershell -ExecutionPolicy Bypass -File .\\workflows\\academic\\11-research-citation.ps1 -Owner zzx-coder -Repo test-repo -Format apa"
}
]
},
{
id: "m4-research",
icon: "🔬",
name: "科研辅助 Agent (gitlink-research)",
prompts: [
{
label: "科研功能总入口6 选项菜单)",
engine: "claude",
prompt: "请使用科研辅助功能\n请展示 6 选项菜单:项目洞察 / 热点追踪 / 合规复现 / 协作匹配 / 进度预警 / 论文引用,等我选择)\n测试仓库zzx-coder/test-repo"
},
{
label: "合规与复现性检查",
engine: "claude",
prompt: "请检查 zzx-coder/test-repo 项目的合规与复现性"
},
{
label: "论文引用生成BibTeX",
engine: "claude",
prompt: "请生成 zzx-coder/test-repo 项目的论文引用BibTeX 格式)"
}
]
}
];
// ═══════════════════════════════════════════════
// DOM refs
// ═══════════════════════════════════════════════
@ -673,13 +1026,14 @@ var btnRun = document.getElementById('btn-run');
var btnCancel = document.getElementById('btn-cancel');
var cliModsContainer = document.getElementById('cli-modules-container');
var skillsModsContainer = document.getElementById('skills-modules-container');
var mission3ModsContainer = document.getElementById('mission3-modules-container');
var mission4ModsContainer = document.getElementById('mission4-modules-container');
var statusDot = document.getElementById('status-dot');
var statusText = document.getElementById('status-text');
var toast = document.getElementById('toast');
var isRunning = false;
var currentEngine = 'powershell'; // 'powershell' | 'claude'
var cliExecMode = 'direct'; // CLI section mode
var skillsExecMode = 'direct'; // Skills section mode
var execModes = { cli:'direct', skills:'direct', mission3:'direct', mission4:'direct' }; // 每个 section 的执行模式
var claudeSessionId = null; // Claude Code session ID for multi-turn
var currentAgent = 'claude'; // 'claude' | 'codex' | 'zcode'
var AGENT_META = {
@ -699,7 +1053,7 @@ function toggleSection(sectionId) {
// ═══════════════════════════════════════════════
// Build Sidebar (CLI + Skills sections)
// ═══════════════════════════════════════════════
function buildModuleGroup(container, modules, section, isSkill) {
function buildModuleGroup(container, modules, section) {
if (!container) return;
modules.forEach(function(mod, idx) {
var div = document.createElement('div');
@ -732,23 +1086,19 @@ function buildModuleGroup(container, modules, section, isSkill) {
}
function buildSidebar() {
buildModuleGroup(cliModsContainer, MODULES, 'cli', false);
buildModuleGroup(skillsModsContainer, SKILLS, 'skills', true);
buildModuleGroup(cliModsContainer, MODULES, 'cli');
buildModuleGroup(skillsModsContainer, SKILLS, 'skills');
buildModuleGroup(mission3ModsContainer, MISSION3, 'mission3');
buildModuleGroup(mission4ModsContainer, MISSION4, 'mission4');
}
// ═══════════════════════════════════════════════
// Execution Mode Toggles
// ═══════════════════════════════════════════════
function setCliExecMode(mode) {
cliExecMode = mode;
document.getElementById('cli-mode-direct').className = (mode === 'direct') ? 'active' : '';
document.getElementById('cli-mode-input').className = (mode === 'input') ? 'active' : '';
}
function setSkillsExecMode(mode) {
skillsExecMode = mode;
document.getElementById('skills-mode-direct').className = (mode === 'direct') ? 'active' : '';
document.getElementById('skills-mode-input').className = (mode === 'input') ? 'active' : '';
function setSectionExecMode(section, mode) {
execModes[section] = mode;
document.getElementById(section + '-mode-direct').className = (mode === 'direct') ? 'active' : '';
document.getElementById(section + '-mode-input').className = (mode === 'input') ? 'active' : '';
}
// ═══════════════════════════════════════════════
@ -796,10 +1146,11 @@ function setAgent(agent) {
currentAgent = agent;
// Update button active states
document.getElementById('agent-claude').className = 'agent-claude' + (agent === 'claude' ? ' active' : '');
document.getElementById('agent-codex').className = 'agent-codex' + (agent === 'codex' ? ' active' : '');
document.getElementById('agent-zcode').className = 'agent-zcode' + (agent === 'zcode' ? ' active' : '');
// Update button active states (支持多 section 共享同一 currentAgent)
var btns = document.querySelectorAll('.agent-btn');
for (var i = 0; i < btns.length; i++) {
btns[i].classList.toggle('active', btns[i].getAttribute('data-agent') === agent);
}
// Clear terminal output (but keep session)
terminal.innerHTML = '';
@ -836,14 +1187,15 @@ function onPresetSelect(selectEl, moduleId) {
return;
}
// Determine section: 'cli' or 'skills'
var isSkill = moduleId.indexOf('skills-') === 0;
// Determine section: 'cli' | 'skills' | 'mission3' | 'mission4'
var section = moduleId.substring(0, moduleId.indexOf('-mod-'));
var dataMap = { cli: MODULES, skills: SKILLS, mission3: MISSION3, mission4: MISSION4 };
var list = dataMap[section] || MODULES;
// Find module
var list = isSkill ? SKILLS : MODULES;
var mod = null;
for (var i = 0; i < list.length; i++) {
if ((isSkill ? 'skills-mod-' : 'cli-mod-') + list[i].id === moduleId) { mod = list[i]; break; }
if (section + '-mod-' + list[i].id === moduleId) { mod = list[i]; break; }
}
if (!mod) return;
@ -851,18 +1203,20 @@ function onPresetSelect(selectEl, moduleId) {
if (!item) return;
var content = item.cmd || item.prompt;
// 每个 item 可自带 engine默认 skills 走 claude其余走 powershell
var engine = item.engine || (section === 'skills' ? 'claude' : 'powershell');
// Show preview
var previewEl = document.getElementById('preview-' + moduleId);
if (previewEl) { previewEl.textContent = content; }
var mode = isSkill ? skillsExecMode : cliExecMode;
var mode = execModes[section] || 'direct';
if (mode === 'direct') {
// Execute immediately
selectEl.value = '';
if (previewEl) { previewEl.textContent = ''; }
if (isSkill) {
if (engine === 'claude') {
setEngine('claude');
executeDirectClaude(content);
} else {
@ -871,7 +1225,7 @@ function onPresetSelect(selectEl, moduleId) {
}
} else {
// Fill input for editing
if (isSkill) { setEngine('claude'); } else { setEngine('powershell'); }
setEngine(engine);
cmdInput.value = content;
autoResizeTextarea();
cmdInput.focus();

View File

@ -220,6 +220,10 @@ class DemoHandler(http.server.BaseHTTPRequestHandler):
tmp = None
proc = None
try:
# 注入 UTF-8 编码设置:避免 PowerShell 默认 GBK 解码含中文 JSON 导致
# ConvertFrom-Json 报 ArgumentException。对已有该设置的命令重复无害。
command = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\n" + command
tmp = tempfile.NamedTemporaryFile(
mode="w", suffix=".ps1", delete=False, encoding="utf-8-sig"
)

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,6 @@
# Flow: 收集周期数据 → 10类关键词分类 → 生成 Release Notes + 社区周报
# 遵循 gitlink-changelog skill 的收集→分类→发布流程
# 条目格式: - 描述 (#编号) (@作者) [分类]
=======
# ----------------------------------------------------------------
#Requires -Version 5.1
@ -18,11 +17,10 @@ param(
)
$ErrorActionPreference = "Stop"
Import-Module "$PSScriptRoot/lib/common.psm1" -Force
Import-Module "$PSScriptRoot/lib/common.psm1" -Force -WarningAction SilentlyContinue
if ($Help) {
Write-Host "Usage: powershell 01-community-ops.ps1 [-Owner O] [-Repo R] [-PeriodHours N] [-ReleaseVersion TAG] [-DryRun]"
=======
exit 0
}
@ -34,7 +32,6 @@ $Owner = $r.Owner; $Repo = $r.Repo
# Phase 1: 时间窗口和基线
# ================================================================
Log-Title "Phase 1: Time Window"
=======
$periodStart = (Get-Date).AddHours(-$PeriodHours)
@ -52,7 +49,6 @@ if ($releasesJson) {
$releases = if ($relData.releases) { @($relData.releases) } elseif ($relData -is [array]) { @($relData) } else { @() }
if ($releases.Count -gt 0) {
$prevTag = if ($releases[0].tag_name) { $releases[0].tag_name } else { "" }
=======
}
} catch {}
@ -95,7 +91,6 @@ if ($prevTag -ne "initial") {
}
Log-Ok "Commits: $commitCount"
<<<<<<< HEAD
# -- Merged PRs --
Log-Step "Collecting merged PRs..."
$prItems = @()
@ -151,7 +146,6 @@ foreach ($state in @("open","closed")) {
if (-not $inPeriod -and $closed) { try { if (([DateTime]$closed) -ge $periodStart) { $inPeriod = $true } } catch {} }
if (-not $inPeriod) { continue }
<<<<<<< HEAD
$line = "- $title (#$num) (@$author)"
if ($stateName -match "关闭|closed") { $line += " [已关闭]" }
@ -191,140 +185,15 @@ $featSection = if ($featLines.Count -gt 0) { ($featLines -join "`n") } else { "_
$docSection = if ($docLines.Count -gt 0) { ($docLines -join "`n") } else { "_无_" }
$otherSection = if ($otherLines.Count -gt 0) { ($otherLines -join "`n") } else { "_无_" }
Log-Ok "Issues in period: $issCount"
=======
$closedJson = Invoke-GL "issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "closed", "--limit", "100"
$closedCount = if ($closedJson) { @($closedJson.data.issues).Count } else { 0 }
$mergedJson = Invoke-GL "pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "merged", "--limit", "100"
$mergedData = @()
$mergedCount = 0
if ($mergedJson) {
$d = $mergedJson.data
if ($d.issues) { $mergedData = @($d.issues) }
elseif ($d.pulls) { $mergedData = @($d.pulls) }
elseif ($d -is [array]) { $mergedData = $d }
$mergedCount = $mergedData.Count
}
>>>>>>> master
# -- 贡献者汇总 --
$allContribs = @($prContributors.Keys; $issContributors.Keys) | Select-Object -Unique | Sort-Object
$contribText = if ($allContribs.Count -gt 0) { ($allContribs | ForEach-Object { "- @$_" }) -join "`n" } else { "(无活跃贡献者)" }
<<<<<<< HEAD
# ================================================================
# Phase 3: 生成 Release Notes (changelog skill 模板)
# ================================================================
Log-Title "Phase 3: Generate Release Notes"
=======
$reportTitle = "Community Weekly Report: $weekStart ~ $weekEnd"
$reportBody = "# $reportTitle" + "`n`n"
$reportBody += "## 概览" + "`n"
$reportBody += "- 仓库: **$Owner/$Repo**" + "`n"
$reportBody += "- 当前开放 Issue: **$newIssuesCount**" + "`n"
$reportBody += "- 已关闭 Issue: **$closedCount**" + "`n"
$reportBody += "- 已合并 PR: **$mergedCount**" + "`n`n"
# 分类汇总
$reportBody += "## Issue 分类汇总" + "`n"
$reportBody += "| 类型 | 数量 |" + "`n"
$reportBody += "|------|------|" + "`n"
$reportBody += "| Bug | $($BugIds.Count) |" + "`n"
$reportBody += "| Feature | $($FeatureIds.Count) |" + "`n"
$reportBody += "| Question | $($QuestionIds.Count) |" + "`n"
$reportBody += "| Docs | $($DocsIds.Count) |" + "`n`n"
# 开放 Issue 清单(含分类标记)
$reportBody += "## 当前开放 Issue 清单" + "`n"
$reportBody += "| # | 标题 | 分类 | 创建时间 |" + "`n"
$reportBody += "|---|------|------|----------|" + "`n"
foreach ($issue in $issues) {
$id = $issue.id
$title = if ($issue.subject) { $issue.subject } elseif ($issue.title) { $issue.title } else { "-" }
$title = ($title -replace '\|', '\\|')
$cat = if ($BugIds -contains $id) { "Bug" }
elseif ($FeatureIds -contains $id) { "Feature" }
elseif ($QuestionIds -contains $id) { "Question" }
elseif ($DocsIds -contains $id) { "Docs" }
else { "-" }
$created = if ($issue.created_at) { $issue.created_at } else { "-" }
$reportBody += "| #$id | $title | $cat | $created |" + "`n"
}
$reportBody += "`n"
# 已关闭 Issue 清单
$reportBody += "## 近期已关闭 Issue" + "`n"
if ($closedCount -gt 0) {
$closedIssues = @($closedJson.data.issues)
$closedLimit = [Math]::Min($closedCount, 15)
$reportBody += "| # | 标题 |" + "`n"
$reportBody += "|---|------|" + "`n"
for ($i = 0; $i -lt $closedLimit; $i++) {
$it = $closedIssues[$i]
$cid = if ($it.id) { $it.id } elseif ($it.number) { $it.number } else { "-" }
$ctitle = if ($it.subject) { $it.subject } elseif ($it.title) { $it.title } else { "-" }
$ctitle = ($ctitle -replace '\|', '\\|')
$reportBody += "| #$cid | $ctitle |" + "`n"
}
if ($closedCount -gt $closedLimit) {
$reportBody += "| ... | 还有 $($closedCount - $closedLimit) 条 |`n"
}
} else {
$reportBody += "_本周无关闭记录_" + "`n"
}
$reportBody += "`n"
# 已合并 PR 清单(含作者)
$reportBody += "## 近期已合并 PR" + "`n"
if ($mergedCount -gt 0) {
$prLimit = [Math]::Min($mergedCount, 15)
$reportBody += "| # | 标题 | 作者 |" + "`n"
$reportBody += "|---|------|------|" + "`n"
for ($i = 0; $i -lt $prLimit; $i++) {
$pr = $mergedData[$i]
$prId = if ($pr.id) { $pr.id } elseif ($pr.number) { $pr.number } else { "-" }
$ptitle = if ($pr.subject) { $pr.subject } elseif ($pr.title) { $pr.title } else { "-" }
$ptitle = ($ptitle -replace '\|', '\\|')
$pauthor = if ($pr.author -and $pr.author.login) { $pr.author.login } elseif ($pr.user -and $pr.user.login) { $pr.user.login } else { "-" }
$reportBody += "| #$prId | $ptitle | @$pauthor |" + "`n"
}
if ($mergedCount -gt $prLimit) {
$reportBody += "| ... | 还有 $($mergedCount - $prLimit) 条合并 PR |`n"
}
} else {
$reportBody += "_本周无合并记录_" + "`n"
}
$reportBody += "`n"
# 贡献者排行(按合并 PR 数)
$reportBody += "## 贡献者排行(按合并 PR 数)" + "`n"
if ($mergedCount -gt 0) {
$contributorMap = @{}
foreach ($pr in $mergedData) {
$login = if ($pr.author -and $pr.author.login) { $pr.author.login } elseif ($pr.user -and $pr.user.login) { $pr.user.login } else { $null }
if ($login) {
if ($contributorMap.ContainsKey($login)) { $contributorMap[$login]++ }
else { $contributorMap[$login] = 1 }
}
}
$reportBody += "| 排名 | 贡献者 | 合并 PR 数 |" + "`n"
$reportBody += "|------|--------|------------|" + "`n"
$rank = 1
foreach ($kv in ($contributorMap.GetEnumerator() | Sort-Object Value -Descending)) {
$reportBody += "| $rank | @$($kv.Name) | $($kv.Value) |" + "`n"
$rank++
}
} else {
$reportBody += "_本周无合并记录_" + "`n"
}
$reportBody += "`n"
$reportBody += "## 本周自动化执行" + "`n"
$reportBody += "- 自动分类并打标 Issue: **$totalClassified** 条" + "`n"
$reportBody += "- 已为 Bug/Feature 类 Issue 指派负责人" + "`n`n"
$reportBody += "---" + "`n"
$reportBody += "*Auto-generated by gitlink-cli community-ops workflow*"
>>>>>>> master
$releaseBody = @"
# 🎉 Release $newVersion
@ -364,7 +233,6 @@ $contribText
Write-Host $releaseBody
Write-Host ""
<<<<<<< HEAD
# ================================================================
# Phase 4: 发布 Release
# ================================================================
@ -380,30 +248,6 @@ if ($DryRun) {
Log-Info "View: https://www.gitlink.org.cn/$Owner/$Repo/releases"
} else {
Log-Warn "Release may have failed (tag might exist)"
=======
Log-Step "Publishing weekly report to Wiki..."
$wikiResult = Invoke-GL "wiki", "+create", "--owner", $Owner, "--repo", $Repo, "--title", $reportTitle, "--content", $reportBody
if ($wikiResult -and $wikiResult.ok) { Log-Ok "Weekly report published to Wiki" } else { Log-Warn "Wiki publish may have failed" }
# ----------------------------------------------------------------
Log-Title "Phase 4: Auto-Publish Release Notes"
# ----------------------------------------------------------------
Log-Step "Collecting recent changes for release notes..."
$tagName = "weekly-$(Get-Date -Format 'yyyyMMdd')"
$releaseName = "Weekly Release $(Get-Date -Format 'yyyy-MM-dd')"
$releaseBody = "# Release Notes - $(Get-Date -Format 'yyyy-MM-dd')" + "`n`n"
$releaseBody += "## Merged PRs ($mergedCount)"
if ($mergedCount -gt 0) {
$limit = [Math]::Min($mergedCount, 10)
for ($i = 0; $i -lt $limit; $i++) {
$prTitle = if ($mergedData[$i].subject) { $mergedData[$i].subject } elseif ($mergedData[$i].title) { $mergedData[$i].title } else { "" }
$prNum = if ($mergedData[$i].id) { $mergedData[$i].id } elseif ($mergedData[$i].number) { $mergedData[$i].number } else { "" }
$releaseBody += "`n- #$prNum $prTitle"
>>>>>>> master
}
}
@ -458,27 +302,9 @@ if ($DryRun) {
}
}
<<<<<<< HEAD
Log-Title "Complete"
Write-Host " Release: $newVersion" -ForegroundColor Green
Write-Host " PRs merged: $prCount" -ForegroundColor Green
Write-Host " Issues: $issCount" -ForegroundColor Green
Write-Host " Contributors: $($allContribs.Count)" -ForegroundColor Green
Write-Host " Wiki: $wikiTitle" -ForegroundColor Green
=======
$releaseBody += "`n`n---`n*Auto-generated by gitlink-cli community-ops workflow*"
Log-Step "Creating release: $tagName..."
$releaseResult = Invoke-GL "release", "+create", "--owner", $Owner, "--repo", $Repo, "--tag", $tagName, "--name", $releaseName, "--body", $releaseBody
if ($releaseResult -and $releaseResult.ok) { Log-Ok "Release $tagName created successfully" } else { Log-Warn "Release creation may have failed (tag might already exist)" }
# ----------------------------------------------------------------
Log-Title "Community Operations Complete"
# ----------------------------------------------------------------
Write-Host " Issues classified: $totalClassified" -ForegroundColor Green
Write-Host " Closed this week: $closedCount" -ForegroundColor Green
Write-Host " Merged PRs: $mergedCount" -ForegroundColor Green
Write-Host " Weekly report: Published to Wiki" -ForegroundColor Green
Write-Host " Release notes: $tagName" -ForegroundColor Green
>>>>>>> master

View File

@ -9,21 +9,22 @@
param(
[string]$Owner = "",
[string]$Repo = "",
[Parameter(Mandatory=$true)]
[string]$IssueNumber,
[string]$IssueNumber = "",
[string]$Assignee = "",
[switch]$DryRun,
[switch]$Help
)
$ErrorActionPreference = "Stop"
Import-Module "$PSScriptRoot/lib/common.psm1" -Force
Import-Module "$PSScriptRoot/lib/common.psm1" -Force -WarningAction SilentlyContinue
if ($Help) {
Write-Host "Usage: powershell 01a-issue-triage.ps1 -IssueNumber N [-Owner OWNER] [-Repo REPO] [-Assignee USER] [-DryRun]"
exit 0
}
if (-not $IssueNumber) { Log-Err "IssueNumber is required (use -Help for usage)"; exit 1 }
Check-Auth
$r = Resolve-OwnerRepo $Owner $Repo
$Owner = $r.Owner; $Repo = $r.Repo

View File

@ -18,8 +18,7 @@
#Requires -Version 5.1
param(
[Parameter(Mandatory=$true, HelpMessage="Webhook 回调 URLGitLink 会向此 URL 推送事件")]
[string]$WebhookUrl,
[string]$WebhookUrl = "",
[string]$Owner = "",
[string]$Repo = "",
@ -34,7 +33,7 @@ param(
)
$ErrorActionPreference = "Stop"
Import-Module "$PSScriptRoot/lib/common.psm1" -Force
Import-Module "$PSScriptRoot/lib/common.psm1" -Force -WarningAction SilentlyContinue
if ($Help) {
Write-Host "Usage: powershell 01a-webhook-setup.ps1 -WebhookUrl URL [-Owner OWNER] [-Repo REPO] [-Secret SECRET] [-Events EVENTS] [-DryRun]"
@ -66,6 +65,8 @@ if ($Help) {
exit 0
}
if (-not $WebhookUrl) { Log-Err "WebhookUrl is required (use -Help for usage)"; exit 1 }
Check-Auth
$r = Resolve-OwnerRepo $Owner $Repo
$Owner = $r.Owner; $Repo = $r.Repo

View File

@ -16,10 +16,8 @@
param(
[string]$Owner = "",
[Parameter(Mandatory=$true)]
[string]$Name,
[Parameter(Mandatory=$true)]
[string]$Description,
[string]$Name = "",
[string]$Description = "",
[string]$Lang = "go",
[switch]$Private,
[switch]$DryRun,
@ -27,13 +25,16 @@ param(
)
$ErrorActionPreference = "Stop"
Import-Module "$PSScriptRoot/lib/common.psm1" -Force
Import-Module "$PSScriptRoot/lib/common.psm1" -Force -WarningAction SilentlyContinue
if ($Help) {
Write-Host "Usage: powershell 03-project-init.ps1 -Owner OWNER -Name REPO_NAME -Description DESC [-Lang go|python|node|java] [-Private] [-DryRun]"
exit 0
}
if (-not $Name) { Log-Err "Name is required (use -Help for usage)"; exit 1 }
if (-not $Description) { Log-Err "Description is required (use -Help for usage)"; exit 1 }
Check-Auth
if (-not $Owner) {
$detected = Detect-OwnerRepo
@ -52,13 +53,17 @@ Divider
# -- Step 1: Create Repository --
Log-Step "Creating repository..."
$privateStr = if ($Private) { "true" } else { "false" }
$repoResult = Invoke-GLCheck "repo", "+create", "--owner", $Owner, "--name", $Name, "--description", $Description, "--private", $privateStr
if ($repoResult) {
Log-Ok "Repository created: $Owner/$Name"
if ($DryRun) {
Log-Warn "[DRY RUN] Would create repository: $Owner/$Name"
} else {
Log-Err "Repository creation failed"
exit 1
$privateStr = if ($Private) { "true" } else { "false" }
$repoResult = Invoke-GLCheck "repo", "+create", "--owner", $Owner, "--name", $Name, "--description", $Description, "--private", $privateStr
if ($repoResult) {
Log-Ok "Repository created: $Owner/$Name"
} else {
Log-Err "Repository creation failed"
exit 1
}
}
# -- Step 2: Create README --
@ -90,22 +95,21 @@ $readmeContent += "See [CONTRIBUTING](./CONTRIBUTING) for guidelines." + "`n`n"
$readmeContent += "## License" + "`n`n"
$readmeContent += "This project is licensed under the MIT License."
$wikiOk = $false
for ($attempt = 1; $attempt -le 3; $attempt++) {
<<<<<<< HEAD
$wikiResult = Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"README",--content,$readmeContent
if ($wikiResult -and (Get-JsonOk ($wikiResult | ConvertFrom-Json))) {
=======
$wikiResult = Invoke-GL "wiki", "+create", "--owner", $Owner, "--repo", $Name, "--title", "README", "--content", $readmeContent
if ($wikiResult -and (Get-JsonOk $wikiResult)) {
>>>>>>> master
Log-Ok "README created"
$wikiOk = $true
break
if ($DryRun) {
Log-Warn "[DRY RUN] Would create README wiki page"
} else {
$wikiOk = $false
for ($attempt = 1; $attempt -le 3; $attempt++) {
$wikiResult = Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"README",--content,$readmeContent
if ($wikiResult -and (Get-JsonOk ($wikiResult | ConvertFrom-Json))) {
Log-Ok "README created"
$wikiOk = $true
break
}
if ($attempt -lt 3) { Start-Sleep -Seconds 2 }
}
if ($attempt -lt 3) { Start-Sleep -Seconds 2 }
if (-not $wikiOk) { Log-Warn "README wiki creation may have failed" }
}
if (-not $wikiOk) { Log-Warn "README wiki creation may have failed" }
# -- Step 3: Create CONTRIBUTING Guide --
Log-Step "Creating CONTRIBUTING guide..."
@ -130,22 +134,21 @@ $contribContent += "- Use the issue tracker" + "`n"
$contribContent += "- Include reproduction steps" + "`n"
$contribContent += "- Include environment details"
$wikiOk = $false
for ($attempt = 1; $attempt -le 3; $attempt++) {
<<<<<<< HEAD
$wikiContrib = Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"CONTRIBUTING",--content,$contribContent
if ($wikiContrib -and (Get-JsonOk ($wikiContrib | ConvertFrom-Json))) {
=======
$wikiContrib = Invoke-GL "wiki", "+create", "--owner", $Owner, "--repo", $Name, "--title", "CONTRIBUTING", "--content", $contribContent
if ($wikiContrib -and (Get-JsonOk $wikiContrib)) {
>>>>>>> master
Log-Ok "CONTRIBUTING guide created"
$wikiOk = $true
break
if ($DryRun) {
Log-Warn "[DRY RUN] Would create CONTRIBUTING wiki page"
} else {
$wikiOk = $false
for ($attempt = 1; $attempt -le 3; $attempt++) {
$wikiContrib = Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"CONTRIBUTING",--content,$contribContent
if ($wikiContrib -and (Get-JsonOk ($wikiContrib | ConvertFrom-Json))) {
Log-Ok "CONTRIBUTING guide created"
$wikiOk = $true
break
}
if ($attempt -lt 3) { Start-Sleep -Seconds 2 }
}
if ($attempt -lt 3) { Start-Sleep -Seconds 2 }
if (-not $wikiOk) { Log-Warn "CONTRIBUTING wiki creation may have failed" }
}
if (-not $wikiOk) { Log-Warn "CONTRIBUTING wiki creation may have failed" }
# -- Step 4: Create CI Config Guide --
Log-Step "Creating CI/CD configuration guide..."
@ -160,12 +163,12 @@ $ciContent += "3. **Deploy**: Deploy to staging (master branch only)" + "`n`n"
$ciContent += "### Configuration" + "`n`n"
$ciContent += "Create a ``.gitlink-ci.yml`` file in the repository root."
<<<<<<< HEAD
Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"CI/CD Configuration",--content,$ciContent | Out-Null
=======
Invoke-GL "wiki", "+create", "--owner", $Owner, "--repo", $Name, "--title", "CI/CD Configuration", "--content", $ciContent | Out-Null
>>>>>>> master
Log-Ok "CI/CD configuration guide created"
if ($DryRun) {
Log-Warn "[DRY RUN] Would create CI/CD configuration wiki page"
} else {
Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"CI/CD Configuration",--content,$ciContent | Out-Null
Log-Ok "CI/CD configuration guide created"
}
# -- Step 5: Create Initial Issues --
Log-Step "Creating initial issues..."
@ -178,29 +181,37 @@ $issuesToCreate = @(
@{ Title = "Setup Dependency Management"; Body = "Configure dependency scanning and updates.`n`n## Tasks`n- [ ] Setup dependency scanner`n- [ ] Configure automatic updates`n- [ ] Add license compliance check`n- [ ] Document dependency policy"; Label = "security" }
)
foreach ($entry in $issuesToCreate) {
$issueResult = Invoke-GL "issue", "+create", "--owner", $Owner, "--repo", $Name, "--title", $entry.Title, "--body", $entry.Body
if ($issueResult) {
try {
$issueJson = $issueResult
$issueNum = if ($issueJson.data.id) { $issueJson.data.id } elseif ($issueJson.data.number) { $issueJson.data.number } else { $null }
if ($issueNum) {
Invoke-GL "issue", "+label-add", "--owner", $Owner, "--repo", $Name, "--number", $issueNum, "--labels", $entry.Label | Out-Null
Log-Ok "Issue created: #$issueNum - $($entry.Title)"
if ($DryRun) {
Log-Warn "[DRY RUN] Would create 5 initial issues"
} else {
foreach ($entry in $issuesToCreate) {
$issueResult = Invoke-GL "issue", "+create", "--owner", $Owner, "--repo", $Name, "--title", $entry.Title, "--body", $entry.Body
if ($issueResult) {
try {
$issueJson = $issueResult | ConvertFrom-Json
$issueNum = if ($issueJson.ok -and $issueJson.data.id) { $issueJson.data.id } elseif ($issueJson.ok -and $issueJson.data.number) { $issueJson.data.number } else { $null }
if ($issueNum) {
Invoke-GL "issue", "+label-add", "--owner", $Owner, "--repo", $Name, "--number", $issueNum, "--labels", $entry.Label | Out-Null
Log-Ok "Issue created: #$issueNum - $($entry.Title)"
}
} catch {
Log-Warn "Issue creation may have failed: $($entry.Title)"
}
} catch {
Log-Warn "Issue creation may have failed: $($entry.Title)"
}
}
}
# -- Step 6: Protect Default Branch --
Log-Step "Protecting master branch..."
$protectResult = Invoke-GL "branch", "+protect", "--owner", $Owner, "--repo", $Name, "--name", "master"
if ($protectResult -and (Get-JsonOk $protectResult)) {
Log-Ok "Branch 'master' protected"
if ($DryRun) {
Log-Warn "[DRY RUN] Would protect branch 'master'"
} else {
Log-Warn "Branch protection may have failed (may require admin permissions)"
$protectResult = Invoke-GL "branch", "+protect", "--owner", $Owner, "--repo", $Name, "--name", "master"
if ($protectResult -and (Get-JsonOk ($protectResult | ConvertFrom-Json))) {
Log-Ok "Branch 'master' protected"
} else {
Log-Warn "Branch protection may have failed (may require admin permissions)"
}
}
# -- Step 7: Create Initial Release --
@ -220,11 +231,15 @@ $releaseBody += "- [ ] Complete documentation" + "`n"
$releaseBody += "- [ ] First feature implementation" + "`n`n"
$releaseBody += "---`n*Auto-initialized by gitlink-cli project-init workflow*"
$releaseResult = Invoke-GL "release", "+create", "--owner", $Owner, "--repo", $Name, "--tag", "v0.1.0", "--name", "Initial Release", "--body", $releaseBody
if ($releaseResult -and (Get-JsonOk $releaseResult)) {
Log-Ok "Release v0.1.0 created"
if ($DryRun) {
Log-Warn "[DRY RUN] Would create release v0.1.0"
} else {
Log-Warn "Release creation may have failed"
$releaseResult = Invoke-GL "release", "+create", "--owner", $Owner, "--repo", $Name, "--tag", "v0.1.0", "--name", "Initial Release", "--body", $releaseBody
if ($releaseResult -and (Get-JsonOk ($releaseResult | ConvertFrom-Json))) {
Log-Ok "Release v0.1.0 created"
} else {
Log-Warn "Release creation may have failed"
}
}
# ----------------------------------------------------------------

View File

@ -13,8 +13,7 @@
#Requires -Version 5.1
param(
[Parameter(Mandatory=$true)]
[string]$Org,
[string]$Org = "",
[string]$Repos = "",
[string]$Release = "",
[string]$Output = "dashboard.html",
@ -30,6 +29,8 @@ if ($Help) {
exit 0
}
if (-not $Org) { Log-Err "Org is required (use -Help for usage)"; exit 1 }
Check-Auth
# -- Step 1: List Repositories --
@ -69,37 +70,66 @@ foreach ($repo in $repoList) {
Divider
Log-Step "Processing $Org/$repo..."
$issuesJson = Invoke-GL "issue", "+list", "--owner", $Org, "--repo", $repo, "--state", "open", "--limit", "50"
$openIssues = if ($issuesJson) { @($issuesJson.data.issues).Count } else { 0 }
$issuesRaw = Invoke-GL "issue", "+list", "--owner", $Org, "--repo", $repo, "--state", "open", "--limit", "50"
$openIssues = 0
if ($issuesRaw) {
try {
$issuesObj = $issuesRaw | ConvertFrom-Json
if ($issuesObj.ok -and $issuesObj.data.issues) {
$openIssues = @($issuesObj.data.issues).Count
}
} catch {}
}
$closedJson = Invoke-GL "issue", "+list", "--owner", $Org, "--repo", $repo, "--state", "closed", "--limit", "50"
$closedIssues = if ($closedJson) { @($closedJson.data.issues).Count } else { 0 }
$closedRaw = Invoke-GL "issue", "+list", "--owner", $Org, "--repo", $repo, "--state", "closed", "--limit", "50"
$closedIssues = 0
if ($closedRaw) {
try {
$closedObj = $closedRaw | ConvertFrom-Json
if ($closedObj.ok -and $closedObj.data.issues) {
$closedIssues = @($closedObj.data.issues).Count
}
} catch {}
}
$prsJson = Invoke-GL "pr", "+list", "--owner", $Org, "--repo", $repo, "--state", "open", "--limit", "50"
$prsRaw = Invoke-GL "pr", "+list", "--owner", $Org, "--repo", $repo, "--state", "open", "--limit", "50"
$openPRs = 0
if ($prsJson) {
$pd = $prsJson.data
if ($pd.issues) { $openPRs = @($pd.issues).Count }
elseif ($pd.pulls) { $openPRs = @($pd.pulls).Count }
elseif ($pd -is [array]) { $openPRs = $pd.Count }
if ($prsRaw) {
try {
$prsObj = $prsRaw | ConvertFrom-Json
if ($prsObj.ok) {
if ($prsObj.data.issues) { $openPRs = @($prsObj.data.issues).Count }
elseif ($prsObj.data.pulls) { $openPRs = @($prsObj.data.pulls).Count }
elseif ($prsObj.data -is [array]) { $openPRs = $prsObj.data.Count }
}
} catch {}
}
$mergedJson = Invoke-GL "pr", "+list", "--owner", $Org, "--repo", $repo, "--state", "merged", "--limit", "50"
$mergedRaw = Invoke-GL "pr", "+list", "--owner", $Org, "--repo", $repo, "--state", "merged", "--limit", "50"
$mergedPRs = 0
if ($mergedJson) {
$md = $mergedJson.data
if ($md.issues) { $mergedPRs = @($md.issues).Count }
elseif ($md.pulls) { $mergedPRs = @($md.pulls).Count }
elseif ($md -is [array]) { $mergedPRs = $md.Count }
if ($mergedRaw) {
try {
$mergedObj = $mergedRaw | ConvertFrom-Json
if ($mergedObj.ok) {
if ($mergedObj.data.issues) { $mergedPRs = @($mergedObj.data.issues).Count }
elseif ($mergedObj.data.pulls) { $mergedPRs = @($mergedObj.data.pulls).Count }
elseif ($mergedObj.data -is [array]) { $mergedPRs = $mergedObj.data.Count }
}
} catch {}
}
$releaseJson = Invoke-GL "release", "+list", "--owner", $Org, "--repo", $repo, "--limit", "1"
$releaseRaw = Invoke-GL "release", "+list", "--owner", $Org, "--repo", $repo, "--limit", "1"
$latestRelease = "none"
if ($releaseJson -and $releaseJson.data.releases) {
$releases = @($releaseJson.data.releases)
if ($releases.Count -gt 0) {
$latestRelease = if ($releases[0].tag_name) { $releases[0].tag_name } elseif ($releases[0].name) { $releases[0].name } else { "none" }
}
if ($releaseRaw) {
try {
$releaseObj = $releaseRaw | ConvertFrom-Json
if ($releaseObj.ok -and $releaseObj.data.releases) {
$releases = @($releaseObj.data.releases)
if ($releases.Count -gt 0) {
$latestRelease = if ($releases[0].tag_name) { $releases[0].tag_name } elseif ($releases[0].name) { $releases[0].name } else { "none" }
}
}
} catch {}
}
Log-Ok "$repo : Issues(open:$openIssues closed:$closedIssues) PRs(open:$openPRs merged:$mergedPRs) Release:$latestRelease"
@ -187,7 +217,7 @@ if ($Release) {
Log-Step "Creating release for $Org/$repo..."
$relBody = "Coordinated release $Release for $Org/$repo"
$relResult = Invoke-GL "release", "+create", "--owner", $Org, "--repo", $repo, "--tag", $Release, "--name", "Release $Release", "--body", $relBody
if ($relResult -and (Get-JsonOk $relResult)) {
if ($relResult -and (Get-JsonOk ($relResult | ConvertFrom-Json))) {
Log-Ok "Release $Release created for $repo"
} else {
Log-Warn "Release creation failed for $repo (tag may already exist)"

View File

@ -55,11 +55,11 @@ Log-Title "Contributor Growth System: $Owner/$Repo"
Log-Step "Collecting data..."
$issuesOpen = Invoke-GLCheck "issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "100"
$issuesClosed = Invoke-GL "issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "closed", "--limit", "100"
$issuesClosed = Invoke-GLCheck "issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "closed", "--limit", "100"
$openCount = if ($issuesOpen) { @($issuesOpen.data.issues).Count } else { 0 }
$closedCount = if ($issuesClosed) { @($issuesClosed.data.issues).Count } else { 0 }
$prsMerged = Invoke-GL "pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "merged", "--limit", "100"
$prsMerged = Invoke-GLCheck "pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "merged", "--limit", "100"
$prMergedData = @()
if ($prsMerged) {
$pd = $prsMerged.data
@ -69,7 +69,7 @@ if ($prsMerged) {
}
$prMergedCount = $prMergedData.Count
$membersJson = Invoke-GL "repo", "+members", "--owner", $Owner, "--repo", $Repo, "--limit", "100"
$membersJson = Invoke-GLCheck "repo", "+members", "--owner", $Owner, "--repo", $Repo, "--limit", "100"
$memberData = @()
if ($membersJson) {
$md = $membersJson.data
@ -119,7 +119,7 @@ for ($i = 0; $i -lt $prMergedCount; $i++) {
$contribData[$author].Merged++
}
if ($i -lt $prSample -and $prId -and $author) {
$filesJson = Invoke-GL "pr", "+files", "--owner", $Owner, "--repo", $Repo, "--id", $prId
$filesJson = Invoke-GLCheck "pr", "+files", "--owner", $Owner, "--repo", $Repo, "--id", $prId
if ($filesJson -and $filesJson.data.files) {
foreach ($f in $filesJson.data.files) {
$add = if ($f.additions) { $f.additions } elseif ($f.addition) { $f.addition } else { 0 }
@ -148,9 +148,9 @@ if ($issuesOpen) {
for ($i = 0; $i -lt $commentSample; $i++) {
$id = $openIssuesArr[$i].id
if (-not $id) { continue }
$detail = Invoke-GL "issue", "+view", "--owner", $Owner, "--repo", $Repo, "--number", $id
if ($detail) {
$commentCount = if ($detail.data.comment_journals_count) { $detail.data.comment_journals_count } else { 0 }
$detailJson = Invoke-GLCheck "issue", "+view", "--owner", $Owner, "--repo", $Repo, "--number", $id
if ($detailJson) {
$commentCount = if ($detailJson.data.comment_journals_count) { $detailJson.data.comment_journals_count } else { 0 }
if ($commentCount -gt 0) {
$author = $openIssuesArr[$i].author.login
if ($author) {
@ -371,11 +371,27 @@ $wikiContent += $wikiRankRows + "`n"
$wikiContent += "---" + "`n"
$wikiContent += "*Auto-generated by gitlink-cli*"
$wikiResult = Invoke-GL "wiki", "+create", "--owner", $Owner, "--repo", $Repo, "--title", $wikiTitle, "--content", $wikiContent
if ($wikiResult -and (Get-JsonOk $wikiResult)) {
Log-Ok "Published to Wiki: $wikiTitle"
$wikiResult = Invoke-GL "wiki", "+update", "--owner", $Owner, "--repo", $Repo, "--title", $wikiTitle, "--cover", $wikiContent
if ($wikiResult -and (Get-JsonOk ($wikiResult | ConvertFrom-Json))) {
Log-Ok "Published to Wiki (updated): $wikiTitle"
} else {
Log-Warn "Wiki publish failed"
Log-Info "Update failed (page may not exist), trying create..."
$wikiResult = Invoke-GL "wiki", "+create", "--owner", $Owner, "--repo", $Repo, "--title", $wikiTitle, "--content", $wikiContent
if ($wikiResult) {
try {
$wikiObj = $wikiResult | ConvertFrom-Json
if ($wikiObj.ok) {
Log-Ok "Published to Wiki (created): $wikiTitle"
} else {
$wikiErr = if ($wikiObj.error.message) { $wikiObj.error.message } elseif ($wikiObj.message) { $wikiObj.message } else { "unknown error" }
Log-Warn "Wiki publish failed: $wikiErr"
}
} catch {
Log-Warn "Wiki publish failed: non-JSON response from API"
}
} else {
Log-Warn "Wiki publish failed: no response from API"
}
}
# -- Step 7: Award Badges (optional) --
@ -409,8 +425,8 @@ if ($Award) {
$issueResult = Invoke-GL "issue", "+create", "--owner", $Owner, "--repo", $Repo, "--title", $issueTitle, "--body", $issueBody
if ($issueResult) {
try {
$issueJson = $issueResult
$issueNum = if ($issueJson.data.id) { $issueJson.data.id } elseif ($issueJson.data.number) { $issueJson.data.number } else { $null }
$issueJson = $issueResult | ConvertFrom-Json
$issueNum = if ($issueJson.ok -and $issueJson.data.id) { $issueJson.data.id } elseif ($issueJson.ok -and $issueJson.data.number) { $issueJson.data.number } else { $null }
if ($issueNum) {
Invoke-GL "issue", "+label-add", "--owner", $Owner, "--repo", $Repo, "--number", $issueNum, "--labels", "badge" | Out-Null
Log-Ok "Badge issue created: #$issueNum - $issueTitle ($($users.Count) recipients)"

View File

@ -33,15 +33,15 @@ Log-Info " Name: $repoName | Lang: $repoLang | Stars: $stars"
# 2. Issues
Log-Step "2/6 Collecting Issue data..."
$openIssuesJson = Invoke-GL @("issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "100")
$closedIssuesJson = Invoke-GL @("issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "closed", "--limit", "100")
$openIssuesJson = Invoke-GLCheck @("issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "100")
$closedIssuesJson = Invoke-GLCheck @("issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "closed", "--limit", "100")
$totalOpen = if ($openIssuesJson.ok) { $d = if ($openIssuesJson.data.issues) { $openIssuesJson.data.issues } else { $openIssuesJson.data }; @($d).Count } else { 0 }
$totalClosed = if ($closedIssuesJson.ok) { $d = if ($closedIssuesJson.data.issues) { $closedIssuesJson.data.issues } else { $closedIssuesJson.data }; @($d).Count } else { 0 }
# 3. PRs
Log-Step "3/6 Collecting PR data..."
$mergedPrsJson = Invoke-GL @("pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "merged", "--limit", "100")
$openPrsJson = Invoke-GL @("pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "50")
$mergedPrsJson = Invoke-GLCheck @("pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "merged", "--limit", "100")
$openPrsJson = Invoke-GLCheck @("pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "50")
$md = if ($mergedPrsJson.data.issues) { $mergedPrsJson.data.issues } elseif ($mergedPrsJson.data.pulls) { $mergedPrsJson.data.pulls } else { $mergedPrsJson.data }
$totalMerged = if ($mergedPrsJson.ok) { @($md).Count } else { 0 }
$od = if ($openPrsJson.data.issues) { $openPrsJson.data.issues } elseif ($openPrsJson.data.pulls) { $openPrsJson.data.pulls } else { $openPrsJson.data }
@ -49,17 +49,17 @@ $totalOpenPrs = if ($openPrsJson.ok) { @($od).Count } else { 0 }
# 4. Releases
Log-Step "4/6 Collecting Release data..."
$releasesJson = Invoke-GL @("release", "+list", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$releasesJson = Invoke-GLCheck @("release", "+list", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$releaseCount = if ($releasesJson.ok) { @($releasesJson.data).Count } else { 0 }
# 5. CI
Log-Step "5/6 Collecting CI data..."
$ciJson = Invoke-GL @("ci", "+builds", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$ciJson = Invoke-GLCheck @("ci", "+builds", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$ciBuilds = if ($ciJson.ok) { @($ciJson.data).Count } else { 0 }
# 6. Members
Log-Step "6/6 Fetching contributors..."
$membersJson = Invoke-GL @("repo", "+members", "--owner", $Owner, "--repo", $Repo, "--limit", "50")
$membersJson = Invoke-GLCheck @("repo", "+members", "--owner", $Owner, "--repo", $Repo, "--limit", "50")
$memberCount = if ($membersJson.ok) {
$d = if ($membersJson.data.members) { $membersJson.data.members } else { $membersJson.data }
if ($d -is [array]) { $d.Count } else { 0 }
@ -118,7 +118,7 @@ Log-Step "Detecting tech stack..."
$techStack = $repoLang
$researchFeatures = ""
$hasCitationCff = $false
$subJson = try { Invoke-GL @("api", "GET", "/v1/$Owner/$Repo/sub_entries?ref=master") } catch { $null }
$subJson = try { Invoke-GLCheck @("api", "GET", "/v1/$Owner/$Repo/sub_entries?ref=master") } catch { $null }
if ($subJson -and $subJson.ok -and ($subJson.data -is [array])) {
$names = @($subJson.data | ForEach-Object { if ($_.name) { $_.name } else { "" } })
$ecosystem = @()
@ -141,7 +141,7 @@ Log-Info " Tech stack: $techStack"
Log-Step "Reading README for project positioning..."
$readmeText = ""
try {
$readmeResult = Invoke-GL @("api", "GET", "raw/$Owner/$Repo/master/README.md")
$readmeResult = Invoke-GLCheck @("api", "GET", "raw/$Owner/$Repo/master/README.md")
if ($readmeResult.ok) { $readmeText = if ($readmeResult.data) { $readmeResult.data } else { "" } }
} catch { $readmeText = "" }

View File

@ -86,7 +86,7 @@ Log-Step "1/7 Compliance scan..."
$cloneInfo = Ensure-LocalClone -Owner $Owner -Repo $Repo -LocalPath $LocalPath
if ($cloneInfo.ScanPath -and (Test-Path (Join-Path $cloneInfo.ScanPath ".git"))) {
Push-Location $cloneInfo.ScanPath
$compResult = Invoke-GL @("compliance", "+scan")
$compResult = Invoke-GLCheck @("compliance", "+scan")
Pop-Location
if ($cloneInfo.NeedCleanup) {
# Git objects are read-only on Windows; strip attributes first
@ -128,7 +128,7 @@ if ($cloneInfo.ScanPath -and (Test-Path (Join-Path $cloneInfo.ScanPath ".git")))
# 2. README
Log-Step "2/7 README completeness..."
try {
$readmeResult = Invoke-GL @("api", "GET", "raw/$Owner/$Repo/master/README.md")
$readmeResult = Invoke-GLCheck @("api", "GET", "raw/$Owner/$Repo/master/README.md")
if ($readmeResult.ok) { $readmeText = if ($null -ne $readmeResult.data) { $readmeResult.data } else { "" } } else { $readmeText = "" }
} catch { $readmeText = "" }
@ -143,7 +143,7 @@ Log-Info " README sections: $sectionCount"
# 3. Dependencies
Log-Step "3/7 Dependency declaration..."
$subResult = Invoke-GL @("api", "GET", "/v1/$Owner/$Repo/sub_entries?ref=master")
$subResult = Invoke-GLCheck @("api", "GET", "/v1/$Owner/$Repo/sub_entries?ref=master")
$depFiles = 0
$depList = ""
$names = @()
@ -172,7 +172,7 @@ Log-Info " Build score: $buildScore/3"
# 5. CI
Log-Step "5/7 CI configuration..."
$ciResult = Invoke-GL @("ci", "+builds", "--owner", $Owner, "--repo", $Repo, "--limit", "10")
$ciResult = Invoke-GLCheck @("ci", "+builds", "--owner", $Owner, "--repo", $Repo, "--limit", "10")
$ciBuilds = if ($ciResult.ok) { @($ciResult.data).Count } else { 0 }
$ciOk = 0
if ($ciResult.ok) {

View File

@ -21,8 +21,8 @@ Log-Title "GitLink Research - Progress Tracking"
# 1. Issues
Log-Step "1/5 Collecting Issue data..."
$openIssues = Invoke-GL @("issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "100")
$closedIssues = Invoke-GL @("issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "closed", "--limit", "100")
$openIssues = Invoke-GLCheck @("issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "100")
$closedIssues = Invoke-GLCheck @("issue", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "closed", "--limit", "100")
$oiData = if ($openIssues.data.issues) { $openIssues.data.issues } else { $openIssues.data }
$totalOpen = if ($openIssues.ok) { @($oiData).Count } else { 0 }
$ciData = if ($closedIssues.data.issues) { $closedIssues.data.issues } else { $closedIssues.data }
@ -31,8 +31,8 @@ Log-Info " Issues: $totalOpen open / $totalClosed closed"
# 2. PRs
Log-Step "2/5 Collecting PR data..."
$mergedPrs = Invoke-GL @("pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "merged", "--limit", "100")
$openPrs = Invoke-GL @("pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "50")
$mergedPrs = Invoke-GLCheck @("pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "merged", "--limit", "100")
$openPrs = Invoke-GLCheck @("pr", "+list", "--owner", $Owner, "--repo", $Repo, "--state", "open", "--limit", "50")
$mData = if ($mergedPrs.data.issues) { $mergedPrs.data.issues } elseif ($mergedPrs.data.pulls) { $mergedPrs.data.pulls } else { $mergedPrs.data }
$totalMerged = if ($mergedPrs.ok) { @($mData).Count } else { 0 }
$opData = if ($openPrs.data.issues) { $openPrs.data.issues } elseif ($openPrs.data.pulls) { $openPrs.data.pulls } else { $openPrs.data }
@ -41,7 +41,7 @@ Log-Info " PRs: $totalOpenPrs open / $totalMerged merged"
# 3. Releases
Log-Step "3/5 Collecting Release data..."
$releases = Invoke-GL @("release", "+list", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$releases = Invoke-GLCheck @("release", "+list", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$releaseCount = if ($releases.ok) { @($releases.data).Count } else { 0 }
$lastReleaseDate = ""
if ($releases.ok -and $releaseCount -gt 0) {
@ -55,7 +55,7 @@ Log-Info " Releases: $releaseCount"
# 4. CI
Log-Step "4/5 Collecting CI data..."
$ci = Invoke-GL @("ci", "+builds", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$ci = Invoke-GLCheck @("ci", "+builds", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$ciTotal = if ($ci.ok) { @($ci.data).Count } else { 0 }
$ciOk = 0
if ($ci.ok) {

View File

@ -30,7 +30,7 @@ if ($doi) { Log-Info " DOI detected: $doi" }
# 2. Get latest release
Log-Step "Fetching latest version..."
$releaseJson = Invoke-GL @("release", "+list", "--owner", $Owner, "--repo", $Repo, "--limit", "1")
$releaseJson = Invoke-GLCheck @("release", "+list", "--owner", $Owner, "--repo", $Repo, "--limit", "1")
$version = if ($releaseJson.ok -and $releaseJson.data[0].tag_name) { $releaseJson.data[0].tag_name } else { "v0.0.0-dev" }
$releaseDate = if ($releaseJson.ok -and $releaseJson.data[0].created_at) { $releaseJson.data[0].created_at } else { $updatedAt }
if ($releaseDate.Length -ge 10) { $releaseDate = $releaseDate.Substring(0, 10) }
@ -38,7 +38,7 @@ $releaseYear = if ($releaseDate.Length -ge 4) { $releaseDate.Substring(0, 4) } e
# 3. Get members
Log-Step "Fetching contributors..."
$membersJson = Invoke-GL @("repo", "+members", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$membersJson = Invoke-GLCheck @("repo", "+members", "--owner", $Owner, "--repo", $Repo, "--limit", "20")
$authorNames = @()
if ($membersJson.ok) {
$data = if ($membersJson.data.members) { $membersJson.data.members } else { $membersJson.data }

View File

@ -11,7 +11,16 @@ $OutputEncoding = [System.Text.Encoding]::UTF8
# Without this, multi-byte UTF-8 chars get garbled and JSON parsing fails.
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$Script:GL = "gitlink-cli"
# Detect the gitlink-cli executable.
# Windows: prefer the repo-local build at ..\..\gitlink-cli.exe (two dirs up
# from lib/); bare 'gitlink-cli' is not on PATH in dev checkouts.
# Unix / global npm install: fall back to bare 'gitlink-cli' on PATH.
if ($env:OS -eq "Windows_NT") {
$localExe = Join-Path $PSScriptRoot "..\..\gitlink-cli.exe"
$Script:GL = if (Test-Path $localExe) { $localExe } else { "gitlink-cli" }
} else {
$Script:GL = "gitlink-cli"
}
# -- Logging --
function Log-Step { param([string]$Msg) Write-Host "[STEP] $Msg" -ForegroundColor Blue }
@ -41,10 +50,9 @@ function Check-Auth {
}
# -- CLI Wrapper --
# Returns parsed JSON object on success, $null on failure
# Usage: Invoke-GL @("issue", "+list", "--owner", $Owner, "--repo", $Repo)
# Returns raw JSON string on success, "" on failure.
# Callers do their own ConvertFrom-Json so they control error handling.
function Invoke-GL {
<<<<<<< HEAD
param([string[]]$Arguments)
# Suppress stderr to keep JSON output clean (errors go to console via error stream)
$output = & $Script:GL @Arguments --format json 2>$null
@ -52,6 +60,7 @@ function Invoke-GL {
return ""
}
# Like Invoke-GL but logs error on failure and returns parsed JSON object ($null on failure).
function Invoke-GLCheck {
param([string[]]$Arguments)
$output = Invoke-GL $Arguments
@ -71,40 +80,10 @@ function Invoke-GLCheck {
} catch {
Log-Err "Command failed (non-JSON response): $Script:GL $($Arguments -join ' ')"
Log-Err $output
=======
param([string[]]$CmdArgs)
$allArgs = @($CmdArgs) + @("--format", "json")
# Capture stdout only; stderr goes to console
$output = & $Script:GL @allArgs
$raw = ($output -join "`n")
if (-not $raw -or $raw.Trim() -eq "") { return $null }
try {
return ($raw | ConvertFrom-Json)
} catch {
>>>>>>> master
return $null
}
}
# Like Invoke-GL but logs error on failure
function Invoke-GLCheck {
param([string[]]$CmdArgs)
$json = Invoke-GL $CmdArgs
if (-not $json) {
$argStr = $CmdArgs -join " "
Log-Err "Command failed (no JSON): $Script:GL $argStr"
return $null
}
if (-not $json.ok) {
$argStr = $CmdArgs -join " "
$errMsg = if ($json.error -and $json.error.message) { $json.error.message } else { "unknown error" }
Log-Err "Command failed: $Script:GL $argStr"
Log-Err $errMsg
return $null
}
return $json
}
# -- JSON Helpers --
function Get-JsonOk {
param($Json)