更新: 2531 个文件 - 2026-03-17 21:00:03

这个提交包含在:
hao
2026-03-17 21:00:04 -07:00
父节点 a3edc88834
当前提交 080e55a98c
修改 2531 个文件,包含 135521 行新增3725 行删除

查看文件

@@ -38,6 +38,7 @@ const ARTIFACT_KIND_LABELS = {
const DOC_HUB_ITEMS = [
{ title: "项目功能总览", href: "/docs/project-features.html", description: "项目定位、功能版图、自动化链路和 CLI 入口。", badge: "docs" },
{ title: "前端设计文档", href: "/docs/frontend-dashboard-design.html", description: "工作台布局、交互、折叠逻辑和视觉规范。", badge: "ui" },
{ title: "中文完整度报告", href: "/docs/testing-completeness-report.html", description: "89 条 advisory 的最新完整度、family 矩阵与 ingest 健康度。", badge: "report" },
{ title: "架构库镜像", href: "/docs/architecture-library.html", description: "当前架构库的结构化镜像页,可直接查看 JSON 真值。", badge: "architecture" },
{ title: "仓库入口镜像", href: "/docs/root-readme.html", description: "根 README 的本地镜像,包含能力矩阵与主入口。", badge: "readme" },
{ title: "授权模型", href: "/docs/authorization-model.html", description: "目标范围、授权模型、最小化验证建议和记录要求。", badge: "scope" },
@@ -50,6 +51,7 @@ const DOC_HUB_ITEMS = [
const DATA_HUB_ITEMS = [
{ title: "summary.json", href: "/summary.json", description: "全局摘要、状态分布、最近失败与系统汇总。", badge: "json" },
{ title: "completeness.json", href: "/data/completeness.json", description: "最新 advisory 完整度、系统/family 进度与 ingest 健康度。", badge: "json" },
{ title: "runs.json", href: "/runs.json", description: "最近运行的结构化详情,可用于 UI 和调试。", badge: "json" },
{ title: "systems.json", href: "/systems.json", description: "系统级覆盖、分类、更新时间和浏览器证据统计。", badge: "json" },
{ title: "advisories.json", href: "/advisories.json", description: "漏洞条目元数据、来源和 secure-code 主题。", badge: "json" },
@@ -84,6 +86,7 @@ const state = {
advisories: {},
profiles: {},
architecture: null,
completeness: null,
selectedRunId: null,
selectedArtifact: null,
refreshHandle: null,
@@ -275,15 +278,17 @@ function familyOptions() {
}
function metricCards() {
const successCount = Number(state.summary?.statuses?.["verified-real"] || 0) + Number(state.summary?.statuses?.["verified-synthetic"] || 0);
const blockedCount = sumStatuses((key) => key.startsWith("blocked"));
const inProgressCount = Math.max(Number(state.summary?.run_count || 0) - successCount - blockedCount, 0);
const completeness = state.completeness || state.summary?.completeness || {};
const successCount = Number(completeness.verified_real || 0) + Number(completeness.verified_synthetic || 0);
const blockedCount = Number(completeness.blocked || 0);
const inProgressCount = Number(completeness.manual || 0);
const advisoryTotal = Number(completeness.advisory_total || state.summary?.advisory_count || 0);
return [
{
label: "运行总数",
value: state.summary?.run_count || 0,
note: `已索引漏洞条目 ${state.summary?.advisory_count || 0} `,
label: "最新 advisory",
value: advisoryTotal,
note: `历史运行 ${state.summary?.run_count || 0} `,
color: "var(--accent-purple)",
iconName: "report"
},
@@ -297,14 +302,14 @@ function metricCards() {
{
label: "当前阻塞",
value: blockedCount,
note: "制品阻塞或破坏性风险阻塞",
note: "latest advisory 状态里的 blocked-*",
color: "var(--accent-red)",
iconName: "failure"
},
{
label: "待处理 / 进行中",
value: inProgressCount,
note: "人工分诊待补证据或未完成实证",
note: "人工分诊待补证据的 latest advisory",
color: "var(--accent-blue)",
iconName: "timeline"
}
@@ -755,6 +760,54 @@ function renderPanel(panelKey, title, meta, iconName, content) {
`;
}
function renderCompletenessPanel(panelKey, compact = false) {
const completeness = state.completeness || state.summary?.completeness || {};
const systems = (state.completeness?.systems || []).map((system) => `
<article class="plan-card">
<span class="plan-label">${escapeHtml(system.system_id)}</span>
<div class="plan-copy">${escapeHtml(`${system.verified_real}/${system.total} verified-real`)}</div>
<div class="tag-row">
${(system.families || []).map((family) => `<span class="tag">${escapeHtml(`${family.family} ${family.verified_real}/${family.total}`)}</span>`).join("")}
</div>
</article>
`).join("");
const failures = (state.completeness?.ingest_health?.failures || []).slice(0, 5);
return renderPanel(
panelKey,
"最新 advisory 完整度",
`${escapeHtml(completeness.verified_real || 0)}/${escapeHtml(completeness.advisory_total || 0)}`,
"shield",
`
<div class="detail-stat-grid">
<article class="detail-stat">
<strong>verified-real</strong>
<span>${escapeHtml(completeness.verified_real || 0)}</span>
</article>
<article class="detail-stat">
<strong>blocked</strong>
<span>${escapeHtml(completeness.blocked || 0)}</span>
</article>
<article class="detail-stat">
<strong>manual</strong>
<span>${escapeHtml(completeness.manual || 0)}</span>
</article>
<article class="detail-stat">
<strong>ingest failures</strong>
<span>${escapeHtml(state.completeness?.ingest_health?.failure_count || 0)}</span>
</article>
</div>
<div class="plan-grid" style="margin-top:16px;">${systems || `<div class="empty-state">暂无系统完整度数据。</div>`}</div>
${compact ? "" : `
<div class="detail-actions" style="margin-top:16px;">
<a class="button button-secondary" href="/docs/testing-completeness-report.html" target="_blank" rel="noreferrer">${icon("docs")}<span>打开中文报告</span></a>
<a class="button button-secondary" href="/data/completeness.json" target="_blank" rel="noreferrer">${icon("json")}<span>打开 completeness.json</span></a>
</div>
${failures.length ? `<div class="callout" style="margin-top:16px;"><strong>Ingest 未清零</strong><div class="plan-copy">${escapeHtml(failures.join(" | "))}</div></div>` : ""}
`}
`
);
}
function renderArchitectureFields(fields = []) {
if (!fields.length) return "";
return `
@@ -1061,6 +1114,7 @@ function renderRunWorkspace() {
</article>
</div>
</section>
${renderCompletenessPanel("runs_completeness", true)}
${renderPanel("timeline", "进度时间线", `${escapeHtml(run.timeline?.length || 0)}`, "timeline", `
<div class="progress-bar">${progressSegments(progress).bar}</div>
<div class="progress-legend">${progressSegments(progress).legend}</div>
@@ -1130,6 +1184,7 @@ function renderOverviewWorkspace() {
<h2 class="detail-title">按板块浏览当前工作台</h2>
<div class="detail-subtitle">根入口保留为概览页,同时新增运行、系统、架构、文档和数据的独立 URL。顶部菜单负责分类切换,搜索与筛选会同步到地址栏。</div>
</section>
${renderCompletenessPanel("overview_completeness")}
${renderPanel("overview_runs", "最新运行", `${escapeHtml(runs.length)}`, "queue", renderRunList(runs, "暂无运行数据。"))}
${renderPanel("overview_systems", "系统覆盖概览", `${escapeHtml(systems.length)} 个系统`, "systems", `<div class="system-grid">${renderSystemCards(systems)}</div>`)}
${renderArchitecturePanel()}
@@ -1195,6 +1250,7 @@ function renderDocsWorkspace() {
<h2 class="detail-title">文档入口按板块集中</h2>
<div class="detail-subtitle">不再把所有入口混在首页链接堆里。这里按说明、设计、真值镜像和 secure-code 索引集中展示。</div>
</section>
${renderCompletenessPanel("docs_completeness", true)}
${renderPanel("docs_hub", "文档与镜像页", `${escapeHtml(DOC_HUB_ITEMS.length)} 个入口`, "docs", renderHubCards(DOC_HUB_ITEMS))}
</div>
`;
@@ -1215,6 +1271,7 @@ function renderDataWorkspace() {
<h2 class="detail-title">数据入口按类型集中</h2>
<div class="detail-subtitle">summary、runs、systems、advisories、profiles、architecture 已单独归入数据中心,避免和文档、运行详情混在一个地址里。</div>
</section>
${renderCompletenessPanel("data_completeness", true)}
${renderPanel("data_hub", "JSON 与生成数据", `${escapeHtml(DATA_HUB_ITEMS.length)} 个入口`, "json", renderHubCards(DATA_HUB_ITEMS))}
</div>
`;
@@ -1416,13 +1473,14 @@ async function loadData(preserveSelection = true) {
renderSyncState("loading", "刷新中", `本地时间 ${new Date().toLocaleTimeString("zh-CN", { hour12: false })}`);
try {
const [summary, runs, systems, advisories, profiles, architecture] = await Promise.all([
const [summary, runs, systems, advisories, profiles, architecture, completeness] = await Promise.all([
fetchJson("/summary.json"),
fetchJson("/runs.json"),
fetchJson("/systems.json"),
fetchJson("/advisories.json"),
fetchJson("/profiles.json"),
fetchJson("/architecture.json")
fetchJson("/architecture.json"),
fetchJson("/data/completeness.json")
]);
state.summary = summary;
@@ -1431,6 +1489,7 @@ async function loadData(preserveSelection = true) {
state.advisories = advisories;
state.profiles = profiles;
state.architecture = architecture;
state.completeness = completeness;
const filtered = filteredRuns();
const candidate = preserveSelection ? (state.selectedRunId || previousRunId) : state.selectedRunId;