Progress tracking now lives in a separate project. Drop the server, docs, and module-boundary entries without restoring engineering-dashboard. Co-authored-by: Cursor <cursoragent@cursor.com>
33 KiB
title, type, date, artifact_contract, product_contract_source, execution
| title | type | date | artifact_contract | product_contract_source | execution |
|---|---|---|---|---|---|
| 个人工程中控台:实时项目看板与离线 HTML 快照 | feat | 2026-09-17 | ce-unified-plan/v1 | ce-plan-bootstrap | code |
已废弃(2026-09-17;2026-09-19 更新):旧版只读工程中控台代码已移除。后来短暂合入的 Control Center 也已移出本仓库,进度管理由独立项目承担。本文仅作历史证据保留。
个人工程中控台:实时项目看板与离线 HTML 快照
Goal Capsule
为仓库所有者提供一个独立于产品后台的本地只读中控台。打开一个页面即可判断当前系统由什么组成、哪些任务正在计划或实施、真实分支和 worktree 在哪里、各环境实际运行了什么,并能在两次点击内到达对应的设计、审计、整改、任务和测试材料。
中控台同时提供两种输出:
serve:持续采集本地仓库、Git 和运行环境,提供自动刷新的 HTML 页面与机器可读 JSON;export:基于同一份不可变快照生成单文件 HTML,便于归档、离线查看和交接。
这不是产品功能,不接入产品后台、产品数据库或产品权限体系;它也不是发布系统,不执行 Git、Docker、部署或文档写操作。
成功标准
- 在当前仓库规模下,首次可用页面目标为 2 秒内出现;慢数据源可随后标记为
degraded,不得拖垮整页。 - 正常情况下,本地文件、Git 或运行态变化在 5 秒内反映到新快照。
- 页面分别展示“文档声明、Git 实施、验证证据、环境实装”,不把任务文档的
done翻译为已合并或已部署。 - 每个关键结论均显示来源、采集时间、新鲜度和可信类型;冲突保留双方证据,不静默选边。
- 在线模式检索 allowlist 内未截断的 Markdown 正文;离线导出同时给出 included、truncated 和 metadata-only 清单,二进制附件只索引路径、类型、大小和归属。
- 单文件 HTML 默认权限为
0600,可脱离仓库阅读已纳入 inclusion manifest 的 Markdown 正文,并醒目标出截断或仅元数据条目;不打包.doc/**/assets。 - 任一采集源失败时仍可查看最近成功数据,并明确显示
stale/error/last_success_at。
Product Contract
用户与使用场景
唯一主要用户是仓库所有者。典型使用包括:
- 每天开始工作时查看焦点任务、阻塞、集成槽和环境异常;
- 从模块进入设计、任务、测试和部署证据链;
- 判断某项工作究竟只是有计划、正在实现、已经验证,还是已在某环境实装;
- 查看本地分支、远端跟踪引用、ahead/behind、worktree 和未提交变更;
- 发现
CURRENT、功能矩阵、发布门禁、Git 与 Docker 之间的漂移; - 导出一个自包含 HTML,作为某一时点的项目快照。
已确定的产品决策
PKD-1:独立本地工具
采用独立 Go CLI 和本地 Web 页面,不加入现有产品后台。
(session-settled: user-approved — chosen over product-admin integration: the console is for the repository owner’s local engineering management and the production image excludes .doc and .git)
PKD-2:只读实时页与离线快照共用数据模型
实时服务和导出文件必须由同一份版本化快照生成,避免在线页面与离线报告出现两套口径。
(session-settled: user-approved — chosen over a static-only report: the requested console must follow agent tasks and project state as they change)
核心需求
| ID | 需求 |
|---|---|
| R1 | CLI 默认解析当前 Git 仓库根,也接受显式 --repo;页面始终显示绝对根路径、当前分支、HEAD 和采集时间。 |
| R2 | 仅监听 127.0.0.1,不依赖产品容器、产品数据库或产品登录。 |
| R3 | 架构与模块页聚合 module-boundaries.yaml、系统设计索引和 FEATURE-MATRIX,展示模块、能力、依赖和证据链。 |
| R4 | 任务状态至少拆为 doc_status、Git facets、verification_result/verification_freshness、deployment facets;可并存事实不得压成单值枚举。 |
| R5 | Git 页展示本地/跟踪分支、ahead/behind、最近提交、worktree、dirty/untracked 和任务声明匹配情况;不得隐式 fetch。 |
| R6 | 部署页按 shared/dev/test/main 分别展示容器状态、应用 readiness、服务完整性、schema、镜像与 promotion receipt;不得计算未经定义的综合绿灯。 |
| R7 | 文档页支持按 taxonomy、状态、模块和关键词筛选,展示正文、正向链接、反向链接、broken、orphan 与 unindexed 状态;查询状态可通过 URL 恢复。 |
| R8 | 一个不可变快照包含 schema_version、generation_id、revision_id、generated_at、仓库/提交身份、来源状态、事实与冲突。 |
| R9 | 自动刷新采用完整快照原子切换;每个来源独立超时,失败时保留最近成功数据并标注过期。 |
| R10 | 每条关键事实标注 declared、observed、verified 或 inferred,并保留来源路径和采集时间。 |
| R11 | 单 HTML 内嵌结构化模型、页面资源和允许导出的 Markdown 正文;附件只保留元数据及相对链接,并显示内容覆盖清单。 |
| R12 | 对 Agent 暴露稳定的只读 JSON,而不是让 Agent 解析 HTML;JSON 与页面引用同一 generation_id 和 revision_id。 |
| R13 | TaskState 显示声明的 owner/Agent 类型/认领/mutex 与基于 Git 的最近活动证据;Herdr 工程 Agent 和产品 PI Agent Runner 使用不同类型。没有运行态来源时必须显示 unknown,不得把“已认领”写成“正在执行”。 |
| R14 | 文件、命令和 HTTP 均采用 allowlist;拒绝路径穿越、symlink 越界、原始 HTML 执行、远程资源加载和凭证读取。 |
事实源与权威边界
| 领域 | 权威来源 | 中控台处理方式 |
|---|---|---|
| 发布门禁 | .doc/remediation/gap-matrix.md |
只解释发布 blocker,不替代能力完成度。 |
| 能力成熟度 | .doc/status/FEATURE-MATRIX.md |
显示功能完成度,不据此推断是否部署。 |
| 当前焦点、认领、集成槽 | .doc/ops/CURRENT.md |
作为团队声明,与 Git 和运行态对账。 |
| 任务计划 | ops/short-term、ops/long-term、backlog front matter |
作为计划状态,不据此推断实现。 |
| 分支与 worktree | Git plumbing | 作为本地观测;远端状态注明“基于本地 refs,未联网刷新”。 |
| 环境运行态 | Docker/Compose 元数据与 /ready |
分开展示容器、应用与服务完整性。 |
| 验收证据 | .doc/test-reports 及 promotion receipts |
显示证据存在性与身份,不以文件名替代内容校验。 |
来源之间不设全局覆盖顺序。各来源回答自己的问题;值不一致时生成 drift,并并列展示原值、时间和来源。
用户流程
flowchart LR
Start[启动 serve 或 export] --> Root[解析显式 repo root]
Root --> Collect[并行采集文档 Git 运行态]
Collect --> Snapshot[构建不可变快照]
Snapshot --> Reconcile[按领域对账]
Reconcile --> Live[本地实时页面和 JSON]
Reconcile --> Export[单文件 HTML]
Live --> Refresh[定时生成下一快照]
Refresh --> Snapshot
总览默认优先显示 in_progress、blocked、planned、partial/deferred、drift 和 degraded。done 与 archive 默认收起,避免历史材料淹没当前工作。
任务详情按照以下证据链导航:
flowchart LR
Audit[audit 问题] --> Remediation[remediation 方案]
Remediation --> Task[任务声明]
Task --> Git[分支 worktree commit merge]
Git --> Test[测试与验收报告]
Test --> Deploy[环境 artifact 与 readiness]
显式 Markdown 链接和既定 taxonomy 属于强关系;仅由文件名或 slug 推断的关系标为“候选”,不得参与完成度计算。
状态模型
flowchart TB
D[doc_status: planned/in_progress/blocked/done] --> View[并列状态视图]
G[Git facets: branch/worktree/merge/cleanliness/ahead-behind] --> View
V[Verification: result + freshness + bound identity] --> View
P[Deployment facets: container/readiness/services/artifact identity] --> View
View --> Drift{来源是否一致}
Drift -->|是| Consistent[consistent]
Drift -->|否| Conflict[drift + 双方证据]
“实装”定义为存在可核对的环境观测证据,而不是任务文档为 done。容器可达但 artifact identity 无法核对时显示“运行可见、版本未验证”,不得提升为 verified deployment。当文档声明 healthy、Docker 显示异常而 /ready 为 ok 时,页面保留多值并标记 drift,不输出统一绿灯。
真实验收样本
- rdev:存在调研、设计、任务与 backlog,但若没有 CURRENT 认领和真实分支,应显示“已计划、未认领、未实施、未实装”。
- main 环境:若 CURRENT 声明整体 healthy,而 events 容器实际 restarting、应用
/ready仍为 ok,应同时显示三项证据与 drift。 - 本地 dev:若分支领先
origin/dev,必须显示“本地已具备、远端未确认可用”,不得写成已远程发布。 system-admin-console:作为产品管理后台能力,与本计划的个人工程中控台分开展示,名称和边界不得混淆。
安全与非目标
一期明确不做:
- 不写文档,不修改任务状态,不占用集成槽;
- 不创建、切换、合并、删除或推送 Git 分支;
- 不执行
git fetch,不调用远端托管平台 API; - 不启动、停止、重建或部署容器;
- 不控制 Herdr 或向 Agent 派发任务;
- 不读取
.env、.secrets、DockerConfig.Env、数据库数据或.git内部文件正文; - 不加入产品 API、产品前端、产品数据库或生产镜像;
- 不执行 Markdown 原始 HTML、脚本、Mermaid 或远程资源。
后续候选包括跨快照历史、远端 CI/Gitea 聚合、受限 Markdown/Mermaid 渲染、Agent 查询 API 和修复建议。任何写操作继续保持在本工具之外。
Planning Contract
High-Level Technical Design
以下图示冻结边界和协议,不规定具体函数签名。
flowchart LR
Docs[.doc sources] --> DC[Document collector]
Git[Git/worktrees] --> GC[Git collector]
Run[Docker/ready/receipts] --> RC[Runtime collector]
DC --> Build[Snapshot builder]
GC --> Build
RC --> Build
Build --> Rec[Reconcile facts and conflicts]
Rec --> JSON[Read-only JSON]
Rec --> Web[Local HTML]
Rec --> File[Offline HTML]
sequenceDiagram
participant UI as Browser
participant C as Collection coordinator
participant S as Sources
participant P as Snapshot publisher
UI->>C: poll with revision_id
C-->>UI: current snapshot immediately
C->>S: singleflight collection with deadlines
S-->>C: facts or source error
C->>P: publish complete generation atomically
P-->>UI: new revision or not-modified
stateDiagram-v2
[*] --> Loading
Loading --> Fresh: first collection succeeds
Loading --> ErrorUnknown: first collection fails
Fresh --> Refreshing: TTL expires
Refreshing --> Fresh: new generation succeeds
Refreshing --> Stale: source fails and last-known exists
Stale --> Fresh: source recovers
ErrorUnknown --> Fresh: source first succeeds
技术决策
KTD-1:采用仓库内独立 Go CLI
新增 cmd/engineering-dashboard 与 internal/engineeringdashboard,复用仓库 Go 工具链但不导入产品业务包。Go 标准库足以提供本地 HTTP、资源嵌入、JSON、并发和原子文件输出;现有 yaml.v3 可用于已定义的 YAML 契约。
KTD-2:快照是唯一交付模型
采集器只生产事实,reconcile 层只生产派生状态和冲突,HTTP/API/export 只消费已完成的不可变快照。快照至少包含:
schema_version, generation_id, revision_id, generated_at, collection_duration
repository { root, branch, head, dirty }
sources[] { name, status, observed_at, last_success_at, error }
facts[] { subject, field, value, provenance, source_ref, observed_at, confidence }
conflicts[] { subject, field, kind, fact_refs[] }
documents[], modules[], tasks[], git[], environments[]
generation_id 唯一标识一次采集,包含采集批次语义;revision_id 只由 schema、仓库身份和规范化的非易变事实、冲突、来源状态确定,明确排除 generated_at、observed_at 和采集耗时。HTML 与 JSON 必须展示同一对标识,HTTP ETag 和前端是否重绘使用 revision_id。一期不读取旧 schema 的外部 JSON;离线 HTML 自带对应 renderer,因此不依赖未来二进制迁移。
KTD-3:专用解析器与容错索引并存
对 CURRENT、FEATURE-MATRIX、gap-matrix、任务 front matter 和 module boundaries 编写契约化解析器。文档层只索引 promotion receipt 的路径与链接,结构化部署凭证由运行态采集器唯一负责。对其余 Markdown 只提取安全元数据、标题、正文与链接。专用解析器失败时保留原文入口并标记 degraded,不凭模糊规则编造状态。
KTD-4:命令执行采用固定 argv 和超时
Git 与 Docker 采集通过注入式 command runner 执行固定程序和分离 argv,不通过 shell 拼接。--repo 先转为绝对、symlink-resolved 的 Git 根并作为单个参数传递。每个来源默认 2 秒超时;错误输出做长度限制和敏感字段清理。Git 使用 porcelain/plumbing 输出,例如 status --porcelain=v2、worktree list --porcelain、for-each-ref、rev-list、merge-base。
KTD-5:一期采用短轮询,不引入持久数据库
服务端由单一采集协调器按 TTL 触发完整重采集,2–5 秒刷新;同一仓库最多一轮采集在途,请求只读取当前快照,不直接叠加扫描。每轮带单调 generation 序号和整轮 deadline,只有当前有效轮次能原子发布。页面使用 ETag/revision_id 避免重复传输。last-known 只在同一 serve 进程内有效;冷启动或单次 export 首次采集失败时显示 unknown/error,不伪造历史值。文件监听、SSE 通知、持久缓存和历史数据库均后置。
KTD-6:安全阅读优先于富渲染
在线详情页一期将 Markdown 全部作为纯文本安全转义,并保留换行和空白;标题、列表、链接、代码、图片和 Mermaid 均显示源码,不生成 HTML 节点或发起资源请求。静态导出内嵌同一正文和内部导航。所有文档 ID 都是规范化仓库相对路径,只允许 .doc/**/*.md 及明确列入 allowlist 的根 Markdown;读取前后都校验解析路径,直接拒绝 symlink,并对 .git、.env*、.secrets、data 等敏感路径执行最终目标 denylist。
KTD-7:导出为自包含、有限尺寸的证据快照
导出将模型、CSS、JS 和允许的 Markdown 正文写入单 HTML,采用临时文件加 rename 原子落盘,默认 0600。数据使用 HTML-safe JSON 或等价编码封装,正文只通过 textContent/DOM API 写入;CSP 禁止网络、外部资源和内联事件执行。默认只嵌入 Git tracked、allowlist 内的 Markdown;untracked Markdown 只列元数据,除非用户显式选择。导出前输出 inclusion manifest 与敏感模式告警;.doc/**/assets、数据库、构建产物和二进制报告不嵌入。
建议目录
cmd/engineering-dashboard/
main.go
internal/engineeringdashboard/
model.go
collector.go
source_docs.go
source_git.go
source_runtime.go
reconcile.go
server.go
export.go
assets/
index.html
app.js
app.css
testdata/
docs/
git/
runtime/
scripts/
engineering-dashboard.sh
.doc/test-reports/
YYYY-MM-DD-engineering-dashboard-test-report.md
风险与缓解
| 风险 | 缓解 |
|---|---|
| 文档结构并不完全统一 | 只对 SSOT 和任务 front matter 使用严格契约;其余文档容错索引并暴露解析告警。 |
| 看板制造“假完成” | 多轴 facets、事实 provenance、验证身份绑定、冲突不覆盖、真实反例测试。 |
| Docker/Git 卡住或不可用 | 独立超时、并行采集、last-known 状态、degraded 页面。 |
| 文档 XSS 或路径穿越 | 纯文本渲染、HTML-safe 数据封装、CSP、路径 allowlist、拒绝 symlink、最终目标敏感路径 denylist。 |
.doc 附件导致扫描/导出失控 |
默认跳过 assets 内容,只采集元数据;设置单文档和总正文上限并报告截断。 |
导出副本离开本机后 0600 不再提供保护 |
页面首部标明敏感快照、仓库身份和生成时间;输出 inclusion manifest,交接者自行控制接收者、保留期与删除。 |
| worktree 与主 checkout 混淆 | 只管理 --repo 指定/解析出的根,页面常驻显示根与 HEAD;其他 worktree 仅作为 Git 元数据。 |
| 本地 remote refs 被误认为远端实时状态 | 显示 refs 观测时间和“未联网刷新”,不自动 fetch。 |
与产品 system-admin-console 命名冲突 |
CLI、包和文档统一使用 engineering-dashboard / “个人工程中控台”。 |
Implementation Units
U1:冻结快照、事实与状态契约
目标:先建立不会把计划、实现、验证、部署混为一谈的模型与测试夹具。
覆盖需求:R4、R8、R10、R12、R13;承接 PKD-2 的同源快照决策。
依赖:无。
文件:
internal/engineeringdashboard/model.gointernal/engineeringdashboard/model_test.gointernal/engineeringdashboard/testdata/**
实施要点:
- 定义版本化
Snapshot、SourceState、Fact、Conflict、TaskState、AgentClaim、EnvironmentState。 - provenance 固定为
declared|observed|verified|inferred;freshness 固定为fresh|stale|error|unknown。 - 状态使用可组合 facets:Git 分为 branch/worktree/merge/cleanliness/ahead-behind;验证分为 result/freshness/subject identity;部署分为 container/readiness/services/artifact identity。
- TaskState 保留 owner、agent kind、claim、mutex、声明分支、观测 worktree、最近活动时间及证据;声明与观测不可互相提升。
- 建立 rdev、dev ahead、main events restarting、CURRENT/worktree 不匹配等夹具。
测试场景:
- 文档
done但无 merge/deploy 时,Git 与部署 facets 不改变; claimed但无可观测运行信号时,Agent 活动保持 unknown;Herdr 与产品 PI Runner 不共享类型;- 同字段多来源不一致时生成 conflict 并保留所有 fact 引用;
- JSON round-trip 保留 schema 与 snapshot identity;
- 枚举未知值失败且错误可定位。
完成证据:模型测试通过,schema 示例落入 Go fixture,不存在页面专用的第二套状态类型。
U2:实现文档图谱与领域解析器
目标:将 .doc taxonomy、模块、任务、测试和链接转换为可追溯文档图谱。
覆盖需求:R3、R7、R10、R11、R14。
依赖:U1。
文件:
internal/engineeringdashboard/source_docs.gointernal/engineeringdashboard/docs_test.go
实施要点:
- 扫描 allowlist 内 Markdown,默认跳过任何
assets目录正文;记录附件元数据。 - 解析 front matter、标题、显式 Markdown 链接和反向链接。
- 为 CURRENT、FEATURE-MATRIX、gap-matrix、任务文、module boundaries 和 test report 建立专用适配器;receipt 只在文档图谱中作为文档与链接,结构化解析归 U4。
- 区分
broken、orphan、unindexed;slug 相似只形成候选关系。 - 规范化路径并阻止
..、绝对路径和任何 symlink;最终目标再次应用扩展名 allowlist 与敏感路径 denylist。
测试场景:
- taxonomy 内文档可检索且反向链接正确;
- broken link 不导致整个索引失败;
- front matter 缺失或非标准时产生告警并仍可阅读;
- assets 不读正文,越界 symlink 被拒绝;
- rdev 文档链被发现,但没有被推断为已实现。
完成证据:文档索引能从 fixture 生成稳定 JSON,路径安全负例通过。
U3:实现 Git 与 worktree 采集
目标:以只读 Git plumbing 形成可复现的分支、提交和 worktree 观测。
覆盖需求:R1、R4、R5、R10、R14。
依赖:U1。
文件:
internal/engineeringdashboard/source_git.gointernal/engineeringdashboard/git_test.go
实施要点:
- 抽象 command runner,固定 argv、工作目录、超时和输出上限。
- 收集当前分支/HEAD、dirty/untracked、local/remote-tracking refs、ahead/behind、merge-base 和 worktree。
- 不执行 fetch;remote tracking ref 始终带本地观测时间与免责声明。
- 对账任务声明的 branch/worktree,但不因路径名相似而认定一致。
测试场景:
- 本地分支领先 origin 时显示 ahead 且不显示“远端可用”;
- worktree 目录名与真实检出分支不一致时生成 drift;
- 命令超时、Git 不存在、非 Git 目录时单源 degraded;
- runner 记录中不存在 shell、fetch、push 或写命令。
完成证据:临时 Git 仓库集成测试和 fake runner 单元测试通过。
U4:实现运行态与部署证据采集
目标:按环境独立呈现容器、应用 readiness、服务完整性、schema、镜像和晋升凭证。
覆盖需求:R4、R6、R10、R14。
依赖:U1。
文件:
internal/engineeringdashboard/source_runtime.gointernal/engineeringdashboard/runtime_test.go
实施要点:
- 从仓库内批准的 Compose 静态配置和 allowlist labels 映射环境与服务;无法明确映射时显示 unknown,不用名称猜测。容器 JSON 只提取容器名、image/digest、状态、restart count、health,以及 allowlist 内的 Compose project/service labels;不复制 Env、Mounts、完整 NetworkSettings 或任意 labels。
- 对 allowlist 中的本地
/ready端点执行短超时、响应大小受限的请求;禁用重定向,或对每一跳重新校验 scheme、解析后 IP、端口和 host。 - 解析 promotion receipt/candidate image 等仓库证据,保留 artifact identity。
- 将 container health、app readiness、required-service completeness 分开建模。
测试场景:
- app ready 且 events restarting 时同时保留两项状态;
- Docker 不可用或 HTTP 超时时,其他数据源仍可输出;
- receipt 与容器 image 不一致时生成 deployment drift;容器可达但 identity 缺失时标记“运行可见、版本未验证”;
- readiness 重定向到外网或非 allowlist 本地端口时拒绝访问;
- 输出中不存在容器环境变量或凭证。
完成证据:fixture 和 fake HTTP/Docker runner 测试通过,main 分叉场景被覆盖。
U5:实现对账、派生视图与新鲜度
目标:把来源事实组合成用户可判断的视图,但不替来源做未经定义的裁决。
覆盖需求:R3、R4、R6、R8、R9、R10、R13。
依赖:U2、U3、U4。
文件:
internal/engineeringdashboard/reconcile.gointernal/engineeringdashboard/reconcile_test.go
实施要点:
- 按领域 SSOT 规则构建 module、task、environment 和 evidence-chain 视图。
- 实现 conflict 分类:declared-vs-observed、task-vs-git、test-vs-subject、receipt-vs-runtime、stale-source、missing-evidence。
- 快照构建期间每个来源独立记录
observed_at、持续时间和错误;成功后一次性发布。 - 失败源只可复用同一 serve 进程的 last-known,并标注 stale、age 与 last-success;冷启动无缓存时为 unknown/error。过期数据不隐藏,但按年龄提升告警级别。
- 测试报告只有在 commit/artifact identity 与当前 subject 对齐时才能派生 pass;身份缺失为 unbound,身份不匹配为 stale/drift。
测试场景:
- 三个真实样本得到预期多轴状态;
- 同一组输入顺序变化不改变规范化快照;
- 单源失败不会删除其他源,也不会重写 last-known 的观测时间;冷启动失败没有伪造 last-known;
- 旧测试报告、新 HEAD 与不同 image 不会派生当前验证通过;
- 恢复后 stale 自动清除并产生新 snapshot ID。
完成证据:reconcile table tests 覆盖一致、漂移、缺失、过期和恢复。
U6:实现本地服务、总览与文档导航
目标:提供能快速判断异常并下钻证据的本地只读页面和 JSON。
覆盖需求:R1、R2、R3、R7–R10、R12–R14;承接 PKD-1 和 PKD-2。
依赖:U5。
文件:
internal/engineeringdashboard/server.gointernal/engineeringdashboard/server_test.gointernal/engineeringdashboard/assets/index.htmlinternal/engineeringdashboard/assets/app.jsinternal/engineeringdashboard/assets/app.csscmd/engineering-dashboard/main.go
实施要点:
serve --repo <path> --addr 127.0.0.1:<port>;一期无条件拒绝所有非 loopback 地址,包括通配、IPv6 非 loopback 和显式传入值。- 暴露
/api/v1/snapshot、/api/v1/doc/<id>、/healthz;所有接口只读。严格校验 Host/Origin/Fetch Metadata,不信任代理转发头;页面和 API 使用每次启动生成的不可预测访问令牌,降低 DNS rebinding 与跨站读取风险。 - 页面分为总览、架构/模块、任务、Git、部署、文档和证据链。
- 自动刷新完整快照,保留当前筛选、滚动位置、焦点和选中文档;ETag 未变化时不重绘。
- 明确一级视图状态:initial loading、fresh empty、fresh success、partial/degraded with last-known、hard error without cache、refreshing、recovered。刷新中继续展示上一完整快照,直到下一版本原子替换。
- 搜索覆盖标题、仓库相对路径、front matter 和未截断正文;不同维度用 AND、同一维度多选用 OR,默认先排当前任务和异常证据,再按匹配度与路径稳定排序。筛选、查询和选中文档写入 URL 参数,支持浏览器前进/后退与深链。
- 桌面优先;窄屏下侧栏变为可关闭抽屉,宽表格保留可横向滚动的语义表头,详情区单列。所有功能可键盘完成,使用 landmark/标题/表格语义,drift/degraded 不只靠颜色表达,自动刷新通过非打断式 live region 报告且不抢焦点。
- Markdown 正文只进入文本节点;在线页与导出页均设置限制性 CSP,不执行 HTML、脚本、SVG、远程 URL 或事件属性。
测试场景:
- 只监听 loopback,方法 allowlist 拒绝写请求;Host/Origin/token、DNS rebinding 和跨 Origin 负例被拒绝;
- HTML 与 JSON 的 generation/revision identity 一致;
- 文档 ID 越界、symlink 越界、未知 ID 返回安全错误;
- degraded source 在总览可见且页面仍可导航;
- 任务状态四轴、drift 和来源时间在浏览器中可见。
- 首次加载、空数据、无缓存错误、刷新、恢复状态可区分;键盘、焦点、语义结构、窄屏和非颜色告警验收通过。
- 搜索组合逻辑、排序、无结果、URL 深链和刷新后的视图保持通过。
完成证据:HTTP tests、基本无障碍检查和真实浏览器验收通过。
U7:实现离线导出、启动脚本与治理文档
目标:生成安全、可携带、可追踪的单文件快照,并完成仓库治理接线。
覆盖需求:R1、R8、R9、R11、R14;承接 PKD-1 和 PKD-2。
依赖:U6。
文件:
internal/engineeringdashboard/export.gointernal/engineeringdashboard/export_test.goscripts/engineering-dashboard.sh.doc/status/FEATURE-MATRIX.md.doc/ops/CURRENT.md.doc/test-reports/YYYY-MM-DD-engineering-dashboard-test-report.md
实施要点:
export --repo <path> --output <file>构建一次不可变快照并原子写入;首次采集失败的来源显示 unknown/error。- 以 HTML-safe JSON/等价编码内嵌允许的 Markdown 正文、索引和页面资源;附件保持元数据与相对链接,所有正文只写入文本节点。
- 默认权限
0600,输出页显示生成时间、repo、HEAD、snapshot ID 和 degraded/drift。 - 薄脚本只负责定位仓库与调用 Go CLI,不隐藏参数或执行安装/部署副作用。
- 实施期间按仓库规范更新 CURRENT、FEATURE-MATRIX 和 test report;完成后再迁移任务生命周期状态。
测试场景:
- 导出文件脱离仓库后仍能搜索和阅读 Markdown;
- 导出中不含附件字节、绝对凭证路径、env 值或远程请求;
</script>、事件属性、SVG、危险 URL scheme 和 Unicode 边界载荷不能逃逸数据上下文; - 默认 tracked/untracked 与敏感模式策略、inclusion manifest 和覆盖清单符合契约;
- 采集部分失败时仍能导出并保留错误;
- 输出中 JSON/HTML snapshot identity 一致,权限符合预期;
- 大文档和总正文上限触发时明确标记截断。
完成证据:export tests、离线浏览器验收和治理文档回链完整。
Verification Contract
自动验证
实施阶段至少运行:
go test ./internal/engineeringdashboard/...
go test ./cmd/engineering-dashboard/...
go vet ./...
go test -short ./...
git diff --check
涉及共享容器的只读验收也必须遵守 CURRENT 集成槽规则;中控台本身不得为测试启动、停止或重建共享容器。
契约验证矩阵
| 领域 | 必须证明 |
|---|---|
| 模型 | 计划、Git facets、验证、部署 facets 互不覆盖;Agent 声明和运行观测分离;所有派生结论可追溯到 facts。 |
| 文档 | taxonomy、全文检索、反链、broken/unindexed、路径安全与 assets 排除。 |
| Git | ahead/behind、worktree、dirty、local refs 新鲜度和无隐式 fetch。 |
| 部署 | container/app/service 三类信号分离,receipt/artifact 身份可核对。 |
| 降级 | 每个源超时、错误、stale、恢复都不会让整页不可用。 |
| 实时 | 变化在目标时间内形成完整新快照,不出现半新半旧卡片。 |
| 导出 | 单文件离线可读、默认 0600、不嵌 assets、不产生网络请求。 |
| 安全 | loopback、Host/Origin/startup token、read-only methods、命令 allowlist、路径边界、Docker 字段 allowlist、CSP 与输出脱敏。 |
浏览器验收
- 从总览进入 rdev,确认“计划/实施/验证/实装”四轴与源文档链接均可见。
- 在仓库外复制导出 HTML,断网打开并全文搜索、阅读至少一份设计与一份测试报告。
- 制造 fixture 中的 CURRENT/Docker/readiness 冲突,确认页面保留多值且不出现综合绿灯。
- 切换 fixture 快照,确认页面刷新后筛选条件和当前文档保持不变。
- 尝试路径穿越、未知文档、POST、DNS rebinding、跨 Origin、readiness 重定向和含原始 HTML/脚本逃逸载荷的 Markdown,确认均不能越界、外联或执行。
性能与容量验证
- 记录当前
.doc规模下的冷启动、增量刷新、JSON 大小和 HTML 导出大小。 - 建议一期门槛:UI shell 与来源状态在 2 秒内可交互,P95 完整快照重建不超过 5 秒,单源超时不超过 2 秒;基线不达标时必须记录实测并拆分后台正文索引,不能伪造 PASS。
- 导出达到配置上限时必须显式列出被截断文档,不允许静默丢失。
Definition of Done
serve和export在显式仓库根下可重复运行,且没有产品后台依赖。- 实时 HTML、离线 HTML 与 JSON 使用同一版本化快照契约。
generation_id标识采集实例,revision_id标识内容版本并驱动 ETag;无内容变化不会触发重绘。- 架构、模块、功能、任务、Git、部署、文档和证据链均可从页面访问。
- 计划、实施、验证、实装四轴独立,rdev、dev ahead、main events 分叉样本通过。
- Agent 认领与可观测活动分开,Herdr 工程 Agent 与产品 PI Agent Runner 不混称。
- 所有 drift、degraded、stale 都带来源和时间,不存在未经定义的综合绿灯。
- 默认 loopback、Host/Origin/startup token、只读命令、路径边界、脱敏、CSP 和 Markdown 安全测试通过。
- 首次加载、空数据、部分失败、无缓存失败、恢复、键盘、窄屏和 URL 深链验收通过。
- 导出 HTML 脱离仓库可读 Markdown,且不包含二进制 assets 或凭证数据。
- 单元、集成、全仓短测、浏览器验收和
git diff --check均有真实输出。 .doc/test-reports报告回链任务文,FEATURE-MATRIX 与 CURRENT 按实际状态更新。- 没有遗留调试入口、写操作按钮、未使用的替代模型或与产品后台重名的组件。
Appendix
一期交付边界
一期交付:本地只读服务、版本化快照 JSON、架构/任务/Git/部署/文档视图、四轴状态、drift/degraded、全文搜索、安全文档阅读和单 HTML 导出。
后续评估:跨快照历史趋势、远端托管/CI 聚合、受限富文本与 Mermaid、跨仓库聚合、面向 Agent 的筛选查询 API。
永久排除:在页面中修改文档、切换或推送分支、控制 Agent、执行部署、读取密钥、成为产品后台模块。
方案依据
.doc/README.md定义的文档 taxonomy 与生命周期;.doc/ops/CURRENT.md的焦点、认领、集成槽与环境声明;.doc/status/FEATURE-MATRIX.md的模块完成度口径;.doc/remediation/gap-matrix.md的发布门禁口径;.doc/system-design/README.md与模块边界清单;- Git/worktree、Docker/Compose、
/ready和 promotion receipts 的当前可观测能力。