Files
Agent-System/.doc/archive/design/2026-09-17-personal-engineering-control-center-plan.md
T
weichenandCursor 14f75df1ac refactor: remove Control Center from this repository
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>
2026-09-19 03:40:00 +00:00

33 KiB
Raw Blame History

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 在哪里、各环境实际运行了什么,并能在两次点击内到达对应的设计、审计、整改、任务和测试材料。

中控台同时提供两种输出:

  1. serve:持续采集本地仓库、Git 和运行环境,提供自动刷新的 HTML 页面与机器可读 JSON;
  2. 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,不输出统一绿灯。

真实验收样本

  1. rdev:存在调研、设计、任务与 backlog,但若没有 CURRENT 认领和真实分支,应显示“已计划、未认领、未实施、未实装”。
  2. main 环境:若 CURRENT 声明整体 healthy,而 events 容器实际 restarting、应用 /ready 仍为 ok,应同时显示三项证据与 drift。
  3. 本地 dev:若分支领先 origin/dev,必须显示“本地已具备、远端未确认可用”,不得写成已远程发布。
  4. system-admin-console:作为产品管理后台能力,与本计划的个人工程中控台分开展示,名称和边界不得混淆。

安全与非目标

一期明确不做:

  • 不写文档,不修改任务状态,不占用集成槽;
  • 不创建、切换、合并、删除或推送 Git 分支;
  • 不执行 git fetch,不调用远端托管平台 API;
  • 不启动、停止、重建或部署容器;
  • 不控制 Herdr 或向 Agent 派发任务;
  • 不读取 .env、.secrets、Docker Config.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.go
  • internal/engineeringdashboard/model_test.go
  • internal/engineeringdashboard/testdata/**

实施要点:

  1. 定义版本化 Snapshot、SourceState、Fact、Conflict、TaskState、AgentClaim、EnvironmentState。
  2. provenance 固定为 declared|observed|verified|inferred;freshness 固定为 fresh|stale|error|unknown。
  3. 状态使用可组合 facets:Git 分为 branch/worktree/merge/cleanliness/ahead-behind;验证分为 result/freshness/subject identity;部署分为 container/readiness/services/artifact identity。
  4. TaskState 保留 owner、agent kind、claim、mutex、声明分支、观测 worktree、最近活动时间及证据;声明与观测不可互相提升。
  5. 建立 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.go
  • internal/engineeringdashboard/docs_test.go

实施要点:

  1. 扫描 allowlist 内 Markdown,默认跳过任何 assets 目录正文;记录附件元数据。
  2. 解析 front matter、标题、显式 Markdown 链接和反向链接。
  3. 为 CURRENT、FEATURE-MATRIX、gap-matrix、任务文、module boundaries 和 test report 建立专用适配器;receipt 只在文档图谱中作为文档与链接,结构化解析归 U4。
  4. 区分 broken、orphan、unindexed;slug 相似只形成候选关系。
  5. 规范化路径并阻止 ..、绝对路径和任何 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.go
  • internal/engineeringdashboard/git_test.go

实施要点:

  1. 抽象 command runner,固定 argv、工作目录、超时和输出上限。
  2. 收集当前分支/HEAD、dirty/untracked、local/remote-tracking refs、ahead/behind、merge-base 和 worktree。
  3. 不执行 fetch;remote tracking ref 始终带本地观测时间与免责声明。
  4. 对账任务声明的 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.go
  • internal/engineeringdashboard/runtime_test.go

实施要点:

  1. 从仓库内批准的 Compose 静态配置和 allowlist labels 映射环境与服务;无法明确映射时显示 unknown,不用名称猜测。容器 JSON 只提取容器名、image/digest、状态、restart count、health,以及 allowlist 内的 Compose project/service labels;不复制 Env、Mounts、完整 NetworkSettings 或任意 labels。
  2. 对 allowlist 中的本地 /ready 端点执行短超时、响应大小受限的请求;禁用重定向,或对每一跳重新校验 scheme、解析后 IP、端口和 host。
  3. 解析 promotion receipt/candidate image 等仓库证据,保留 artifact identity。
  4. 将 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.go
  • internal/engineeringdashboard/reconcile_test.go

实施要点:

  1. 按领域 SSOT 规则构建 module、task、environment 和 evidence-chain 视图。
  2. 实现 conflict 分类:declared-vs-observed、task-vs-git、test-vs-subject、receipt-vs-runtime、stale-source、missing-evidence。
  3. 快照构建期间每个来源独立记录 observed_at、持续时间和错误;成功后一次性发布。
  4. 失败源只可复用同一 serve 进程的 last-known,并标注 stale、age 与 last-success;冷启动无缓存时为 unknown/error。过期数据不隐藏,但按年龄提升告警级别。
  5. 测试报告只有在 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.go
  • internal/engineeringdashboard/server_test.go
  • internal/engineeringdashboard/assets/index.html
  • internal/engineeringdashboard/assets/app.js
  • internal/engineeringdashboard/assets/app.css
  • cmd/engineering-dashboard/main.go

实施要点:

  1. serve --repo <path> --addr 127.0.0.1:<port>;一期无条件拒绝所有非 loopback 地址,包括通配、IPv6 非 loopback 和显式传入值。
  2. 暴露 /api/v1/snapshot、/api/v1/doc/<id>、/healthz;所有接口只读。严格校验 Host/Origin/Fetch Metadata,不信任代理转发头;页面和 API 使用每次启动生成的不可预测访问令牌,降低 DNS rebinding 与跨站读取风险。
  3. 页面分为总览、架构/模块、任务、Git、部署、文档和证据链。
  4. 自动刷新完整快照,保留当前筛选、滚动位置、焦点和选中文档;ETag 未变化时不重绘。
  5. 明确一级视图状态:initial loading、fresh empty、fresh success、partial/degraded with last-known、hard error without cache、refreshing、recovered。刷新中继续展示上一完整快照,直到下一版本原子替换。
  6. 搜索覆盖标题、仓库相对路径、front matter 和未截断正文;不同维度用 AND、同一维度多选用 OR,默认先排当前任务和异常证据,再按匹配度与路径稳定排序。筛选、查询和选中文档写入 URL 参数,支持浏览器前进/后退与深链。
  7. 桌面优先;窄屏下侧栏变为可关闭抽屉,宽表格保留可横向滚动的语义表头,详情区单列。所有功能可键盘完成,使用 landmark/标题/表格语义,drift/degraded 不只靠颜色表达,自动刷新通过非打断式 live region 报告且不抢焦点。
  8. 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.go
  • internal/engineeringdashboard/export_test.go
  • scripts/engineering-dashboard.sh
  • .doc/status/FEATURE-MATRIX.md
  • .doc/ops/CURRENT.md
  • .doc/test-reports/YYYY-MM-DD-engineering-dashboard-test-report.md

实施要点:

  1. export --repo <path> --output <file> 构建一次不可变快照并原子写入;首次采集失败的来源显示 unknown/error。
  2. 以 HTML-safe JSON/等价编码内嵌允许的 Markdown 正文、索引和页面资源;附件保持元数据与相对链接,所有正文只写入文本节点。
  3. 默认权限 0600,输出页显示生成时间、repo、HEAD、snapshot ID 和 degraded/drift。
  4. 薄脚本只负责定位仓库与调用 Go CLI,不隐藏参数或执行安装/部署副作用。
  5. 实施期间按仓库规范更新 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 与输出脱敏。

浏览器验收

  1. 从总览进入 rdev,确认“计划/实施/验证/实装”四轴与源文档链接均可见。
  2. 在仓库外复制导出 HTML,断网打开并全文搜索、阅读至少一份设计与一份测试报告。
  3. 制造 fixture 中的 CURRENT/Docker/readiness 冲突,确认页面保留多值且不出现综合绿灯。
  4. 切换 fixture 快照,确认页面刷新后筛选条件和当前文档保持不变。
  5. 尝试路径穿越、未知文档、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 的当前可观测能力。