add ? and § dual-track buttons to G/K/F/H tabs + 4 spec JSON files
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"module": "dev_spec",
|
||||
"version": "1.0",
|
||||
"purpose": "Dashboard 'G 规范' tab 展示开发规范 (dev-spec.md) 内容,供开发人员查阅系统架构、编码规范、部署流程等约束。",
|
||||
"ui_location": "Principles 菜单 → G 规范 tab",
|
||||
|
||||
"human_help": {
|
||||
"title": "G 规范 — 开发规范",
|
||||
"description": [
|
||||
"本 tab 展示 dev-spec.md(开发规范文档)的完整内容,包含系统架构、开发约束、上线流程、编码规范等。",
|
||||
"文档本身通过 git 版本管理,历史版本可通过下方的「历史版本」折叠区查看。",
|
||||
"修改 dev-spec.md 后需 commit & push,dashboard 自动读取最新版本。"
|
||||
],
|
||||
"usage": [
|
||||
"1. 查看当前开发规范和约束",
|
||||
"2. 点击「历史版本」折叠区查看 git commit 历史",
|
||||
"3. 如需修改:编辑 docs/dev-spec.md → git commit → git push → 刷新本页"
|
||||
],
|
||||
"related": "H 需求 tab 展示产品需求文档 (PRD.md),G+H 构成双轨规范体系"
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/spec", "returns": "{ok, content, path} — dev-spec.md 全文"},
|
||||
{"method": "GET", "path": "/api/spec/history", "returns": "{ok, count, log} — git log 条目"}
|
||||
],
|
||||
"dependencies": [
|
||||
"docs/dev-spec.md 文件必须存在且在 git 跟踪中",
|
||||
"git 历史依赖 git log 命令可用"
|
||||
],
|
||||
"constraints": [
|
||||
"文档展示在子 tab 中,通过 fill('spec', html) 渲染",
|
||||
"内容通过内置 mdRender() 函数转换 Markdown 到 HTML",
|
||||
"历史版本折叠区默认收起,不占用首屏空间"
|
||||
],
|
||||
"tests": [
|
||||
{"id": "DS01", "name": "/api/spec 返回 dev-spec.md 内容", "endpoint": "GET /api/spec"},
|
||||
{"id": "DS02", "name": "/api/spec/history 返回 git log", "endpoint": "GET /api/spec/history"},
|
||||
{"id": "DS03", "name": "G tab 展示规范的 Markdown 渲染内容", "endpoint": "n/a (frontend check)"}
|
||||
],
|
||||
"related_files": [
|
||||
"docs/dev-spec.md — 被展示的规范文档",
|
||||
"gateway/scripts/dashboard.py — /api/spec, /api/spec/history",
|
||||
"gateway/scripts/templates/dashboard.html — fS2() 渲染函数",
|
||||
"gateway/scripts/specs/dev_spec.json — 本 spec 文件"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"module": "health",
|
||||
"version": "1.0",
|
||||
"purpose": "Dashboard 'F 健康' tab 展示系统整体健康状态,三層結構:系统概览 → 异常服务 → 全部服务(按功能分层)。",
|
||||
"ui_location": "Principles 菜单 → F 健康 tab",
|
||||
|
||||
"human_help": {
|
||||
"title": "F 健康 — 系统健康",
|
||||
"description": [
|
||||
"本 tab 展示系统全部服务的运行健康状态,采用三層結構方便快速定位问题:",
|
||||
"第一層「系统概览」:整体状态信号(正常/部分异常/严重异常)+ 数字摘要",
|
||||
"第二層「异常服务」:只高亮显示有问题的服务,附带影响描述",
|
||||
"第三層「全部服务」:按功能分层列出所有服务及其运行状态",
|
||||
"底部「定时任务」区域展示 Windows Scheduled Tasks 状态。"
|
||||
],
|
||||
"usage": [
|
||||
"1. 先看顶部概览信号(绿色=正常,黄色=部分异常,红色=严重异常)",
|
||||
"2. 如果概览显示异常,直接看「异常服务」区域了解具体哪个服务挂了及影响范围",
|
||||
"3. 需要查看全部服务状态时,展开「全部服务」按层浏览",
|
||||
"4. 底部定时任务区域检查计划任务是否正常运行"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"如果无法加载数据:检查 dashboard.py (5803) 是否运行",
|
||||
"如果部分服务显示 down 但实际在运行:检查该服务的 health check 端点",
|
||||
"如果定时任务都显示 not_deployed:这些任务是 Windows 端配置的,246 上无法检测"
|
||||
],
|
||||
"related": "K 测试 tab 有各模块的细化测试结果,G 规范定义服务应满足的规范要求"
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/services", "returns": "{ok, services[{name,type,port,health{ok},watchdog,depends_on}]} — 运行服务列表含健康检查"},
|
||||
{"method": "GET", "path": "/api/expected", "returns": "{expected[{name,port,expected,critical}], actual{name:status}} — 期望状态矩阵"},
|
||||
{"method": "GET", "path": "/api/monitor", "returns": "{tier1{summary{ok,total}}, tier2{summary{ok,total}}, tasks[{name,status}]} — 监控聚合"}
|
||||
],
|
||||
"dependencies": [
|
||||
"/api/services 依赖各个服务的 HTTP health check 端点",
|
||||
"/api/expected 依赖 port_open()、schtasks、pgrep 等检测方法",
|
||||
"/api/monitor 源自 dashboard.py 定时执行的健康检查任务"
|
||||
],
|
||||
"architecture": {
|
||||
"three_layer_design": "Layer1=summary cards(status+nums), Layer2=issues only(highlight with impact text), Layer3=all services grouped by layer(通信层/AI网关/辅助服务/定时任务)"
|
||||
},
|
||||
"constraints": [
|
||||
"services 和 expected 数据源有重叠但不完全一致 — 代码用 added{} 去重合并",
|
||||
"ejabberd 和 gateway 服务只出现在 /api/services,不在 /api/expected 中",
|
||||
"watchdog 和定时任务只出现在 /api/expected,不在 /api/services",
|
||||
"tier1 监控可能不存在 — 代码做空值检查 (if mD.tier1 && mD.tier1.summary)",
|
||||
"所有服务名通过 M{} 元数据映射到中文 label/layer/impact"
|
||||
],
|
||||
"must_not": [
|
||||
"不要移除 added{} 去重机制 — 否则 expected 和 services 重叠的服务会重复显示",
|
||||
"不要在 fHealth() 里用 fill('health',...) 外的渲染方式 — 标准 fill pattern",
|
||||
"不要移除 M{} 元数据映射 — 它是中文展示和分层的核心"
|
||||
],
|
||||
"tests": [
|
||||
{"id": "H01", "name": "/api/services 返回服务列表", "endpoint": "GET /api/services"},
|
||||
{"id": "H02", "name": "/api/expected 返回期望矩阵", "endpoint": "GET /api/expected"},
|
||||
{"id": "H03", "name": "/api/monitor 返回监控数据", "endpoint": "GET /api/monitor"},
|
||||
{"id": "H04", "name": "三層結構正确渲染 (summary + issues + grouped)", "endpoint": "n/a (frontend check)"}
|
||||
],
|
||||
"known_issues": [
|
||||
"scheduled tasks 在 Linux 246 上无法检测 Windows 计划任务状态,统一显示 not_deployed",
|
||||
"部分服务的 HTTP health check 端点可能返回 Connection refused(如 xmpp_bot 在 5802 仅 Windows 端监听)"
|
||||
],
|
||||
"related_files": [
|
||||
"gateway/scripts/templates/dashboard.html — fHealth() 渲染函数",
|
||||
"gateway/scripts/dashboard.py — /api/services, /api/expected, /api/monitor",
|
||||
"gateway/scripts/specs/health.json — 本 spec 文件"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"module": "prd",
|
||||
"version": "1.0",
|
||||
"purpose": "Dashboard 'H 需求' tab 展示产品需求文档 (PRD.md) 内容,包含产品目标、功能需求、交付标准等。",
|
||||
"ui_location": "Principles 菜单 → H 需求 tab",
|
||||
|
||||
"human_help": {
|
||||
"title": "H 需求 — 产品需求",
|
||||
"description": [
|
||||
"本 tab 展示 PRD.md(产品需求文档)的完整内容,包含产品的核心目标、功能需求、验收标准等。",
|
||||
"PRD 文档通过 git 版本管理,历史版本可通过下方的「历史版本」折叠区查看。",
|
||||
"H 需求与 G 规范构成双轨制:H 描述「做什么」,G 描述「怎么做」。"
|
||||
],
|
||||
"usage": [
|
||||
"1. 查看产品的核心目标和功能需求",
|
||||
"2. 了解各需求的验收标准和优先级",
|
||||
"3. 点击「历史版本」折叠区查看 PRD 的变更历史",
|
||||
"4. 如需修改 PRD:编辑 docs/PRD.md → git commit → git push → 刷新本页"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"如果 PRD 内容不显示:检查 docs/PRD.md 文件是否存在",
|
||||
"如果历史版本不显示:确认 PRD.md 已在 git 跟踪中且有提交记录"
|
||||
],
|
||||
"related": "G 规范 tab 展示开发规范 (dev-spec.md),G+H 构成双轨规范体系"
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/prd", "returns": "{ok, content, path} — PRD.md 全文"},
|
||||
{"method": "GET", "path": "/api/prd/history", "returns": "{ok, count, log} — git log 条目"}
|
||||
],
|
||||
"dependencies": [
|
||||
"docs/PRD.md 文件必须存在且在 git 跟踪中",
|
||||
"git 历史依赖 git log 命令可用",
|
||||
"PRD 通过 dev-spec.md 内容中的 'PRD' 前缀部分加载 — 或由 /api/prd 端点单独加载"
|
||||
],
|
||||
"constraints": [
|
||||
"文档展示在子 tab 中,通过 fill('prd', html) 渲染",
|
||||
"内容通过内置 mdRender() 函数转换 Markdown 到 HTML",
|
||||
"历史版本折叠区默认收起",
|
||||
"PRD 文档的修改应符合双轨原则:H 聊做什么,G 聊怎么做"
|
||||
],
|
||||
"tests": [
|
||||
{"id": "PRD01", "name": "/api/prd 返回 PRD.md 内容", "endpoint": "GET /api/prd"},
|
||||
{"id": "PRD02", "name": "/api/prd/history 返回 git log", "endpoint": "GET /api/prd/history"},
|
||||
{"id": "PRD03", "name": "H tab 展示 PRD 的 Markdown 渲染内容", "endpoint": "n/a (frontend check)"}
|
||||
],
|
||||
"related_files": [
|
||||
"docs/PRD.md — 被展示的需求文档",
|
||||
"gateway/scripts/dashboard.py — /api/prd, /api/prd/history",
|
||||
"gateway/scripts/templates/dashboard.html — fH() 渲染函数",
|
||||
"gateway/scripts/specs/prd.json — 本 spec 文件"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"module": "tests",
|
||||
"version": "1.0",
|
||||
"purpose": "Dashboard 'K 测试' tab 展示系统测试运行结果,包含 Passed/Failed/Expected Fail 分类汇总。",
|
||||
"ui_location": "Principles 菜单 → K 测试 tab",
|
||||
|
||||
"human_help": {
|
||||
"title": "K 测试 — 测试报告",
|
||||
"description": [
|
||||
"本 tab 展示系统各模块的自动化测试结果。",
|
||||
"测试用例通过 /api/tests 获取,按 Passed / Failed / Expected Fail 分类展示。",
|
||||
"Expected Fail 表示已知但可接受的失败(不影响整体功能),Real Fail 需要关注。"
|
||||
],
|
||||
"usage": [
|
||||
"1. 查看顶部的概要卡片(Total / Passed / Failed)了解整体情况",
|
||||
"2. 检查 Expected Fail 区域 — 已知问题,yellow 标记",
|
||||
"3. 检查 Real Fail 区域 — 需要修复的问题,red 标记",
|
||||
"4. 查看 Passed 列表确认正常功能不受影响"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"如果数据加载失败,检查 dashboard.py 是否运行在 5803 端口",
|
||||
"如果所有测试都 Failed:检查 /api/tests 端点是否返回正确格式的数据"
|
||||
],
|
||||
"related": "G 规范定义模块应满足的开发规范,H 需求定义产品层验收条件"
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/tests", "returns": "{ok, summary{total,passed,failed}, tests[{name,ok,detail,expected}], time}"}
|
||||
],
|
||||
"dependencies": [
|
||||
"dashboard.py 的 test runner 或外部测试脚本提供数据"
|
||||
],
|
||||
"constraints": [
|
||||
"测试列表按 expected 字段分类展示 — expected=true 的失败归类为 'Expected Fail'",
|
||||
"expected=false 且 failed 的测试归类为 'Real Fail',会以红框突出显示",
|
||||
"summary 卡片显示 total / passed / failed 但不含 expected 维度",
|
||||
"支持自定义测试套件通过 API 注入"
|
||||
],
|
||||
"tests": [
|
||||
{"id": "T01", "name": "/api/tests 返回完整测试结果", "endpoint": "GET /api/tests"},
|
||||
{"id": "T02", "name": "测试结果正确分类 (Passed/Failed/Expected)", "endpoint": "n/a (data validation)"}
|
||||
],
|
||||
"related_files": [
|
||||
"gateway/scripts/dashboard.py — /api/tests 端点",
|
||||
"gateway/scripts/templates/dashboard.html — fTests() 渲染函数",
|
||||
"gateway/scripts/specs/tests.json — 本 spec 文件"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -164,7 +164,7 @@ async function fHealth(){try{
|
||||
M['agents-todo-executor']={n:'待办执行器(10min)',l:'定时任务',i:'定时待办任务未执行'};
|
||||
var layerOrder=['通信层','AI网关','辅助服务','定时任务'];
|
||||
|
||||
var h='';
|
||||
var h='<h2>F 系统健康<span class="help-btn" onclick="showModuleHelp(\'health\',\'human\')" title="使用说明">?</span><span class="help-btn ai" onclick="showModuleHelp(\'health\',\'ai\')" title="AI Spec">§</span></h2>';
|
||||
var all=await Promise.all([
|
||||
fetch('/api/services').then(function(r){return r.json()}).catch(function(){return{}}),
|
||||
fetch('/api/expected').then(function(r){return r.json()}).catch(function(){return{}}),
|
||||
@@ -429,7 +429,7 @@ function _renderUsageMetric(label,m,barColor){
|
||||
async function fH(){try{
|
||||
var r=await fetch('/api/prd'),d=await r.json();
|
||||
if(!d.ok||!d.content){fill('prd','Failed');return}
|
||||
var h='<div style=padding:8px 0>'+mdRender(d.content)+'</div>';
|
||||
var h='<h2>H 产品需求<span class="help-btn" onclick="showModuleHelp(\'prd\',\'human\')" title="使用说明">?</span><span class="help-btn ai" onclick="showModuleHelp(\'prd\',\'ai\')" title="AI Spec">§</span></h2><div style=padding:8px 0>'+mdRender(d.content)+'</div>';
|
||||
try{var rh=await fetch('/api/prd/history'),dh=await rh.json();
|
||||
if(dh.ok&&dh.log&&dh.log.length){
|
||||
h+='<div class=section style=margin-top:16px><h2 style=font-size:17px;cursor:pointer onclick="var e=document.getElementById(\'prd-history\');e.style.display=e.style.display===\'none\'?\'block\':\'none\'">历史版本 <span style=color:var(--dim);font-size:18px>('+dh.count+' commits)</span></h2><div id=prd-history style=display:none;margin-top:8px>';
|
||||
@@ -438,7 +438,7 @@ async function fH(){try{
|
||||
}catch(e){}
|
||||
fill('prd',h)}catch(e){fill('prd','Error')}}
|
||||
|
||||
async function fTests(){try{var r=await fetch('/api/tests'),d=await r.json();var h='';if(!d.ok||!d.tests){fill('tests','<span class=tag r>Error</span>');return}
|
||||
async function fTests(){try{var r=await fetch('/api/tests'),d=await r.json();var h='<h2>K 测试报告<span class="help-btn" onclick="showModuleHelp(\'tests\',\'human\')" title="使用说明">?</span><span class="help-btn ai" onclick="showModuleHelp(\'tests\',\'ai\')" title="AI Spec">§</span></h2>';if(!d.ok||!d.tests){fill('tests','<span class=tag r>Error</span>');return}
|
||||
var s=d.summary;h+='<div style=display:flex;gap:12px;margin-bottom:16px><div style="background:var(--card);border:1px solid var(--border);border-radius:8px;padding:12px 16px;flex:1;text-align:center"><div style=font-size:32px;font-weight:700;color:var(--accent)>'+s.total+'</div><div style=color:var(--dim);font-size:19px>Total</div></div><div style="background:var(--card);border:1px solid var(--border);border-radius:8px;padding:12px 16px;flex:1;text-align:center"><div style=font-size:32px;font-weight:700;color:var(--green)>'+s.passed+'</div><div style=color:var(--dim);font-size:19px>Passed</div></div><div style="background:var(--card);border:1px solid var(--border);border-radius:8px;padding:12px 16px;flex:1;text-align:center"><div style=font-size:32px;font-weight:700;color:var(--red)>'+s.failed+'</div><div style=color:var(--dim);font-size:19px>Failed</div></div></div>';
|
||||
h+='<div style=margin-bottom:8px;font-weight:600;color:var(--yellow)>Expected Fail ('+s.failed+')</div>';
|
||||
d.tests.filter(function(t){return!t.ok&&t.expected}).forEach(function(t){h+='<div style="background:var(--card);border:1px solid var(--yellow);border-radius:6px;padding:6px 12px;margin-bottom:4px"><span style="background:var(--yellow);color:#000;padding:1px 6px;border-radius:3px;font-weight:700;font-size:18px">EXPECTED</span> <span style=font-size:19px>'+esc(t.name)+'</span> <span style=font-size:19px;color:var(--dim)>'+esc(t.detail||'')+'</span></div>';});
|
||||
@@ -457,7 +457,7 @@ async function fR(){try{var r=await fetch('/api/rdp'),d=await r.json();var e1=do
|
||||
var fS2_c=null;var fS2_last='';async function fS2(){try{
|
||||
var r=await fetch('/api/spec'),d=await r.json();
|
||||
if(!d.ok||!d.content){fill('spec','Failed');return}
|
||||
var h='<div style=padding:8px 0>'+mdRender(d.content)+'</div>';
|
||||
var h='<h2>G 开发规范<span class="help-btn" onclick="showModuleHelp(\'dev_spec\',\'human\')" title="使用说明">?</span><span class="help-btn ai" onclick="showModuleHelp(\'dev_spec\',\'ai\')" title="AI Spec">§</span></h2><div style=padding:8px 0>'+mdRender(d.content)+'</div>';
|
||||
try{var rh=await fetch('/api/spec/history'),dh=await rh.json();
|
||||
if(dh.ok&&dh.log&&dh.log.length){
|
||||
h+='<div class=section style=margin-top:16px><h2 style=font-size:17px;cursor:pointer onclick="var e=document.getElementById(\'spec-history\');e.style.display=e.style.display===\'none\'?\'block\':\'none\'">历史版本 <span style=color:var(--dim);font-size:18px>('+dh.count+' commits)</span></h2><div id=spec-history style=display:none;margin-top:8px>';
|
||||
|
||||
Reference in New Issue
Block a user