diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d2f8c674..b4b86286 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,4 +1,4 @@ -name: Docs checks +name: Documentation on: push: @@ -11,24 +11,55 @@ on: paths: - 'docs/**' - '.github/workflows/docs.yml' + workflow_dispatch: permissions: contents: read +concurrency: + group: pages + cancel-in-progress: true + jobs: build: - name: Docusaurus build + name: Build Docusaurus site runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: 20 + cache: npm + cache-dependency-path: docs/package-lock.json + - name: Install website dependencies working-directory: docs run: npm ci + - name: Build documentation working-directory: docs run: npm run build env: DOCUSAURUS_BASE_URL: /Persisting/ + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/build + + deploy: + name: Deploy documentation + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index d51bb431..928a0abe 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -129,7 +129,6 @@ jobs: - name: Setup Build Environment uses: ./.github/actions/setup-build-env - with: - name: Install hyperfine uses: taiki-e/install-action@v2 diff --git a/README.md b/README.md index 36676c7e..88d80a25 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Persisting +# Persisting Persisting **Persistent infrastructure for the Agent era.** @@ -6,6 +6,8 @@ [![Documentation](https://img.shields.io/badge/docs-latest-blue)](https://deeplink-org.github.io/Persisting/) [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) +Persisting logo + Persisting connects durable model state—parameters and KV caches—with durable Agent history—trajectories and execution records. The current product is the path from execution to queryable history: diff --git a/docs/src/en/pchronicle/index.md b/docs/src/en/pchronicle/index.md index 63032fdc..5900d4d0 100644 --- a/docs/src/en/pchronicle/index.md +++ b/docs/src/en/pchronicle/index.md @@ -1,5 +1,7 @@ # pChronicle +pChronicle logo + **pChronicle is an Agent trajectory storage engine.** Use it to browse, query, exchange, and serve run Datasets produced by Persisting or by supported external formats; pChronicle does not require pVisor to run. diff --git a/docs/src/en/pvisor/index.md b/docs/src/en/pvisor/index.md index 79010abd..d8565e65 100644 --- a/docs/src/en/pvisor/index.md +++ b/docs/src/en/pvisor/index.md @@ -1,5 +1,7 @@ # pVisor +pVisor logo + **pVisor runs an existing Agent command inside a controlled execution environment.** It gives each Run its own workspace boundary, records the controls that were actually installed, and lets you review filesystem changes diff --git a/docs/src/zh/pchronicle/index.md b/docs/src/zh/pchronicle/index.md index 12d1d387..60930cf7 100644 --- a/docs/src/zh/pchronicle/index.md +++ b/docs/src/zh/pchronicle/index.md @@ -1,5 +1,7 @@ # pChronicle +pChronicle logo + **pChronicle 是 Agent 轨迹存储引擎。** 用于浏览、查询、交换和服务运行 Dataset;既可以读取 Persisting 产生的运行记录,也可以直接读取受支持的外部格式;不要求先运行 pVisor。 diff --git a/docs/src/zh/pvisor/index.md b/docs/src/zh/pvisor/index.md index fc114fe5..da946f5a 100644 --- a/docs/src/zh/pvisor/index.md +++ b/docs/src/zh/pvisor/index.md @@ -1,5 +1,7 @@ # pVisor +pVisor logo + **pVisor 在受控执行环境中运行现有的 Agent 命令。** 它为每个 Run 提供独立的工作区边界, 记录实际生效的控制机制,并让你在文件变更进入项目之前先进行审查。 diff --git a/docs/static/img/logos/pchronicle-icon.png b/docs/static/img/logos/pchronicle-icon.png new file mode 100644 index 00000000..60e5be09 Binary files /dev/null and b/docs/static/img/logos/pchronicle-icon.png differ diff --git a/docs/static/img/logos/persisting-icon.png b/docs/static/img/logos/persisting-icon.png new file mode 100644 index 00000000..2fd10f23 Binary files /dev/null and b/docs/static/img/logos/persisting-icon.png differ diff --git a/docs/static/img/logos/pvisor-icon.png b/docs/static/img/logos/pvisor-icon.png new file mode 100644 index 00000000..44e0a743 Binary files /dev/null and b/docs/static/img/logos/pvisor-icon.png differ diff --git a/docs/superpowers/plans/2026-08-30-docs-polish.md b/docs/superpowers/plans/2026-08-30-docs-polish.md deleted file mode 100644 index 875c17ec..00000000 --- a/docs/superpowers/plans/2026-08-30-docs-polish.md +++ /dev/null @@ -1,743 +0,0 @@ -# 文档体系打磨实施计划 - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** 将 Persisting 的 README 与文档体系打磨至顶级开源项目水平,移除令人困惑的文档,为对外发布与增长拉新做准备。 - -**Architecture:** 三层信息架构——顶层 README 负责快速吸引(uv/Ruff 风格),MkDocs 文档站负责分层深入(Overview → Get Started → Concepts → Guides → Design → Reference 契约),组件 README 面向贡献者。遗留重定向桩统一归档至 `docs/archive/legacy-nav/`,pPilot 三页孤立内容接入导航成为第三个产品小节。 - -**Tech Stack:** MkDocs Material + i18n 插件(en/zh 双语,`file.md` / `file.zh.md` 后缀约定)、just(`docs-build` / `docs-links`)、git mv 保留历史。 - -**Spec:** `docs/superpowers/specs/2026-08-30-docs-polish-design.md`(已获用户确认) - -## Global Constraints - -- **AGENTS.md 排除范围**:TTAS、Queue 及 sampler、Search、`persisting-dlcapt` 的文档**内容不修改、不翻译、不重构**。涉及文件:`docs/src/guide/queue.md(.zh.md)`、`docs/src/guide/custom-backends.md(.zh.md)`、`docs/src/api/index.md`、`docs/src/api/queue.md`、`crates/persisting-dlcapt/README.md`。这些文件仅允许随导航/构建健康做最小位移,本轮实际不动。 -- **双语约定**:每个面向用户的页面必须有 `.zh.md` 中文版本;**例外**:`docs/src/rfcs/` 下除 `index.md` 外的 RFC 正文保持英文(ADR 惯例,用户已确认),Queue 排除项保持现状。 -- **术语一致性**:中文译文遵循 `docs/mkdocs.yml` 的 `nav_translations` 与现有译文惯例(Run、Effect、Dataset、Capture 等术语保留英文)。 -- **验证基线**:每个结构性改动后运行 `just docs-build && just docs-links`(strict),必须零警告通过。 -- **README 自动化标记**:`README.md` 中的 `` / `` 块由 `benchmark/pchronicle/bench.py` 自动更新,**必须原样保留标记**。 -- **重定向桩模板**:`template: redirect.html` 来自 Material 主题(`material/templates/redirect.html`),frontmatter 用 `location: <相对URL>`。 -- **交付**:单 PR,每个 Task 一个 commit;commit message 遵循仓库现有风格(观察:`Refactor documentation to ...`、`feat: ...`)。 -- **文档源事实顺序**(来自 docs/README.md):`--help` 输出 > 用户指南/命令参考 > 架构页 > RFC > 研究笔记。命令示例必须与二进制 `--help` 一致。 - ---- - -### Task 1: 提交规格、归档遗留文档、修复 site_url - -**Files:** -- Create: `docs/archive/legacy-nav/`(接收 38 个文件) -- Modify: `docs/mkdocs.yml`(site_url) -- Modify: `docs/archive/README.md` -- Delete: `docs/product/`(空目录) -- Move: `docs/pchronicle-design-review.md` → `docs/superpowers/reviews/2026-08-23-pchronicle-design-review.md` - -- [ ] **Step 1: 提交规格与计划文档** - -```bash -cd /Users/reiase/workspace/Persisting -git add docs/superpowers/specs/2026-08-30-docs-polish-design.md docs/superpowers/plans/2026-08-30-docs-polish.md -git commit -m "docs: add documentation polish spec and implementation plan" -``` - -- [ ] **Step 2: 归档重定向桩** - -```bash -cd /Users/reiase/workspace/Persisting/docs -mkdir -p archive/legacy-nav -git mv src/design archive/legacy-nav/design -git mv src/dev archive/legacy-nav/dev -git mv src/quickstart.md archive/legacy-nav/quickstart.md -# guide/ 下仅移动重定向桩,保留 queue 与 custom-backends 内容页 -mkdir -p archive/legacy-nav/guide -cd src/guide -git mv capture.md capture.zh.md examples.md examples.zh.md history.md history.zh.md \ - index.md index.zh.md orchestrate.md orchestrate.zh.md overlaynet.md overlaynet.zh.md \ - pvisor-execution.md pvisor-execution.zh.md review-apply.md review-apply.zh.md \ - ../../archive/legacy-nav/guide/ -``` - -- [ ] **Step 3: 删除空目录、归位评审文档** - -```bash -cd /Users/reiase/workspace/Persisting/docs -rm -f product/.DS_Store && rmdir product -git mv pchronicle-design-review.md superpowers/reviews/2026-08-23-pchronicle-design-review.md -``` - -- [ ] **Step 4: 修复 mkdocs.yml 的 site_url** - -```yaml -# docs/mkdocs.yml 第 4 行 -site_url: https://deeplink-org.github.io/Persisting/ -``` - -- [ ] **Step 5: 更新 docs/archive/README.md** - -在现有内容后追加: - -```markdown - -## legacy-nav/ - -Redirect stubs from the pre-restructure `/design/`, `/guide/`, `/dev/`, and -`/quickstart` URL space. The current navigation under `pvisor/`, `pchronicle/`, -`ppilot/`, `project/`, and `system-design/` has absorbed their targets, so the -stubs no longer serve external links. Archived 2026-08-30; excluded from the -MkDocs build because they live outside `src/`. -``` - -- [ ] **Step 6: 验证构建** - -Run: `just docs-build && just docs-links` -Expected: 零警告通过;`docs/site/` 中不再生成 `design/`、`dev/`、`quickstart.html` 页面(`guide/` 仍生成 queue 与 custom-backends 两页)。 - -- [ ] **Step 7: Commit** - -```bash -git add -A docs/ -git commit -m "docs: archive legacy redirect stubs and fix mkdocs site_url" -``` - ---- - -### Task 2: pPilot 接入文档站导航 - -**Files:** -- Move: `docs/src/pvisor/guides/orchestrate.md(.zh.md)` → `docs/src/ppilot/guides/orchestrate.md(.zh.md)` -- Move: `docs/src/pvisor/design/orchestration.md` → `docs/src/ppilot/design/orchestration.md` -- Move: `docs/src/pvisor/reference/ppilot-cli.md` → `docs/src/ppilot/reference/cli.md` -- Create: `docs/src/ppilot/index.md`、`docs/src/ppilot/get-started.md` -- Modify: `docs/mkdocs.yml`(nav + nav_translations) - -**Interfaces:** -- Produces: `ppilot/index.md`、`ppilot/get-started.md` 的英文定稿——Task 8 据此翻译中文版本。 - -- [ ] **Step 1: 移动文件** - -```bash -cd /Users/reiase/workspace/Persisting/docs/src -mkdir -p ppilot/guides ppilot/design ppilot/reference -git mv pvisor/guides/orchestrate.md pvisor/guides/orchestrate.zh.md ppilot/guides/ -git mv pvisor/design/orchestration.md ppilot/design/ -git mv pvisor/reference/ppilot-cli.md ppilot/reference/cli.md -``` - -- [ ] **Step 2: 查找并修复入链** - -Run: `rg -n "orchestrate|orchestration|ppilot-cli" docs/src --type md -g '!ppilot/**'` -对每一处指向旧路径的链接,改为新的 `ppilot/...` 相对路径。被移动文件内部的相对链接(如 `ppilot/reference/cli.md` 中的 `../../pchronicle/reference/cli.md`)深度不变,保持有效;逐一打开三个被移动文件确认链接仍然正确。 - -- [ ] **Step 3: 新写 `docs/src/ppilot/index.md`** - -```markdown -# pPilot - -**Durable Run production at scale.** - -pPilot extends the Run model from one execution to a bounded collection of -tasks. It owns planning, bounded concurrency, leases and fencing decisions, -infrastructure retry and recovery, reconciliation, durable result publication, -and task-to-Run mapping. - -It does not redefine the Agent runtime: each task remains an independent -[pVisor Run](../pvisor/concepts/run-model.md), executed by the standalone -`pvisor` binary. - -| Command | Owns | -| --- | --- | -| `ppilot run` | execute a `plan()` / `execute(item)` workload with durable recovery | -| `ppilot produce` | create independent pVisor Runs from a streaming planner | - -## Where to start - -- [Get Started](get-started.md) — run your first parallel plan in five minutes -- [Orchestrate many Agent Runs](guides/orchestrate.md) — planning, workers, resume, and sinks -- [Orchestration design](design/orchestration.md) — leases, fencing, and recovery guarantees -- [pPilot CLI reference](reference/cli.md) — exact flags and exit behavior -``` - -- [ ] **Step 4: 新写 `docs/src/ppilot/get-started.md`** - -```markdown -# Get Started with pPilot - -This page runs the shortest verified pPilot loop: a streaming Python plan -executed by multiple workers, with terminal results written to a durable sink. - -## Install - -pPilot ships in the same component set as `pvisor` and `pchronicle`. From a -source checkout: - -```bash -git clone https://github.com/DeepLink-org/Persisting.git -cd Persisting -just install-cli -ppilot --version -``` - -## Define the work - -Create `plan.py`: - -```python -def plan(): - for value in range(6): - yield {"id": f"square-{value}", "value": value} - - -def execute(item): - return {"square": item["value"] ** 2} -``` - -`plan()` yields work items with stable `id`s; `execute(item)` processes one -item. Stable identity lets an interrupted job resume without repeating -completed work. - -## Run it - -```bash -ppilot run plan.py --workers 2 --per-worker 2 --sink ./results --results ndjson -``` - -## Verify the durable result - -```bash -cat ./results/ready.ndjson -``` - -Expected: six result records, one per task, with squares 0, 1, 4, 9, 16, 25 -(sum 55). A scripted version of this loop lives in -[`examples/ppilot/01-run/`](https://github.com/DeepLink-org/Persisting/tree/main/examples/ppilot/01-run). - -## Where to go next - -- [Orchestrate many Agent Runs](guides/orchestrate.md) — resume, retries, and production sinks -- [pPilot CLI reference](reference/cli.md) — `run` and `produce` flags -``` - -(注:实施时先实际运行一次该示例确认输出格式与 `ready.ndjson` 路径准确——`just install-cli` 后在临时目录执行上述命令。) - -- [ ] **Step 5: 更新 mkdocs.yml 导航** - -在 `nav:` 的 pVisor 小节之后、pChronicle 之前插入: - -```yaml - - pPilot: - - Overview: ppilot/index.md - - Get Started: ppilot/get-started.md - - Guides: - - Orchestrate many Agent Runs: ppilot/guides/orchestrate.md - - Design: - - Orchestration architecture: ppilot/design/orchestration.md - - Reference: - - pPilot CLI: ppilot/reference/cli.md -``` - -在 `nav_translations` 的 zh 段追加(`Overview`/`Get Started`/`Guides`/`Design`/`Reference` 已有翻译,勿重复添加): - -```yaml - Orchestrate many Agent Runs: 编排多个 Agent Run - Orchestration architecture: 编排架构 - pPilot CLI: pPilot CLI -``` - -- [ ] **Step 6: 验证** - -Run: `just docs-build && just docs-links` -Expected: 零警告;导航中出现 pPilot 小节;无指向旧路径的死链。若 strict 构建报告其他页面对旧路径的入链,修复链接;仅当某旧 URL 有外部收录风险时才在原位置留 redirect 桩(默认不留)。 - -- [ ] **Step 7: Commit** - -```bash -git add -A docs/ -git commit -m "docs: add pPilot section to site navigation" -``` - ---- - -### Task 3: 重写顶层 README(uv/Ruff 风格) - -**Files:** -- Modify: `README.md`(整体重写) - -- [ ] **Step 1: 核实 PyPI 发布状态** - -Run: `curl -fsSL https://pypi.org/pypi/persisting/json | head -c 200` -Expected: 返回 JSON 则已发布,README 加 PyPI 徽章;404 则不加(避免死徽章),并在 Step 2 中跳过对应行。 - -- [ ] **Step 2: 写入新 README** - -完整替换 `README.md` 为以下内容(若 Step 1 确认已发布 PyPI,在徽章行追加 -`[![PyPI](https://img.shields.io/pypi/v/persisting.svg)](https://pypi.org/project/persisting/)`): - -```markdown -# Persisting - -**Persistent infrastructure for the Agent era.** - -[![CI](https://github.com/DeepLink-org/Persisting/actions/workflows/ci.yml/badge.svg)](https://github.com/DeepLink-org/Persisting/actions/workflows/ci.yml) -[![Documentation](https://img.shields.io/badge/docs-latest-blue)](https://deeplink-org.github.io/Persisting/) -[![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) - -Persisting connects durable model state—parameters and KV caches—with durable -Agent history—trajectories and execution records. The current product provides -two commands: - -- **`pvisor`** runs one Agent in a controlled environment and lets you review - its effects before accepting them; -- **`pchronicle`** browses, queries, exchanges, and serves trajectory Datasets. - -Each works on its own; together they preserve a path from execution to -queryable history. - -![Current Persisting workflows and optional integration](docs/src/assets/diagrams/persisting/system-products.svg) - -## Install - -```bash -pip install persisting[lance] -pvisor --version -pchronicle --version -``` - -The rolling nightly build installs the same commands without a Rust toolchain: - -```bash -curl -fsSL https://raw.githubusercontent.com/DeepLink-org/Persisting/main/scripts/install-nightly.sh | bash -``` - -See the [installation guide](https://deeplink-org.github.io/Persisting/installation/) -for platform requirements and executor setup. - -## Run one Agent and review its changes - -```bash -pvisor run --safe codex -pvisor review last -pvisor apply last --all # or: pvisor drop last -``` - -`--safe` stages workspace changes; nothing enters your project tree before you -accept it. The exact boundary is platform-dependent and recorded with the -Run—consult the [execution guide](https://deeplink-org.github.io/Persisting/pvisor/guides/execution/) -before treating it as a security boundary. - -## Query Agent trajectory history - -```bash -pchronicle onboard -pchronicle onboard query -pchronicle agent codex ./trajectory-data --ask "Which tools fail most often?" -``` - -The onboarding flow creates a temporary example Dataset—no source checkout -required. `pchronicle import` accepts ATIF, ACTF, and OpenAI Messages; -`pchronicle serve` starts a loopback-only, read-only Dataset UI and API. - -## Current maturity - -| Capability | Status | -|---|---| -| pVisor host execution, review, checkpoints, and transactional workspace | Implemented | -| pChronicle local/S3 catalog, bounded SQL, analysis, find, import/export | Implemented | -| pChronicle loopback-only read API and embedded Web UI | Implemented | -| Gateway capture and cooperative proxy policy | Implemented | -| Container/libkrun executors and transparent network boundaries | Platform-dependent; see the pVisor and OverlayNet docs | -| Queue and document Search | Separate stable capabilities | -| Tensor Memory / TTAS | Experimental | - -## Documentation - -- [Choose a workflow](https://deeplink-org.github.io/Persisting/overview/) — pick the entry point that matches your task -- [Run your first Agent](https://deeplink-org.github.io/Persisting/pvisor/get-started/) — the run-review-apply loop -- [Explore durable history](https://deeplink-org.github.io/Persisting/pchronicle/get-started/) — browse and query a trajectory Dataset -- [Project architecture](https://deeplink-org.github.io/Persisting/system-design/) — ownership and delivery boundaries - -Criterion.rs microbenchmarks and hyperfine lifecycle scenarios are compared -against `main` in CI; see the [benchmark contract](benchmark/pchronicle/README.md). - - -No nightly benchmark has been published with the unified report format yet. - - -## License - -[Apache License 2.0](LICENSE). See [`NOTICE`](NOTICE) for third-party -attributions and separately licensed bundled components. -``` - -注意:benchmark 标记块原样保留(含当前占位文本);`bench.py` 会更新其内容。 - -- [ ] **Step 3: 验证链接与命令** - -- 逐一核对 README 中的命令与 `--help`:`pvisor run --help`、`pvisor review --help`、`pvisor apply --help`、`pchronicle onboard --help`、`pchronicle agent --help`; -- 确认 4 个文档站 URL 路径与 `docs/src/` 实际页面一致(`overview/`、`pvisor/get-started/`、`pchronicle/get-started/`、`system-design/`)。 - -- [ ] **Step 4: Commit** - -```bash -git add README.md -git commit -m "docs: rewrite top-level README for first-time evaluators" -``` - ---- - -### Task 4: 文档站入口层打磨(中英同步) - -**Files:** -- Modify: `docs/overrides/home.html`、`docs/src/overview.md(.zh.md)`、`docs/src/installation.md(.zh.md)`、`docs/src/pvisor/get-started.md(.zh.md)`、`docs/src/pchronicle/get-started.md(.zh.md)` - -**Interfaces:** -- Consumes: Task 3 移除的 "Command ownership" 表(迁入 `overview.md`)。 - -- [ ] **Step 1: overview.md 吸收 Command ownership 表** - -在 `overview.md` 的 "Current user workflows" 表格之后插入(中英两版同步): - -```markdown -## Command ownership - -| Command | Primary responsibility | -|---|---| -| `pvisor` | One Run, environments, review, checkpoints, apply/drop | -| `ppilot` | Bounded collections of Runs: planning, concurrency, recovery, sinks | -| `pchronicle` | Dataset catalog, SQL, built-in analysis, find, import/export, read-only serving | -``` - -中文版(`overview.zh.md` 对应位置): - -```markdown -## 命令分工 - -| 命令 | 主要职责 | -|---|---| -| `pvisor` | 单个 Run、执行环境、审查、检查点、apply/drop | -| `ppilot` | 成组的 Run:规划、并发、恢复、结果汇聚 | -| `pchronicle` | Dataset 目录、SQL、内建分析、find、导入导出、只读服务 | -``` - -- [ ] **Step 2: home.html 首页检查** - -以首次评估者视角审读 `docs/overrides/home.html`:hero 文案与 README 新定位保持一致;三个 CTA 按钮目标有效;四个版块(工作流 / 五分钟上手 / 整体关系 / 继续阅读)链接全部指向存活页面。仅在发现不一致时修改,不为改而改。 - -- [ ] **Step 3: installation.md 审计** - -- 核对 `pip install persisting[lance]` 与 README 一致; -- 核对 macFUSE、libkrun、Zig 等平台要求仍然准确(对照 `justfile` 与 `crates/persisting-pvisor` 构建逻辑); -- 确认页面未提及 `ppilot` 安装——在 "CLI component set" 一节补充一句:ppilot 经 `just install-cli` 从源码安装(中英同步)。 - -- [ ] **Step 4: 两个 get-started 审计** - -`pvisor/get-started.md` 与 `pchronicle/get-started.md`:按 Get Started 契约(最短可验证成功循环、步骤可复制执行、每步有预期结果)逐行审读;实际执行其中的命令序列验证可用性;中英两版同步修订发现的问题。 - -- [ ] **Step 5: 验证 + Commit** - -Run: `just docs-build && just docs-links` - -```bash -git add -A docs/ -git commit -m "docs: polish entry-layer pages for first-time evaluators" -``` - ---- - -### Task 5: pVisor 文档区审计 - -**Files:** -- Audit: `docs/src/pvisor/` 全部页面(index、get-started、concepts×4、guides×5、design×3、reference×2,及各自已有 `.zh.md`) - -- [ ] **Step 1: 逐页应用文章类型契约** - -对每一页核对(契约全文见 `docs/README.md` "Each article type has one job" 表): - -| 检查项 | 动作 | -|---|---| -| 页面是否只回答该类型该回答的问题 | 越界内容移至正确类型页面或删除 | -| 命令示例与 `--help` 输出一致 | 运行 `pvisor --help` 逐一核对,修正漂移 | -| 有回链(owning concept/workflow)与前链(下一层) | 缺则补 | -| Design 页中 roadmap/target 内容有显式标注 | 缺则加 `!!! note "Target architecture"` admonition | -| 中英两版内容同步 | 英文改动同步进 `.zh.md`(本任务只改已有中文版的页面) | - -pVisor 命令核对清单:`pvisor run`、`review`、`apply`、`drop`、`checkpoint`(以 `pvisor --help` 实际输出为准增减)。 - -- [ ] **Step 2: 验证 + Commit** - -Run: `just docs-build && just docs-links` - -```bash -git add -A docs/src/pvisor/ -git commit -m "docs: audit pVisor section against article-type contract" -``` - ---- - -### Task 6: pChronicle 文档区审计 - -**Files:** -- Audit: `docs/src/pchronicle/` 全部页面(index、get-started、concepts×3、guides×6、design×5、reference×6,及各自已有 `.zh.md`) - -- [ ] **Step 1: 逐页应用文章类型契约** - -同 Task 5 的检查表。pChronicle 命令核对清单:`pchronicle onboard`、`import`、`export`、`agent`、`serve`、`find`、`query`(以 `pchronicle --help` 实际输出为准)。特别注意: - -- `reference/cli.md` 与 `--help` 逐条对齐(这是参考页的核心职责); -- `reference/query-model.md` 与 RFC-0012 的 find 语法一致性(以代码实现为准,RFC 仅历史参考); -- `guides/serve-gateway.md` 中 Gateway 转发/改写/捕获描述与 `crates/persisting-gateway` 实际行为一致。 - -- [ ] **Step 2: 验证 + Commit** - -Run: `just docs-build && just docs-links` - -```bash -git add -A docs/src/pchronicle/ -git commit -m "docs: audit pChronicle section against article-type contract" -``` - ---- - -### Task 7: Project、System Design 与 RFC 索引审计 - -**Files:** -- Audit: `docs/src/project/`(4 页)、`docs/src/system-design/`(4 页)、`docs/src/rfcs/index.md` - -- [ ] **Step 1: 逐页审计** - -- `project/`:engineering/releasing/examples 面向贡献者,核对命令(`just test`、`just docs-*`、发布流程)与 `justfile`、`.github/workflows/release.yml` 实际一致; -- `system-design/`:四页只回答"哪个产品拥有哪个跨产品对象/转移/失败",发现与产品页重复的实现细节则改为链接; -- `rfcs/index.md`:确认 0001–0013 索引完整(注意无 0011)、状态标注准确;在页面说明 RFC 为历史决策记录、非命令参考(英文版已有则说明一致,中文版在 Task 8 补译时体现)。 - -- [ ] **Step 2: 验证 + Commit** - -Run: `just docs-build && just docs-links` - -```bash -git add -A docs/src/project/ docs/src/system-design/ docs/src/rfcs/index.md -git commit -m "docs: audit project, system-design, and RFC index pages" -``` - ---- - -### Task 8: 双语补译 - -**Files:** -- Create(12 个 `.zh.md`): - - `docs/src/pvisor/design/gateway.zh.md` - - `docs/src/pvisor/design/isolation.zh.md` - - `docs/src/pvisor/design/overlaynet.zh.md` - - `docs/src/pvisor/reference/cli.zh.md` - - `docs/src/ppilot/index.zh.md` - - `docs/src/ppilot/get-started.zh.md` - - `docs/src/ppilot/guides/orchestrate.zh.md`(已存在——从 pvisor 移动而来,核对链接即可,不重译) - - `docs/src/ppilot/design/orchestration.zh.md` - - `docs/src/ppilot/reference/cli.zh.md` - - `docs/src/pchronicle/reference/agenticmd.zh.md` - - `docs/src/project/engineering.zh.md` - - `docs/src/project/releasing.zh.md` - - `docs/src/rfcs/index.zh.md` - -**Interfaces:** -- Consumes: Task 2 的 `ppilot/index.md`、`ppilot/get-started.md` 英文定稿;Task 5–7 审计后的英文定稿。 - -**反向对齐(Task 6 审计发现)**:以下 4 个页面的 `.md`(英文位)当前实为全中文内容,与 `.zh.md` 完全相同。本任务需将 `.md` **重写为地道英文**(以 `.zh.md` 为中文源,`.zh.md` 本身不动): -- `docs/src/pchronicle/design/catalog.md` -- `docs/src/pchronicle/design/trajectory-storage.md` -- `docs/src/pchronicle/design/storyline-lance.md` -- `docs/src/pchronicle/reference/agenticmd.md` - -- [ ] **Step 1: 翻译 pPilot 与 pVisor 页面** - -翻译规范: -- 术语保留英文:Run、Effect、Dataset、Capture、Gateway、OverlayFS、OverlayNet、lease、fencing、sink; -- 代码块、命令、文件路径不翻译; -- frontmatter 与相对链接保持与英文版一致(链接目标不本地化); -- 参照 `pvisor/guides/orchestrate.zh.md` 的既有风格。 - -- [ ] **Step 2: 翻译 pchronicle/project/rfcs 页面** - -`rfcs/index.zh.md` 中必须包含说明:RFC 正文保持英文,因为它们是历史决策快照,翻译会产生两个可能漂移的副本。 - -- [ ] **Step 3: 验证 + Commit** - -Run: `just docs-build && just docs-links`,并抽查 3 个页面的中文渲染(`just docs-serve` 或构建后检查 `docs/site/zh/` 下对应 HTML 存在)。 - -```bash -git add -A docs/src/ -git commit -m "docs: add Chinese translations for user-facing pages" -``` - ---- - -### Task 9: 组件 README 统一 - -**Files:** -- Modify(按模板套用,内容为精简对齐而非重写): - - crates(8 个):`persisting-agentctl`、`persisting-gateway`、`persisting-overlayfs`、`persisting-overlaynet`、`persisting-pchronicle`、`persisting-pchronicle-cli`、`persisting-ppilot`、`persisting-pvisor` 的 `README.md` - - examples(12 个):`examples/README.md`、`examples/data/README.md`、`examples/pchronicle/README.md` + 6 个子示例、`examples/ppilot/README.md` + 2 个子示例、`examples/pvisor/README.md` + 4 个子示例 - - benchmark(5 个):`benchmark/README.md`、`benchmark/gateway/README.md`、`benchmark/langfuse-pchronicle-review/README.md`、`benchmark/pchronicle/README.md`、`benchmark/pvisor/README.md` - - tests(3 个):`tests/regression/README.md`、`tests/regression/gateway-echo/README.md`、`tests/regression/gateway-fuzz/README.md` - - web(1 个):`pchronicle-web/README.md` -- 不动:`crates/persisting-dlcapt/README.md`(排除范围)、`crates/*/tests/fixtures/**/README.md`(fixture 数据说明)、`docs/`、`benchmark` 下非 README 文件 - -模板(按类型裁剪): - -```markdown -# <组件名> - -**<一句话职责>.** - -<边界段:拥有什么;不拥有什么(链向拥有者)。> - -## - -<命令或步骤> - -## Links - -- <文档站对应页或相邻组件> -``` - -- [ ] **Step 1: crates README(8 个)** - -逐一核对:一句话职责与 crate 实际边界一致(对照 `Cargo.toml` description 与代码);构建/测试命令可执行(如 `cargo build -p persisting-pvisor --bin pvisor`);链向文档站对应 Design 页。`persisting-ppilot/README.md` 已有较好的职责段,保留主体、补 Links 段。 - -- [ ] **Step 2: examples README(12 个)** - -每个示例 README 核对:`run.sh` 可执行、预期输出描述与实际一致(抽查 `examples/ppilot/01-run/run.sh` 与 `examples/pvisor/01-filesystem-isolation/run.sh`);顶部有一句话"问题:…可复现结论:…"(现有风格,保留并统一)。 - -- [ ] **Step 3: benchmark 与 tests README(8 个)** - -核对复现命令与 `justfile` 配方一致(`just benchmark-pvisor`、`just benchmark-gateway` 等);报告契约说明与 `benchmark/pchronicle/bench.py` 实际输出一致。 - -- [ ] **Step 4: pchronicle-web README** - -核对开发命令(`npm`/`pnpm` 脚本)与 `pchronicle-web/package.json` 一致;补边界段(embedded Web UI 的前端源,构建产物由 `persisting-pchronicle` 嵌入——以代码实际为准)。 - -- [ ] **Step 5: Commit** - -注意:工作区可能存在用户的未提交 WIP(如 `crates/persisting-pchronicle/src/`),**禁止 `git add -A crates/`**,只精确添加 README 文件: - -```bash -git add crates/*/README.md crates/persisting-gateway/tests/README.md \ - examples/ benchmark/ tests/regression/ pchronicle-web/README.md -git status --short # 确认暂存区只有 README 与 examples/benchmark/tests 文档改动 -git commit -m "docs: standardize component READMEs on ownership template" -``` - ---- - -### Task 10: i18n 检查脚本与最终验收 - -**Files:** -- Create: `scripts/check-docs-i18n.py` - -- [ ] **Step 1: 创建检查脚本** - -```python -#!/usr/bin/env python3 -"""Fail if any translatable docs page lacks a Chinese counterpart. - -RFC bodies (historical decision records) and Queue-subsystem pages -(out of documentation scope per AGENTS.md) are intentionally English-only. -""" -from pathlib import Path -import sys - -SRC = Path(__file__).resolve().parent.parent / "docs" / "src" - -EN_ONLY = { - "api/index.md", - "api/queue.md", - "guide/custom-backends.md", - "guide/queue.md", -} - -def is_translatable(rel: str) -> bool: - if rel in EN_ONLY: - return False - if rel.startswith("rfcs/") and rel != "rfcs/index.md": - return False - return True - -missing = [] -for page in sorted(SRC.rglob("*.md")): - if page.name.endswith(".zh.md"): - continue - rel = page.relative_to(SRC).as_posix() - if not is_translatable(rel): - continue - if not page.with_name(page.name[:-3] + ".zh.md").exists(): - missing.append(rel) - -if missing: - print("Missing Chinese translations:") - for rel in missing: - print(f" {rel}") - sys.exit(1) -print("All translatable pages have Chinese counterparts.") -``` - -- [ ] **Step 2: 运行脚本** - -Run: `python3 scripts/check-docs-i18n.py` -Expected: `All translatable pages have Chinese counterparts.`(若有遗漏,回到 Task 8 补齐) - -- [ ] **Step 3: 最终验收清单** - -依次执行并确认: -1. `just docs-build` — 零警告; -2. `just docs-links` — strict 通过; -3. `python3 scripts/check-docs-i18n.py` — 通过; -4. README 链接可达性:核对 4 个 Pages URL 与 `docs/src/` 页面一一对应; -5. 归档完整性:`docs/src/` 下不再存在 `design/`、`dev/`、`quickstart.md`;`git log --follow docs/archive/legacy-nav/design/index.md` 可见历史延续; -6. `git status` — 工作区干净,全部改动已提交。 - -- [ ] **Step 4: Commit** - -```bash -git add scripts/check-docs-i18n.py -git commit -m "docs: add i18n coverage check for documentation site" -``` - ---- - -### Task 8b: 叙事对齐(宣发主角决策后的入口层修订) - -**背景**:用户在执行期间确认了宣发主角为**链路**——"从执行到可查询历史的完整基础设施"。叙事原则(来自用户提供的分析):pVisor 对外一句话定位收敛为"产生可持久化、可审查事实的执行器";不并列多个旗号;强调 run → review/apply → capture → 可查询 Dataset 的贯通路径,同时保留"两者可独立使用"的灵活性说明。 - -**Files:** -- Modify: `README.md`、`docs/src/overview.md(.zh.md)`、`docs/overrides/home.html` - -- [ ] **Step 1: README 叙事调整** - -保持 uv/Ruff 式简洁,仅调整叙事层: -- 开篇定位段:从"two commands"并列改为链路叙事——pVisor 让 Agent 执行产生可审查的事实(staged Effects、执行记录),pChronicle 让这些事实成为可查询的历史;两者各自独立可用,连起来构成从执行到查询的完整路径; -- 两个快速上手小节保留,在 pChronicle 小节末尾或其后增加一行贯通提示(capture 配置后 pVisor Run 事件可进入 pChronicle Dataset,链向 `pvisor/guides/capture/`); -- 不重排成熟度表、不动 benchmark 标记块。 - -- [ ] **Step 2: overview.md 叙事调整** - -- "Optional integration" 一节升级表述:从"可选集成"改为"贯通路径"(the throughline),作为页面叙事收束而非附属说明;"两者独立可用"保留为灵活性说明而非开场主张; -- 中英同步。 - -- [ ] **Step 3: home.html hero 检查** - -hero 已有 "One persistence story, two ways to start" 与 "Composable, not a mandatory pipeline" 版块——按链路主角口径审视:"Composable, not a mandatory pipeline" 的措辞强调"非强制流水线",与链路主角叙事张力过大时,调整为"独立可用,连通更强"类表述(保持事实准确:两者确实可独立使用)。中英同步。 - -- [ ] **Step 4: 验证 + Commit** - -Run: `just docs-build && just docs-links` - -```bash -git add README.md docs/src/overview.md docs/src/overview.zh.md docs/overrides/home.html -git commit -m "docs: align entry narrative on the execution-to-history throughline" -``` - ---- - -## Self-Review 记录 - -- **Spec 覆盖**:规格第 3–8 节分别映射到 Task 3、1/2/4、5–7、8、9、10;规格第 9 节实施顺序与 Task 1–10 顺序一致。无遗漏。 -- **占位符扫描**:Task 5–7 的审计类步骤以检查表 + 命令清单为可执行内容(审计工作的产出取决于逐页读到的现状,无法预先给出定稿文案);所有新建内容(README、ppilot 页面、脚本、nav YAML)均含完整文本。 -- **类型一致性**:`ppilot/index.md`/`get-started.md` 在 Task 2 定义英文定稿,Task 8 消费同一文件名;`check-docs-i18n.py` 的排除清单与 Global Constraints 的排除范围一致。 diff --git a/docs/superpowers/reviews/2026-08-23-four-page-prototype-review.md b/docs/superpowers/reviews/2026-08-23-four-page-prototype-review.md deleted file mode 100644 index 084a1368..00000000 --- a/docs/superpowers/reviews/2026-08-23-four-page-prototype-review.md +++ /dev/null @@ -1,168 +0,0 @@ -# 四页原型 review:还不理想的地方 - -> Review 对象:`pchronicle-four-pages.html` 中的 Overview / Explore / Traces / Analysis 四页原型。 -> 判断标准:昨天讨论的新品类方向——Agent 的飞行记录仪 + 时间旅行调试器,而不是 observability dashboard。 - -## 整体判断 - -这个原型的骨架是对的:dataset snapshot → source → traces → analysis 的主线清晰,pin-to-compare 和 evidence/interpretation/limitation 三段式结论都是好结构。但**它仍然被 observability dashboard 的语言主导**——时间序列 KPI、"Behavior health"、"terminal failures"、"latency P95"——这些词适合监控在线服务,不适合分析离线语料。 - -如果 pChronicle 要开新品类,最大的一块缺口在 **Trace 页**:它现在还只是"turn 列表 + 摘要",没有提供"模型在那一刻看到了什么"的状态重建,也没有 scrubber/断点/重放。真正的新形态要在这里发生。 - ---- - -## Overview 页 - -![Overview 原型](./assets/pc-proto-overview.png) - -### 做得对的 - -- Dataset snapshot + sources/projection/coverage 状态条非常好,把"数据就绪性"变成了一等概念。 -- Signals 列表直接给出可点击的调查入口(Repeated tool loop / Missing terminal event / Task completion drift),这比图表更接近"调试器"心智。 -- Cohort 表格(agent-v3 vs agent-v4)是页面下半部分最值钱的内容,但它被压在了 fold 下面。 - -### 还不理想 - -1. **"Outcome and behavior trend" 用日期横轴是错的心智模型** - - 这批数据是 import 的 corpus / benchmark 结果,不是按天流动的生产流量。日期条形图暗示"服务随时间变化",但用户真正想问的是"v4 比 v3 差在哪"。 - - 建议:把 cohort 对比做成页面的核心图,按 agent_version / model / source 分组,而不是按日期。 - -2. **KPI 卡片的语言还是 monitoring 的** - - "Traces 1,284 +9.4% from prior period"、"Latency P95" 对离线分析没有解释力。 - - 建议:改成"v3 vs v4 完成率差 8.1pt"、" tool loop 影响 42 条 traces"、"82 条 traces 缺业务指标被排除"。每个数字都指向一个可调查的 cohort 或 signal。 - -3. **Signals 的 badge 颜色语义弱** - - "3 active" 是 warn 色,但三个 signal 里只有 Missing terminal event 是 capture 问题,另外两个是行为问题。混在一起会让用户误判优先级。 - ---- - -## Explore 页 - -![Explore 原型](./assets/pc-proto-explore.png) - -### 做得对的 - -- Source inventory 表把 format / revision / projection / state 放在一起,符合 data lineage 需求。 -- Treemap 给了源规模的直观感受。 - -### 还不理想 - -1. **Explore 页缺少"问题意识"** - - 用户来这一页不是想看方块大小,而是想确认"我的数据能不能回答我想问的问题"。 - - 建议:右侧 selected source 面板除了 metadata,应该列出"基于该 source 可问的典型问题"或"已知限制"(例如 OpenAI messages source 的 60 条 trace 有 1 issue,具体是什么 issue?能不能一键修复?)。 - -2. **Treemap 颜色无意义** - - 当前所有 tile 都是同一蓝色,只是按大小分。颜色应该编码 agent_version、format 或 readiness state——让"哪块数据有问题"一眼可见。 - -3. **"Analyze dataset" 和 "Open traces" 两个按钮没有区别感** - - 从 Explore 打开 Traces 后用户要干什么?从 Explore 打开 Analysis 后又该问什么?入口需要带默认问题/scope,而不是空跳。 - ---- - -## Traces 页 - -![Traces 原型](./assets/pc-proto-traces.png) -![Trace diff 原型](./assets/pc-proto-diff.png) - -### 做得对的 - -- Pinbar + "Compare with pinned" 是极好的交互。它让"同一 root 下两个版本对比"变成了显式操作,不再是 power user 的暗能力。 -- Diff 视图用 changed / repeated / added 标注,直接对应用户想找的因果线索。 - -### 还不理想 - -1. **单条 trace 的详情仍然是事件摘要,不是调试器** - - 当前详情区只有 user/agent/tool 的简短摘要 + token/latency 条。用户点进来真正想问的是:"模型在第 17 步为什么会调用 execute_bash 5 次?" - - 缺的核心原语:**步进 scrubber + 该步的上下文重建 + 与上一步的 diff 高亮**。这是昨天"时间旅行调试器"形态的关键,原型里完全没有。 - - 建议:详情区至少有两个 tab:Summary(当前)和 Replay/Context(新)。Replay tab 用底部 scrubber,主区域显示模型在该步看到的完整上下文,新增消息高亮。 - -2. **Behavior signals 列没有链接到具体位置** - - "tool loop" badge 在列表里只是一枚标签,点击后应该直接跳到 trace 中 loop 发生的 step,并把上下文展开。 - -3. **Pinbar 的 copy 太弱** - - "Pin another trace while browsing" 没有说明价值。建议改成"Pin a second trace to diff against",并自动推荐同一 root 的其他 run。 - ---- - -## Analysis 页 - -![Analysis 页下半部原型](./assets/pc-proto-analysis-bottom.png) - -### 做得对的 - -- "Reviewed plan → Evidence → Interpretation" 三段式是核心竞争力。它把 LLM 分析的可验证性做进了界面(Observed / Inference / Limitation)。 -- Advanced SQL 可展开,兼顾平民用户和 power user。 - -### 还不理想 - -1. **Schema 浏览器占用了左侧主边栏** - - 分析流程的起点是问题("Why did task completion fall..."),不是表结构。把 schema 放在默认展开位置,会让首次进入的用户困惑。 - - 建议:左侧边栏默认折叠,或在 question 输入框里提供"schema 提示"(例如 `@` 唤起字段),只在编辑 SQL 时才展开完整 schema。 - -2. **"Promote rule to Signal" 被埋在底部** - - 这个动作其实是分析闭环的关键:把一次调查得到的规律变成可复用的检测规则。但它和 "Export evidence report"、"Rerun on new snapshot" 并列,视觉权重相同。 - - 建议:把 "Promote to Signal" 作为 Evidence 卡片的主要 action,甚至可以叫 "Watch this"——让分析产出自动回流到 Overview 的 signals 列表。 - -3. **Interpretation 的三种状态需要更强的 epistemic 设计** - - 现在 Observed / Inference / Limitation 只是三个小标题。Limitation("82 traces excluded")和 Inference("candidate explanation")的置信度差异很大,但视觉上平级。 - - 建议:给每个结论加置信度标识,例如 Observed = 已验证(绿色),Inference = 待验证(黄色,可点击"在 traces 中验证"),Limitation = 已知缺口(灰色)。 - ---- - -## 跨页问题 - -1. **Snapshot 概念很重要,但只在 header 作为 badge 出现** - - 如果 pChronicle 要往"飞行记录仪"走,snapshot 应该可命名、可比较、可在新 snapshot 上重跑 analysis。现在它像是一个只读时间戳。 - -2. **Rail 里 "Copilot" 的身份不清晰** - - 它是全局浮层?是某一页?图标是一颗菱形,用户不知道点开会发生什么。如果 Copilot 是"在任意页问我一个问题",应该做成 FAB 或右下角面板,而不是和四页并列的 nav item。 - -3. **"Read only" badge 是防御性文案** - - 对本地文件系统来说 read-only 是合理的,但 badge 本身没有解释 why 或 what I can do。建议改为更积极的说明:"Local snapshot · refresh to update",并把刷新频率/手动刷新入口放在一起。 - -4. **Overview / Explore / Traces / Analysis 的命名对新人不够自解释** - - 尤其是 Explore 和 Overview 容易混淆。如果按新品类重新命名,可以考虑: - - Overview → Summary(或 Health → 但 avoid monitoring connotation) - - Explore → Sources(数据血缘) - - Traces → Inspector(调试器语义) - - Analysis → Ask(问题驱动) - - 命名改动有成本,但方向是减少 dashboard 暗示、增加 debugger/lab 暗示。 - ---- - -## 与品类方向的对齐 - -| 新品类方向 | 原型现状 | 下一步 | -|---|---|---| -| 数据:完整录制 = 黑匣子 | snapshot/source lineage 已有 | 让 snapshot 可命名、可比较、可重跑 analysis | -| 回放:任意步的状态重建 | 只有 turn 摘要 | 加 scrubber + context reconstruction + step diff | -| 断点:SQL 即条件 | Signals 列表已出现 | 把 signal 和 SQL plan 打通,signal 从 analysis 一键 promote | -| 实验:fork & rerun | Compare diff 已有 | 从 diff 直接跳到"在 v3 的 prompt/工具结果下重跑 v4"的实验入口 | - ---- - -## 优先级建议 - -**P0 — 改心智模型,不是改样式** -- Overview 移除日期趋势图,把 cohort 对比(agent-v3 vs v4)提升为核心视图。 -- 所有 KPI 文案从"monitoring 指标"改为"调查入口"。 - -**P1 — 把 Trace 页从"查看器"改成"调试器"** -- 单条 trace 详情增加 Replay/Context tab:scrubber + 上下文重建 + diff 高亮。 -- Behavior signals badge 可点击跳转到对应 step。 - -**P1 — 理顺 Analysis 的入口和信息层级** -- Schema 默认折叠;问题输入区更突出。 -- "Promote to Signal" 提升为 Evidence 卡片主 action。 -- 给 Interpretation 加置信度/验证状态。 - -**P2 — 跨页一致** -- Snapshot 可比较、可重跑。 -- Copilot 不要放在 rail 里。 -- Explore 的 source tile 用颜色编码状态/格式。 - ---- - -## 一句话 - -这个原型已经站在了正确的结构(snapshot → source → traces → analysis)上,但**设计语言还没从"监控大屏"切换到"飞行记录仪/调试器"**。最大的单一改进是:**让 Trace 详情页支持步进 + 上下文重建 + step diff**——做到这一点,整个产品的品类主张才会在界面上成立。 diff --git a/docs/superpowers/reviews/2026-08-23-frontend-product-review.md b/docs/superpowers/reviews/2026-08-23-frontend-product-review.md deleted file mode 100644 index e34236e2..00000000 --- a/docs/superpowers/reviews/2026-08-23-frontend-product-review.md +++ /dev/null @@ -1,104 +0,0 @@ -# pChronicle 前端产品整体 review - -日期:2026-08-23 -范围:运行中的 Dioxus WASM 前端(当前命令为 `pchronicle serve ./data`,26 runs 真实数据)+ 已收敛的产品方向(时间旅行调试器叙事 v2) -方法:agent-browser 逐页实测截图(8 张,存 `assets/2026-08-23-frontend/`) - -![Catalog 页:单数据集 tile 拉伸撑满](assets/2026-08-23-frontend/pc-fe-1-catalog.png) - -![Runs 页](assets/2026-08-23-frontend/pc-fe-2-runs.png) - -![Analyze 页](assets/2026-08-23-frontend/pc-fe-3-analyze.png) - -![详情页 Trace](assets/2026-08-23-frontend/pc-fe-4-detail.png) - -![详情页 Steps 视图](assets/2026-08-23-frontend/pc-fe-5-steps.png) - -![展开 step 仅一行摘要 + 0 ev](assets/2026-08-23-frontend/pc-fe-7-turn-expand.png) - -![Copilot 抽屉](assets/2026-08-23-frontend/pc-fe-6-copilot.png) - -![详情页 Analysis tab](assets/2026-08-23-frontend/pc-fe-8-detail-analysis.png) - -## 结论摘要 - -当前前端是一个**完成度不错的 trajectory workbench**:Data / Runs / Analyze 三段式清晰,SQL 工作台扎实,详情页的指标与组成分析信息量大。但它整体讲的是 **observability 语言**("检查执行、延迟、显式失败"),而不是已经定稿的**时间旅行调试器语言**("模型在那一刻看到了什么")。最硬的两处证据: - -1. 详情页点开一个 step,展开的只有一行摘要和 "0 ev"——**数据层录了完整上下文,界面上却看不到任何重建**; -2. 详情页第一眼看到的是 UUID 和 ACTIVE 状态——**第一视角是系统,不是模型**。 - -界面骨架是对的四段(Data → Runs → 详情 → Analyze),但每一段的叙事都还是旧的。 - -## 现状地图(实测) - -| Rail | 页面 | 实测状态 | 截图 | -|---|---|---|---| -| Data | Catalog 数据集树 | 单数据集时 tile 拉伸撑满整屏(视觉破损) | pc-fe-1 | -| Runs | run 列表 + 路径树 | 正常,表格信息完整 | pc-fe-2 | -| Analyze | 问题 + SQL 编辑器 + catalog 侧栏 | 正常,starting points 好 | pc-fe-3 | -| Runs → 详情 | 指标行 + 组成卡 + Trace(Chats/Steps) / Analysis tab | 功能在,叙事旧 | pc-fe-4/5/7/8 | -| Copilot | 抽屉,read-only | 需要配置模型才能用 | pc-fe-6 | - -## 发现(P0 / P1 / P2) - -### P0 — 直接破损或与新品类主张正面冲突 - -**P0-1 Catalog 页大蓝块(pc-fe-1)—— ✅ 已修复(2026-08-23)** -`default` 数据集 tile 拉伸占满整个视口,只剩 "default" 字样和角标 "26"。疑似 grid `minmax` + 单卡片时的布局 bug。作为用户进入应用的第一屏(默认 page=catalog),这是门面问题。 - -修复:根因在 treemap——`children ≤ 2` 时单 tile 必占满 `flex:1` 的容器。`CatalogMosaic` 在子项 ≤2 时切换为 compact 卡片模式(260×120 固定卡片流),`catalog.rs` + `catalog.css`。验证截图 `pc-fix-1-catalog.png`。 - -**P0-2 详情页看不到"模型所见"(pc-fe-7)—— ✅ 已修复(2026-08-23)** -展开 step #4 得到的只有一行内联摘要(`AGENT #4 autonomous I'll start by exploring…`)+ "0 ev"。warehouse 里明明录着该步完整上下文(evidence SQL 可查),界面却不做重建。这是 v2 叙事的核心原语("回到那一刻是字面操作")在现有界面上**完全缺席**——不只是没做,而是当前 UI 结构里没有它的位置。 - -修复:新增 **Context at this step** 上下文重建面板——打开任一 turn 时,从 `/api/storyline` 拉取完整录制轨迹,按顺序重放该步之前的全部消息(角色 chip + #id + 字数 + 长文可展开),底部标注 "turn #N decided with the context above ↓"。改动:`model.rs`(`StorylineSnapshot`)、`api.rs`(`storyline()`)、`workspace.rs`(独立加载、不阻塞主工作区、失败静默降级)、`components.rs`(`ContextRebuild`/`ContextMessage` + 切片单测)。验证截图 `pc-fix-2-context.png` / `pc-fix-3-context-open.png`(展开 system prompt 全文可见)。 - -### P1 — 叙事与信息架构偏差 - -**P1-1 详情页 header 是系统语言(pc-fe-4)** -标题是 session UUID + ACTIVE badge + root id。用户在调试时脑子里想的是"这个 agent 在执行什么任务、哪一步出了问题",界面却不回答。建议:标题放任务首句(user turn 0),UUID 降级为小字。 - -**P1-2 EVIDENCE 列全 "0 ev" 无降级(pc-fe-4/5)** -该数据集所有 chat/step 的 evidence 均为 0,列形同虚设但占着宝贵宽度。空态应隐藏列或明确说明"该数据未捕获 events",而不是让用户面对一列零。 - -**P1-3 详情页左侧 Run paths 树空间浪费(pc-fe-4)** -已进入单条 run 的详情,左栏仍是完整的路径树(26 个节点),与本页任务无关。这列正是未来 **step 导航 / 时间轴**该在的位置(对应调试器原型的左栏)。空间被导航占用,核心工作面反而没有。 - -**P1-4 "Analyze this run" 入口关系含糊(pc-fe-4)** -详情页内已有 Analysis tab(pc-fe-8),顶部又有 "Analyze this run" 按钮跳全局 Analyze 页。三个"分析"入口(详情 tab、顶部按钮、rail Analyze)职责边界不清。应明确:详情 Analysis tab = 该 run 的自动画像;按钮 = 携带 scope 跳转到 SQL 工作台。 - -**P1-5 Copilot 是旁观者,不是现场工具(pc-fe-6)** -Copilot 自述 "Read-only · minimal evidence",未配置模型时是空抽屉。按 v2 叙事,自然语言入口应该嵌在"现场"里("在 step N 问为什么"),而不是一个与当前步无关的全局抽屉。现状它与用户选中的 step/turn 没有联动。 - -### P2 — 打磨项 - -- **P2-1** 键盘操作只有 `⌘J`(Copilot)。详情页应支持 `←/→` 或 `j/k` 步进——时间旅行的标志性交互目前一个键都没有。 -- **P2-2** Runs 表 Session 列是截断 UUID,无可读标识(pc-fe-2)。可加任务首句作为副标题。 -- **P2-3** Sequence/Occupancy strip 是时间轴的雏形(pc-fe-4/5),但语义是 "occupancy" 且不可拖——距 scrubber 一步之遥,值得重构成可交互时间轴。 -- **P2-4** Coverage 卡片里 "unavailable 6"(MODELS)这类裸词无解释,需 tooltip 或文案说明。 -- **P2-5** rail 图标用字符(▣◫⌁◇),与四页原型的 SVG 图标体系不一致,视觉语言有代差。 - -## 与时间旅行调试器叙事的对齐度 - -| 叙事主张(v2) | 现有前端最接近的落点 | 差距 | -|---|---|---| -| 回到那一刻是字面操作 | Sequence strip + 展开 step | 无上下文重建,无 scrubber | -| 界面以模型视角为第一视角 | 无 | header/详情全是系统视角 | -| 每个异常是入口 | EXPLICIT ERRORS 指标卡 | 只是数字,不可点 | -| 断点设在条件上 | Analyze 页 SQL | SQL 能力在,但未与轨迹视图联动(查询结果无法"跳到现场") | -| fork 重演验证因果 | 无 | 全新能力 | - -**判断:现有前端与新品类方向不冲突,但还停留在它的"走廊层"。** Data/Runs/Analyze 三段是通往现场的走廊,质量够用(除 P0-1);真正缺的是"现场"本身——详情页需要从"证据陈列"升级为"时间旅行调试"。这与四页原型 review、调试器原型的结论一致。 - -## 建议行动序 - -1. **P0-1**(半天):修 catalog 单卡片拉伸 bug —— 门面。 -2. **P0-2**(核心迭代):详情页 step 展开 → 上下文重建面板(对齐调试器原型 Context tab)。这是新品类的第一块基石,优先于一切 P1。 -3. **P1-3 + P2-3**(同一迭代):详情页左栏改 step 列表,sequence strip 升级为可拖 scrubber——把调试器原型的左栏和底栏落进真实页面。 -4. **P1-1/P1-2/P1-4/P1-5**:叙事与入口清理,随 #3 一起改。 -5. P2 项随时穿插。 - -## 遗留风险 - -- 详情页改造会触碰 `workspace.rs`(1862 行,单文件巨石)——改 step 列表/scrubber 时建议先拆组件,否则回归面大。 -- "0 ev" 数据集说明本地样例数据证据覆盖率低,调试用数据需要一份含完整 events 的样例,否则上下文重建做出来也看不到效果。 diff --git a/docs/superpowers/reviews/2026-08-23-pchronicle-design-review.md b/docs/superpowers/reviews/2026-08-23-pchronicle-design-review.md deleted file mode 100644 index f1da4941..00000000 --- a/docs/superpowers/reviews/2026-08-23-pchronicle-design-review.md +++ /dev/null @@ -1,294 +0,0 @@ -# pChronicle 设计与实现深度评审 - -> 视角:分布式系统与存储。重点:过度设计识别与"刀法"建议。 -> 范围:`crates/persisting-pchronicle`(约 109 个 Rust 文件)+ `crates/persisting-pchronicle-cli`(约 7.3 万行合计,含测试)。 -> 日期:2026-08-23 - ---- - -## 0. 一句话总评 - -pChronicle 的**核心数据模型和写入路径是健康的**(append-only events → 单向投影 → Lance 三表),但它在三个维度上系统性超配:**用多写者分布式协议保护一个单机嵌入存储、用 9 种格式服务一个 1:1 的 schema、用手写查询优化器绕过已有的成熟优化器**。估算总代码中约 1.2–1.5 万行(近 20%)服务于边际收益极低的需求,且这些复杂度集中在最容易腐烂的并发协议与格式转换上。 - -## 1. 架构骨架(先说清楚它是什么) - -``` -capture 回调 - → append_queue(有界 mpsc + 专用线程 + 2-worker tokio runtime) - → events.lance(per-run,append-only,事实层) - → projection(单向投影为 StorylineDocument) - → storyline store(runs/steps/tool_calls 三表 + objects.lance 内容寻址) - → CURRENT 指针 CAS 发布 -读取:DataFusion (ChronicleQueryEngine) → DocumentSourceImpl → 4 种 datasource -CLI/server:import/export、query、explorer HTTP API、acceleration 内存索引、analysis compile -``` - -亮点(必须承认做得好的部分): - -- ** Lance 单引擎决策正确**。没有自研存储格式,MVCC/索引/compaction 全部复用 Lance,Arrow/DataFusion 打通内存与查询。这是整个项目最值钱的一个取舍。 -- **trait 使用克制**。crate 自有 trait 仅 2 个(`ChronicleEventRecordExt`,`formats/events.rs:48`;`QueryDocumentSource`,`document_source.rs:28`,pub(crate)),没有 trait 爆炸。注:另有 5 处 `impl TableProvider`(storyline/datafusion、catalog/provider、files、events/datafusion、agenticmd_datafusion),那是对 DataFusion 外部 trait 的实现而非自有抽象——但它们正是 §2.6 合并刀口的对象,两处结论自洽。 -- **写入路径的 epoch fence 思路正确**:旧 epoch 只能产生垃圾、不能产生可见数据。 -- **测试文化健康**:CLI 层测试与实现约 2:1,且以端到端行为测试为主(import 原子性、预算截断、错误策略),不是镜像内部结构的脆测试。 - -问题不在骨架,在骨头上长的赘肉。以下按"砍掉的收益/风险比"排序。 - ---- - -## 2. 过度设计清单(按动刀优先级排序) - -### 2.1 多写者分布式 lease 协议保护单机存储 —— 最大的刀口 - -**现状与证据**: - -| 组件 | 行数 | 职责 | -|---|---|---| -| `store/writer_control.rs` | 628 | 完整 writer lease:acquire/renewal/takeover/CAS publish | -| `store/events/manifest.rs` | 1006 | epoch fence + 分层 segment 压缩 + 64 次 CAS 重试 | -| `store/run_control.rs` | 858 | per-run lease/commit CAS | -| 其他 | — | root_write_lock、dataset_write_lock、index_build_gate、append_queue 双检 | - -加起来 **2500+ 行并发协议代码**,外加 4 组 `#[cfg(test)]` 全局 barrier/故障注入 hook——分布在 `store/storyline/mod.rs:292-317`(`CREATE_AFTER_EMPTY_READ_BARRIER`、`REPLACEMENT_AFTER_CURRENT_READ_BARRIER`)和 `projection/storyline.rs:28-32`(`BUILD_BEFORE_PUBLICATION_BARRIER`、`PROJECT_SOURCE_READ_FAILURE`)——**并发协议复杂到必须注入故障注入点才能测试,这本身就是复杂度失控的信号**。 - -**为什么过了**:对象存储后端(s3://az://gs://)是这套协议唯一真正的存在理由,而它只是 `open_uri` 注释里预留的插件点(`store/mod.rs:435-439`)。单机嵌入场景下,代码里其实**已经存在正解**:`acquire_write_guard` 的 flock(`store/mod.rs:504-539`)+ `write_local_current` 的原子 rename(L1535)。lease/takeover/CAS 全部是在为一个尚未接入的后端买单。 - -**刀法**: -- 现在:本地路径走 flock + rename,writer_control 整体降级为一个 feature-gated 模块或直接删除,对象存储支持声明为"roadmap"。省约 1000–1500 行,并消掉全部 takeover/cleanup 分支和故障注入 hook。 -- 真到接 S3 那天:用 Lance 自身的外部 manifest store(它本来就支持 commit 抽象),不要自己写 CAS 协议。 -- **原则**:分布式协议的复杂度不能"预埋"。预埋的协议代码不是资产,是每轮重构都要搬运的负债。 - -### 2.2 9 种数据表示、5 种轨迹表示 —— schema 是 1:1 的,表示却是 1:5 的 - -**口径说明**:`DocumentFormat` 枚举为 7 个变体(`format.rs:11-26`:CanonicalEvent / Storyline / StorylineLance / AgenticMd / Atif / OpenaiMsg / Actf);"9 种"的完整口径 = 7 个登记变体 + 2 个未登记表示(`formats/llm.rs` 的 LLM payload、`convert/actf.rs` 内藏的 OpenClaw 事件日志子格式)。另有 3 种控制面 JSON(manifest / CURRENT / run-control)未计入。 - -**证据**(`format.rs:11-26` + 逐字段对比): - -- **Storyline JSON ≈ ATIF,几乎是字段改名**。`AtifStep{step_id, timestamp, source, message, reasoning_content, ...}` 对照 `StorylineTurn{id, ts, src, msg, reason, ...}`(`formats/storyline.rs:121-161`),`lib.rs:5` 自认"与 ATIF v1.7 对齐"。`convert/atif.rs` 943 行大部分在做 rename + 短键映射。 -- **ACTF 概念泄漏进 hub**:`StorylineTaskResult`(storyline.rs:364-393)的 `correct/final_answer/ground_truth/score/...` 14 个字段是纯 benchmark 打分语义,hub 被 ACTF 污染。 -- **ACTF 内部还藏着第三种格式**:untagged `ActfTrajectoryWire::Events` + `convert/actf.rs:297-587` 的 openclaw_* 函数族,一个未被 `DocumentFormat` 承认的 event-log 格式。 -- **边界混乱**:openai_msg 的双向转换不在 `convert/` 而在 `formats/openai_corpus.rs`(含约 450 行反向 synthesize);`pointer_join` 出现 3 次、`message_text` 2 次、`insert_*_map` 3 份。 -- **文档与实现矛盾**:lib.rs 声称 events→Storyline 是单向投影,但 `storyline_to_events` 存在并被 `store/catalog/mod.rs:413,430` 用于重建 events。 - -**刀法**:交换格式 5 砍到 2——保留 **ATIF**(外部标准,Harbor RFC 0001)和 **AgenticMD**(人类可读)。Storyline JSON 退化为内部类型别名(不再作为交换格式暴露),ACTF/OpenAI Msg 语料移出核心、降级为独立 import 工具或声明有损导入。省约 3000 行,且 hub schema 从此只需要对齐一个外部标准。 - -### 2.3 unknown_fields 机制:2500+ 行为一个弱需求 - -**证据**:`formats/unknown_fields.rs` 1318 行,实现"把源格式中 hub 不认识的字段按 `(source_format, document_id, JSON pointer)` 三元组保留、导出时写回原位置",外加每个转换器里的寄生 capture/restore 逻辑(actf.rs:664-836 约 170 行、openai_corpus 约 250 行、agenticmd restore),总成本 **2500+ 行**。 - -**为什么过了**:同 crate 里 `atif.rs:30-31` 已经用 `#[serde(flatten)] unknown: Map` 廉价解决了同一问题;而且 `storyline.rs:19` 全部结构体 `deny_unknown_fields`——**权威模型本身根本不需要这套保留机制**。为一个"roundtrip 不丢陌生字段"的弱需求付出一套分布式追踪级别的基础设施。 - -**刀法**:全面改用 `#[serde(flatten)]` 的 per-struct unknown map(同 format 内 roundtrip 即可),跨格式转换时仅告警不保留。省 2000+ 行,语义对 99% 用户无差别。 - -### 2.4 acceleration.rs:手写了一个 miniature 查询优化器 - -**证据**:`crates/persisting-pchronicle-cli/src/server/acceleration.rs` 1762 行(**CLI crate 的 server 子模块,非核心存储 crate**)——用 sqlparser 解析用户 SQL(`AnalyzedQuery`),保守注入 `_file_ IN (...)` 谓词做 source 裁剪;自建三套内存索引(run 摘要缓存、run 路由索引、上限各 100 万行的 value→source 指纹索引)。其注释声明 persistent Catalog 仍是 source of truth、裁剪失败时回退原查询,即它是一个保守可降级的加速层——位置与可降级性使其影响面小于核心查询引擎内嵌优化器,但不改变下面的结论。 - -**为什么过了**:DataFusion 自带谓词下推与分区裁剪,Lance 自带标量索引。手写 SQL 重写器是在和一个成熟优化器赛跑,而且只能"保守地"跑——典型的负和博弈:写 1762 行,换来的是 DataFusion 升级时必须跟着维护的 AST 分析代码。 - -**刀法**:`_file_` 裁剪下推给 DataFusion/Lance;value→source 映射持久化为一张小物化表,用普通 SQL join 实现;run 摘要缓存退化为简单的 TTL cache。省约 1400 行。 - -### 2.5 "分析"功能的三份实现 - -同一个"按 agents/models/tools 维度聚合"的需求(证据链完整,均可直接跳转): - -1. CLI 的 4 条硬编码 SQL 常量:`pchronicle-cli/src/lib.rs:1944-2028`(`ANALYSIS_OVERVIEW_SQL` / `ANALYSIS_AGENTS_SQL` / `ANALYSIS_MODELS_SQL` / `ANALYSIS_TOOLS_SQL`,由 L1852-1855 的 `AnalysisCommand` 分派消费) -2. `pchronicle-cli/src/server/explorer.rs` 的 Rust 侧聚合:`analyze`(L440)+ `dimension_aggregates`(L782),直方图/百分位/维度聚合 -3. spec→SQL 编译管线:`analysis_compile.rs`(核心 crate)+ 前端 `analysis.rs`(2538 行) + `analysis_session.rs`(2332 行) + `analysis_agent.rs`(1528 行) - -**刀法**:统一到 analysis compile 管线(它已有 stale_snapshot/EXPLAIN 校验,最严谨),CLI `analysis` 子命令改为调 compile,删硬编码 SQL 与 explorer 的 Rust 聚合。顺带把 `analysis_compile.rs`(1068 行)从存储 crate 移到 CLI crate——它唯一的调用方就在 CLI,存储 crate 不该为 LLM 分析功能背书。 - -### 2.6 catalog 多 mount 查询层 - -**证据**:`store/catalog/`(6 文件约 3000 行)实现多 mount union + LazySource + 第五套 DataFusion TableProvider + `_file_` 谓词下推。 - -**刀法**:要求数据先投影进单一 Storyline store,用 DataFusion 原生 `UNION ALL` 视图替代 LazySource/provider 体系。五套 TableProvider(storyline/datafusion、events/datafusion、files、agenticmd_datafusion、catalog/provider)合并为至多两套(events + storyline),样板代码随之消失。 - -### 2.7 功能面赘肉(单项不大,合计可观) - -- **`onboard.rs`(1087 行 + 3 份内嵌资产)**:教程不该是可执行代码,还要进程内回调 `run_list/run_query` 捕获输出再渲染。换成静态 Markdown 文档 + `pchronicle demo` 生成示例数据集。 -- **`echo` 子命令**:测试工具混进产品 CLI,移到 gateway crate 的 dev-bin。 -- **`/export/har`、`/export/otlp`、`/revisions` 三个单用途端点**:合并为 `/api/export?format=har|otlp`;revisions 前端未调用(`api.rs` 无引用),删。 -- **`/api` 与 `/api/v1` 双前缀**(`server/mod.rs:184-211` 等价路由注册两遍):留其一。 -- **`QueryDocumentSource` trait**(`document_source.rs:28`):唯一实现者就是同文件的 `DocumentSourceImpl` enum,方法全部委托回 enum match——trait+enum 双重抽象,删 trait 无损失。 -- **四层 re-export 门面**(lib.rs → storage.rs → store/mod.rs → storyline/mod.rs):同一符号转出口 4 次,收敛到 2 层。 -- **agenticmd 写路径**:自称"非权威 debug 视图"却有 `fs.rs`(814 行)的 upsert/索引/元数据重写 + 专属 TableProvider。debug 视图不该有写路径,砍 `fs.rs` 只留渲染。 -- **objects.lance 内容寻址**(`content.rs` 1121 行的 externalize/hydrate/prune + GC):Lance blob 列或提高阈值直存大 JSON 即可覆盖大多数场景,`prune_unreferenced_objects` 随之消失。这条优先级最低,因为它确实解决大 payload 问题,但值得重新标定阈值验证收益。 - -### 2.8 serve 三合一编排 - -`serve` 把 Warehouse HTTP + Control JSONL/TCP 写协议 + LLM Gateway 编排进一个进程,配套 110 行 shutdown 状态机 + `projection_supervisor` 539 行 per-source 重试状态机。单一职责拆分:Gateway/Control 独立子命令,Warehouse 只做读;投影收敛用一次性 `converge_before_readiness` + 后台定时任务即可。 - ---- - -## 3. 刀法汇总:砍/留/改 - -| 优先级 | 动作 | 目标 | 预估省代码 | 风险 | -|---|---|---|---|---| -| P0 | 砍 | writer_control lease + 对象存储预留(改 flock+rename) | ~1500 行 | 低,未来接 S3 用 Lance commit 抽象 | -| P0 | 砍 | unknown_fields 机制(改 serde flatten) | ~2000 行 | 低,跨格式 roundtrip 变有损(可接受) | -| P0 | 砍 | acceleration.rs(下推给 DataFusion + 物化小表) | ~1400 行 | 中,需验证查询延迟回归 | -| P1 | 合并 | 交换格式 5→2(ATIF + AgenticMD) | ~3000 行 | 中,外部用户迁移成本 | -| P1 | 合并 | analysis 三份实现 → compile 管线 | ~1500 行 | 低 | -| P1 | 合并 | catalog 层 → DataFusion 原生 union;TableProvider 5→2 | ~2000 行 | 中 | -| P2 | 移动 | analysis_compile.rs → CLI crate;agenticmd 砍写路径;onboard 改静态文档 | ~2000 行移出核心 | 低 | -| P2 | 清理 | 双 API 前缀、QueryDocumentSource trait、4 层 re-export、echo/revisions | ~500 行 | 低 | - -**合计:约 1.2–1.4 万行从核心链路移除(当前总量 7.3 万行含测试),核心 crate 预计瘦身 25–30%,且砍掉的全是故障率最高的并发协议与格式转换代码。** - -## 4. 边际收益曲线视角的总结 - -这个项目的复杂度分布呈现一个清晰的模式:**每一项过度设计都对应一个"未来可能要"的需求**——对象存储、多写者、五种交换格式、无损 roundtrip、手写优化器——而这些需求至今没有一个真实落地。与之相对,真正落地的需求(单机嵌入、ATIF 交换、DataFusion 查询)都已经有更简单的现成解。 - -刀法精准的判据只有一条:**为已验证的需求付复杂度,不为想象中的需求付复杂度;当简单方案(flock、serde flatten、DataFusion 下推)已经存在于代码库自身时,它就是正确答案的证据,而不是权宜之计。** - -好消息是骨架不用动:events 事实层 + 单向投影 + Lance 三表这个核心是对的。所有的刀都落在附加层上,这也是为什么上面的每项砍除风险都只有"低"或"中"——它们本来就不该在关键路径上。 - ---- - -## 5. 第二轮意见的吸收(2026-08-23 补充) - -另一份评审对本文档提出了三点修正和若干新发现。经逐条代码核实,**其新发现全部属实,其修正我接受两条半**。核实证据与合并后的结论如下。 - -### 5.1 核实通过的新发现 - -**(a) 三套逐行同构的 CAS store —— 确认,且比本文档 §2.1 的定性更精确。** - -`store/attempt_registry.rs`(409 行,第一轮漏看)、`store/run_control.rs`、`store/events/manifest.rs` 三段代码结构完全一致,证据链: - -| 元素 | attempt_registry.rs | run_control.rs | manifest.rs | -|---|---|---|---| -| `CAS_RETRIES` | L20 (=32) | L22 (=32) | L24 (=64) | -| `enum Backend {Local, Object}` | L48 | L43 | 隐含于 mutate_with_mode | -| `async fn mutate` 闭包模式 | L216 | L368 | L498 (`mutate_with_mode`) | -| `PutMode::Create` / `Update(version)` | L257-258 | L412-413 | L554-556 | -| `read_local_*` / `write_local_*`(tmp+rename) | L315/328 | L478/491 | L603/615 | -| `encoded_id` 路径编码 | L294 | 同款 | — | - -第二份意见的定性是对的:**这不是"三个系统重复解决一个问题",而是"一个正确性论证(读-改-CAS 写)被抄了三遍"**。问题在抽象缺失,不在职责重复。这把 §2.1 的行动建议从"砍 lease"修正为"先抽象"——见 §5.3。 - -**(b) `SingleWriter` 双写模式 —— 确认。** `manifest.rs:27-33` 定义 `Conditional`/`SingleWriter` 双轨,为"不支持条件替换的 S3 提供商"准备,在 RFC-0007 已定调本地 loopback sidecar 的当前阶段无真实使用者。属提前工程,归入 §2.1 同一刀口。 - -**(c) ATIF 的 unknown 被处理两遍 —— 确认,比我第一轮说的更严重。** `src/atif.rs` 的 5 个结构体全部自带 `#[serde(flatten)] unknown: Map`(L30/44/74/87/94),而 `convert/atif.rs:287` 又手写 `capture_atif_unknowns` 用 JSON pointer 再捕获一遍。声明式 flatten 与手写指针捕获语义重叠、各自维护。这强化了 §2.3 的结论:unknown_fields 机制不是"可以更便宜",而是"在同一格式内部就已经自相重复"。 - -**(d) 两个空 `mapping/` 死目录 —— 确认。** `src/mapping/` 与 `src/agenticmd/mapping/` 均为空(2026-08-17 重构残留),直接删。 - -### 5.2 接受的修正 - -| 第一轮判断 | 修正后 | -|---|---| -| §2.1:"砍 writer_control lease 体系,省约 1000 行" | **降级为两步**:先抽 `cas_store` 原语消除三份同构(约 600 行重复下沉),对象存储后端是否删除另作独立决策。直接删 lease 会把"防本地多进程"的真实保护一起删掉,风险被低估 | -| §2.7:"objects.lance 内容寻址值得重新标定阈值验证收益" | **撤回,改为明确保留**。它是作用于三表全部宽列的通用 content-addressed 大对象层,解决 `reasoning_content`/`message_json` 的行宽与重复痛点,是刀刃上的钢。第二轮意见对"它是 unknown-fields 去重附属品"的反驳成立 | -| epoch fence 语义 | 两论一致:**保留**。这是写入路径正确性的核心 | - -### 5.3 合并后的刀法清单 v2 - -| 优先级 | 动作 | 省代码 | 性质 | -|---|---|---|---| -| **P0** | 抽 `cas_store` 原语(read-if-match + 重试,本地锁/对象 store 双后端),三个 store 下沉复用 | ~600 行 | 消除冗余(两份意见汇合后的第一刀) | -| **P0** | 收敛格式:`atif.rs` 的 flatten `unknown` 与 `capture_atif_unknowns` 合并为一条路径;unknown_fields 全局机制改 serde flatten | ~2000 行 | 冗余 | -| **P0** | 砍 acceleration.rs(下推 DataFusion + 物化小表) | ~1400 行 | 过度设计(仅第一轮提出,第二轮未反对) | -| **P1** | 格式收敛:2 个存储权威(Events Lance + Storyline Lance)+ 其余降级为纯 import codec,砍掉 5 个 codec 的 DataFusion provider 与 7 分支能力矩阵(`document_source.rs:260-326`) | ~3000 行 | 冗余+过度设计(两论方向一致,第二轮的"砍 query provider 但保留 import codec"比第一轮的"砍格式"更稳妥,采纳) | -| **P1** | 删 `SingleWriter` 双写模式;catalog 层 → DataFusion 原生 union | ~2500 行 | 过度设计 | -| **P2** | analysis 三份实现合一;analysis_compile.rs 移到 CLI;agenticmd 砍写路径;onboard 改静态文档 | ~2000 行移出核心 | 第一轮提出,第二轮未涉及,保留 | -| **P2** | 删空 `mapping/` 目录 ×2;评估 Storyline writer lease 续约退化为单写者断言 | ~100 行 | 冗余/过度设计 | - -**保留清单(两论一致)**:Lance 单引擎、events→Storyline 单向投影、epoch fence、`content.rs` content-addressed 层、CLI 行为测试套件。 - -### 5.4 两轮意见的关系 - -第二轮的价值不在于推翻第一轮,而在于**把"过度设计"拆成了两个性质不同的桶**: - -- **冗余(复制粘贴)**:三套 CAS、两套 unknown 捕获、空目录——这类问题解法是抽象,风险极低,应最先动; -- **提前工程(为未出现场景的复杂度)**:SingleWriter、lease 续约、多跳 envelope、acceleration、多 codec provider——这类问题解法是做减法和降级,需要逐项验证无真实使用者。 - -第一轮按"砍多少行"排序,第二轮按"问题性质"分类。合并后的正确顺序是:**先做零风险的抽象(CAS 原语、unknown 单路径),再做需要验证的减法(provider、SingleWriter、lease 降级)**——这正是边际收益曲线上"先摘低垂果实"的标准打法。 - ---- - -## 6. 第三轮交叉核验的裁决(2026-08-23 补充) - -第三轮核验者对本报告 §0-§4 提出 2 处事实性质疑和 3 处口径质疑。经逐条回到代码钉死,**裁决如下:本文档 2 处措辞不精确(已修正),1 处双方各对一半,3 个数字口径全部补证成立**。 - -### 6.1 数字口径的补证(第三轮的三个"待补证"全部落实) - -| 被质疑论断 | 裁决 | 证据 | -|---|---|---| -| "analysis 三份实现"证据链断裂 | **成立,证据链已补齐**(§2.5 已更新行号)。第三轮只找到 1 份是因为漏了 CLI 的 4 条硬编码 SQL 常量(`pchronicle-cli/src/lib.rs:1944-2028`,由 L1852-1855 的 `AnalysisCommand` 分派消费)和 `explorer.rs` 的 `analyze`(L440)+`dimension_aggregates`(L782)。三份=CLI 硬编码 SQL + explorer Rust 聚合 + compile 管线,置信度升为**高** | 见 §2.5 | -| "9 种格式"口径不明 | **口径钉死**:7 个 `DocumentFormat` 登记变体(`format.rs:11-26`,第三轮实测一致)+ 2 个未登记表示(`formats/llm.rs` LLM payload、ACTF 内藏 OpenClaw 子格式)= 9。§2.2 已补充口径说明 | `format.rs:11-26` | -| "全 crate 仅 2 个 trait"会被抓漏洞 | **第三轮的提醒成立,已修正措辞**:自有 trait 2 个(`ChronicleEventRecordExt` pub、`QueryDocumentSource` pub(crate)),另有 5 处对 DataFusion 外部 trait `TableProvider` 的实现。§1 亮点已改为带口径的表述 | `formats/events.rs:48`、`document_source.rs:28`、5 处 impl | - -### 6.2 事实性裁决 - -**(a) 故障注入 hook 的位置——双方各对一半,真相是更多。** - -- 本文档第一版写"`store/mod.rs:301-406`",实际路径是 `store/storyline/mod.rs:292-317`(路径截断笔误,已修正); -- 第三轮写"hook 在 `projection/storyline.rs:28-34`,`writer_control.rs` 里没有"——`projection/storyline.rs` 的 hook 属实,但第三轮漏掉了 `store/storyline/mod.rs` 里的另外两组(`CREATE_AFTER_EMPTY_READ_BARRIER` L302、`REPLACEMENT_AFTER_CURRENT_READ_BARRIER` L313); -- **事实全貌:4 组全局 barrier/故障注入 hook,分布在 2 个文件,都不在 `writer_control.rs`**。本文档从未把 hook 归于 writer_control(第三轮引用的"安到 writer_control"是对本文档 §2.1 的误读),但路径确实写错过。实质观察(并发协议需要故障注入才能测试)经三轮核实**反而被加强**——hook 比任何一方说的都多。 - -**(b) acceleration.rs 的位置与定性。** - -本文档自始至终引用的是 `server/acceleration.rs`(即 CLI crate 的 server 子模块),第三轮先误判本文档"说它在核心 crate",随后自行纠正并确认位置——**此项无分歧**。接受第三轮的两点改进并已并入 §2.4:标注完整 crate 路径;补充"保守可降级加速层、Catalog 仍是 source of truth"的定性。该定性微调**不改变结论**:1762 行的 sqlparser 重写器 + 3 套内存索引对"物化小表让 DataFusion 自己剪"仍是负和账,但它位于 CLI 层、可整体丢弃、不污染核心,因此 v2 清单中其优先级维持 P0(收益/风险比高)而非升级为"核心引擎问题"。 - -### 6.3 三轮汇合后的最终刀法(置信度标注版) - -| 优先级 | 动作 | 置信度 | 汇合情况 | -|---|---|---|---| -| P0 | 抽 `cas_store` 原语,三 store 下沉复用 | 高 | 三方独立证实同构 | -| P0 | unknown_fields → serde flatten 单路径 | 高 | 三方独立证实 flatten 已存在 | -| P0 | acceleration → DataFusion 下推 + 物化小表(CLI 层) | 高 | 第一轮提出,第三轮确认位置与定性 | -| P1 | 交换格式收敛:2 存储权威 + 其余降级纯 import codec | 高 | 三轮方向一致 | -| P1 | TableProvider 5→2(catalog → DataFusion 原生 union) | 高 | 第一轮提出,第三轮验证 5 处 impl 存在 | -| P1 | analysis 三份实现 → 统一 compile 管线 | **高**(证据链已补齐) | 第一轮提出,第三轮质疑后补证成立 | -| P1 | 删 SingleWriter 双写模式 | 高 | 第二轮发现,未受质疑 | -| P2 | ACTF benchmark 语义剥离出 hub | 中 | 三方证实泄漏,剥离方案待设计 | -| P2 | 空 mapping 目录、双 API 前缀、onboard 静态化等 | 高 | 低垂果实 | - -**三轮核验的元结论**:本报告的所有 P0/P1 刀口均已被至少两方独立核实;第三轮的全部质疑已闭环——要么是口径问题(已钉死),要么是双方各对一半(hook 位置,真相更强)。没有任何一刀因交叉核验而被撤销,反而有两刀(analysis 三份、hook 信号)因质疑而被加强。可以进入重构提案阶段。 - ---- - -## 7. 施工清单 Review(§6.3 的可执行性审查) - -以 §6.3 为施工蓝本逐条审查。**总评:刀口选择正确、置信度可信,但作为施工列表缺三样东西——依赖顺序、验收标准、以及 2 个在前几轮丢失/倒挂的条目。** 直接照单施工会在两处卡住。 - -### 7.1 逐条裁决 - -| 条目 | 施工裁决 | 问题 | -|---|---|---| -| P0 cas_store 原语 | ✅ 可施工,**但需前置一个小 PR** | ① SingleWriter 删除(P1)应**前移进本刀**:否则原语必须参数化一个即将死掉的模式,提取面凭空变大。② `CAS_RETRIES` 三个 store 为 32/32/64,统一值需显式决策(manifest 的 64 是有意的还是随手写的,无从考证——建议统一为 64 并留注释)。③ 抓手确认:三个 store 各有独立测试 mod(attempt_registry:376、run_control:540、manifest 内),行为保持型重构可验收 | -| P0 unknown → flatten | ⚠️ **顺序有坑** | 与 P1 格式收敛存在依赖倒挂:若先做 flatten,要改写 `convert/actf.rs` 等约 170 行×若干的捕获逻辑——而这些文件在格式收敛后**整个被删**,纯返工。正确顺序:先做格式收敛的**范围决策**(哪些 codec 幸存),再对幸存者做 flatten | -| P0 acceleration | ✅ 可施工,**但验收标准缺失** | 已核实前端 5 个文件(`llm_settings.rs`/`analysis.rs`/`result_explorer.rs`/`analysis_agent.rs`/`components.rs`)真实消费 evidence 接口——这不是无人使用的死代码。拆除必须有**延迟回归门槛**(fixture 数据集 p50/p95 前后对比),否则是盲拆。与 P1 catalog 合并有隐含依赖:acceleration 注入的 `_file_` 谓词由 catalog provider 下推消费,先砍 acceleration、后并 catalog 的顺序是对的,但清单未写明 | -| P1 格式收敛 + P1 TableProvider 5→2 | ⚠️ **应合并为一个 epic** | 5 个 codec provider 的删除本来就是格式收敛的组成部分,拆成两条独立 P1 会造成大量中间态(codec 还在、provider 已删,或反之)。另缺**外部兼容策略**:`DocumentFormat` 是公开枚举、import/export 是 CLI 公开接口,需要一个 deprecation/alias 计划,否则是 breaking change | -| P1 analysis 三合一 | ✅ 可施工,**与 P2 有一条顺序倒挂** | 应先做纯机械的 `analysis_compile.rs` 移 crate(P2、零行为变化),再做三合一(行为变化)。否则统一工作要在错误的位置做一遍再搬家。验收标准建议:CLI `analysis` 子命令对 fixture 数据集做 **golden diff**(统一前后 SQL 结果等价) | -| P2 各项 | ✅ 无异议 | 空目录、双前缀这类可随手热身 | - -### 7.2 清单缺漏(三轮评审中有、施工清单中丢了的) - -1. **多跳 `_storyline` envelope 删除**——第二轮 P1 明确提出("unknown 无损降为单跳"),§6.3 里丢失了。应并入格式收敛 epic。 -2. **`openai_corpus.rs` 的转换逻辑移入 `convert/`**——第一、二轮都点名的边界统一,属格式收敛 epic 的子任务。 -3. **横切验收基建**:整个清单没有一条性能回归门。建议先建一个最小 benchmark fixture(现成的 benchmark/ 目录数据即可)+ p50/p95 报告脚本,作为 P0-3 和 P1 catalog 两刀的共享门槛。 -4. **构建耦合提示**:CLI 通过 build.rs `include_dir!` 嵌入前端 WASM,所有动 CLI server 层的 PR 构建失败会连带前端——施工顺序上应先解耦(asset 改运行时加载或 feature-gate),否则每个 server 层 PR 都背负双端构建。 - -### 7.3 修正后的 PR 序列 - -``` -PR0 热身:删空 mapping/ 目录 ×2、/api 双前缀留一、echo→dev-bin、revisions 删 - (~150 行,零风险,验证 CI 通路) -PR1 删 SingleWriter 双写模式(独立小 PR,缩小 cas_store 提取面) -PR2 cas_store 原语 + 三 store 迁移(1 个新模块 PR + 3 个迁移 PR) - 验收:现有测试全绿 + 原语单测(并发互斥/CAS 重试/本地锁)+ 三 store 测试不动 -PR3 analysis_compile.rs 移到 CLI crate(纯移动,零行为变化) -PR4 格式收敛 RFC(决定 2 权威 + import codec 幸存清单 + deprecation 计划) - → 执行 PR:codec 降级 + provider 5→2 + unknown flatten(对幸存者)+ envelope 删除 - + openai_corpus 移 convert/ -PR5 性能门基建(benchmark fixture + p50/p95 报告) ← 可与 PR1-4 并行 -PR6 acceleration 拆除(验收:PR5 门槛内 + 前端 evidence 功能回归) -PR7 analysis 三合一(验收:golden diff) -PR8 catalog → DataFusion 原生 union(依赖 PR6:_file_ 裁剪的归宿先定) -PR9 P2 余项:agenticmd 砍写路径、onboard 静态化、lease 续约降级评估 -``` - -依赖关系:PR1→PR2→(PR4 可并行);PR5→PR6→PR8;PR3→PR7。关键路径 = PR0→PR1→PR2→PR4,约占总收益的一半以上。 - -### 7.4 范围合规 - -全部条目落在 `persisting-pchronicle` / `persisting-pchronicle-cli` 两个 crate 及 `pchronicle-web` 构建配置内,符合 AGENTS.md 默认 scope(不触碰 queue/search/TTAS/dlcapt)。验收命令建议用 `-p persisting-pchronicle -p persisting-pchronicle-cli` 定向跑,避免拉入排除子系统。 diff --git a/docs/superpowers/reviews/2026-08-23-product-phase-review.md b/docs/superpowers/reviews/2026-08-23-product-phase-review.md deleted file mode 100644 index e8b9fb51..00000000 --- a/docs/superpowers/reviews/2026-08-23-product-phase-review.md +++ /dev/null @@ -1,114 +0,0 @@ -# 产品阶段性 Review:定位、架构与功能暴露路线 - -## Status - -- 评审时间:2026-08-23 -- 覆盖范围:pChronicle Web 全部功能面(后端 17 条路由、前端 12 个模块、20 份 spec)、`pchronicle serve` 数据链路、Datasets / Runs / Run Detail / Analyze 四个界面(基于 2026-08-23 实机截图) -- 评审视角:产品定位(PM)+ 分布式系统 / 存储 + Agent 生态竞品(LangSmith、Laminar、Langfuse、Phoenix) -- 性质:项目执行阶段 review,结论供下一阶段排期参考 - -## 结论摘要 - -pChronicle 当前的形态是「单二进制本地 Agent 轨迹仓库 + 分析工作台」:files-first、SQL-first、WASM 前端内嵌、Copilot 兜底。三个核心判断: - -1. **定位差异化成立**。竞品全是 SaaS pipeline-first,数据在他们云上;pChronicle 数据永远在用户磁盘上。对企业内部数据、科研数据集是刚需,SaaS 方案在这些场景无法进入。 -2. **架构是「存储正确」的**。Dataset mount + Warehouse 虚拟根 + `_file_` 前缀是干净的数据湖抽象;Report 错误策略让坏数据降级而不阻塞;bounded query 在引擎层做了资源边界。 -3. **最大的杠杆不在建新能力,而在暴露已建成的能力**。后端约一半能力(导出、revisions、events、multi-storage、compare)已建成或已有 spec,但没有 UI 入口,产品回报为零。 - -## 现状盘点:能力分层与 UI 暴露度 - -![pChronicle 能力分层与 UI 暴露度](assets/2026-08-23-capability-layers.svg) - -约一半的后端能力已建成(或已有 spec)但没有 UI 入口,产品回报为零。逐项明细: - -| 层 | 能力 | UI 暴露状态 | -|---|---|---| -| L1 数据与存储 | dataset mounts、catalog treemap | ✅ 已暴露(Datasets 页) | -| L1 | error sources | ⚠️ 部分暴露(红色横幅,无管理操作) | -| L1 | `/revisions` 数据集快照 | ❌ 后端已有,无 UI | -| L1 | 多 Dataset 挂载 | ❌ spec 已批准(2026-08-23),未实现 | -| L2 查询引擎 | query console(tables + SQL) | ✅ 已暴露 | -| L2 | evidence bounded 查询 | ✅ 已暴露(Analyze agent 消费) | -| L2 | `/export/har`、`/export/otlp` | ❌ 后端已有,无 UI | -| L3 派生视图 | explorer runs / tree / turns、storyline、trace + span timeline | ✅ 已暴露 | -| L3 | `/events` 原始事件流 | ❌ 后端已有,无 UI | -| L3 | trajectory compare | ❌ spec 已写(2026-08-22),未实现 | -| L4 分析与协作 | analyze agent(plan-review-run)、analysis sessions | ✅ 已暴露(Analyze 页) | -| L4 | signals 检测器(Laminar 式) | ❌ 仅有产品讨论,无 spec | -| L4 | deep link / 分享 / 报告导出 | ❌ 未建设 | - -## Review 发现 - -### 产品定位层 - -- **在「轨迹查看器」与「分析平台」之间摇摆**。Span Timeline、Trace、JSON renderer 是世界级的查看体验;但分析侧(Analyze agent、Query Console)的能力密度没有透出来。用户第一印象会是「好看的 trace viewer」,而非「能回答质量问题的分析平台」。 -- **两个 AI 入口的关系没有交代**。Copilot(对话式问答)与 Analyze(plan-review-run 可复算取证)能力重叠,用户不知道何时用哪个。建议明确分工叙事并在两个入口互相引流。 -- **Query Console 是埋没的杀手锏**。「对轨迹数据写 SQL」是对 SaaS 竞品最硬的差异,但藏在开发者角落:无 schema 引导、无示例、无保存。 - -### 架构层(分布式 / 存储) - -做对了的: - -1. Dataset mount / `_file_` 前缀抽象,天然支持多数据集与路径钻取(catalog treemap 是其直接产物);multi-storage spec 使其成为 CLI 一等公民。 -2. Report 错误策略 + error sources 显式暴露(624MB 超限文件降级为 error source 而非炸掉启动,2026-08-22 修复)——「坏数据不阻塞好数据」。 -3. Bounded query(max_rows / max_bytes)引擎层资源上限;SQL 执行错误映射为带详情的 400(2026-08-22 修复),查询路径已工程化成熟。 - -架构债: - -1. **数据新鲜度是手动的且不可见**。`POST /catalog` 刷新存在,但 UI 无「我看到的是哪个快照 / 是否有新文件」的心智模型。分布式系统用户对 staleness 极其敏感。 -2. **单用户单进程**。无并发写、无协作故事。短期可接受,产品叙事只能停留在「个人 / 小队工具」。 -3. **`/revisions` 已付工程成本但未收产品回报**。 - -### 界面交互层(基于 2026-08-23 实机截图) - -主链路 Datasets → Runs → Run Detail(Trace / Analysis)→ Analyze 通畅,「先看分布再钻取」心智正确。详细交互问题见当日会话记录(P0 loading 反馈缺失、tile 颜色无语义、URL 不反映状态等)。产品层级补充: - -- **P1**:Analyze 页首屏价值密度低——大标题 + 空的 Recent analysis 把核心能力(问题输入)推到中下区域。 -- **P1**:Run Detail 加载 >10s 仅显示 "Building trajectory evidence…",需要分阶段 skeleton。 -- **P2**:Coverage 卡 0 值行、Duration/Tokens "—" 缺解释,属视觉噪音。 - -## 行动项 - -候选功能按「用户价值 × 实现成本」排布如下: - -![候选功能价值-成本矩阵](assets/2026-08-23-feature-priority-matrix.svg) - -### 立即做(高价值低成本:给已有 API 加 UI) - -| ID | 行动项 | 优先级 | 验收标准 | -|---|---|---|---| -| A1 | Run Detail 工具栏增加导出 HAR / OTLP 按钮 | P0 | 任一 run 可一键下载 HAR 与 OTLP 文件 | -| A2 | 全局 URL 状态(page / dataset / run / catalog 路径),刷新与分享不丢状态 | P0 | 复制 URL 打开还原同一视图 | -| A3 | 顶部 catalog 快照状态条:快照时间 + 新文件待扫描提示 + 手动/自动刷新 | P1 | staleness 可见且可操作 | -| A4 | Query Console 侧栏 schema 浏览器:列级说明 + 示例值 + 一键插入 | P1 | 不读文档即可写出正确 SQL | -| A5 | error source 管理面板:失败原因(如超 max_file_bytes)+ 调整上限重试 | P1 | 624MB 文件可通过面板处理后入库 | - -### 规划做(高价值高成本:产品叙事下一级台阶) - -| ID | 行动项 | 优先级 | 说明 | -|---|---|---|---| -| B1 | trajectory compare 工作区 | P1 | spec 已完成(2026-08-22),Pin + 对齐 diff;A/B 评估前置 | -| B2 | signals 检测器(Failure / Logic / Task / Friction / Hallucination / Intent) | P1 | 参照 Laminar 模板;先落 Failure + Task,Runs 列表加信号列,CompactOverviewStrip 加 risk badges | -| B3 | revisions 时间旅行 UI | P2 | `/revisions` 已有;数据集版本切换,配 B1 可做版本差异审计 | -| B4 | 分析报告导出(Markdown / HTML) | P2 | Analyze 产出脱离 session,完成「取证→结论→交付」闭环 | - -### 顺手做 - -| ID | 行动项 | 说明 | -|---|---|---| -| C1 | 多 dataset 切换器 | 依赖 multi-storage spec 落地 | -| C2 | SQL 收藏 / 模板 | Query Console 增强 | -| C3 | `/events` 原始事件流视图 | power user 排障 | - -## 附录:竞品参照——Laminar Signal 角色分工 - -行动项 B2(signals 检测器)的产品化参照。Laminar 把 agent trace 的自动分析拆成 6 个「专职检测员」,横轴是问题阶段(意图理解 / 推理与执行 / 输出验证),纵轴是受影响对象(agent / 用户 / 任务)。关键启示:**Friction Detector 把 UX 问题从「任务是否完成」中独立出来**——agent 可能完成了任务但用户已被糟糕交互折磨,这是 trajectory 分析工具最容易忽略的维度。pChronicle 落地顺序建议:先 Failure Detector(Behavior 已有基础)与 Task Evaluator(直接回答完成度),再 Friction Detector,LLM judge 类(Hallucination / Logic / Intent)后置。 - -![Laminar 6 Signal 角色分工矩阵](assets/2026-08-23-laminar-signal-roles.svg) - -## 遗留与风险 - -- 既有失败测试 `status_reports_projection_stale_and_safe_errors`(已验证与近期改动无关),需单独排查。 -- 2026-08-22 报告的 WASM panic 疑似卡死状态伴生现象,未复现;若再出现需保留完整控制台堆栈。 -- Analyze 页与 Copilot 的双入口叙事未定,影响 B2 的入口设计,需在 signals spec 前决策。 -- 单用户架构是有意选择还是过渡状态,影响 B4(报告导出)之后的协作类功能排序,建议下阶段明确。 diff --git a/docs/superpowers/reviews/2026-08-28-pchronicle-design-impl-review.md b/docs/superpowers/reviews/2026-08-28-pchronicle-design-impl-review.md deleted file mode 100644 index d154f4b8..00000000 --- a/docs/superpowers/reviews/2026-08-28-pchronicle-design-impl-review.md +++ /dev/null @@ -1,162 +0,0 @@ -# pChronicle 设计与实现整体 Review - -## Status - -| 项 | 内容 | -|---|---| -| 评审时间 | 2026-08-28 | -| 覆盖范围 | `crates/persisting-pchronicle`(约 51k 行 Rust / 99 个源文件)全部非 `search` 源码,含 `README.md` 与 `docs/src/rfcs/0003-pchronicle-ownership.md` 的对照核实 | -| 排除范围 | `src/search/`、`src/operations/`(search 适配层)按项目默认约定排除;`persisting-dlcapt` 不在范围 | -| 评审方式 | 五个子系统并行探查后交叉核对,对关键断言逐条读原文核实(见文末「核实清单」) | -| 关联消费者 | `persisting-pchronicle-cli`、`persisting-gateway`(pPilot / pVisor 通过 spawn `pchronicle` 二进制消费,不链接库) | - -## 结论摘要 - -pChronicle 的核心设计是对的,而且好得超出预期。真正的债务不在概念层,而在**执行一致性**:对外承诺的能力位(streaming、filter exact)和预算(unknown fields limits、查询行数)有相当一部分没有在实现里落地;README 描述的四模块门面没有编译约束;几个核心模块已经膨胀到 2000 行量级。这不是一个需要重新设计的系统,而是一个需要把已经写在文档里的承诺补齐、然后拆文件的系统。 - -三个最重要的判断: - -1. **单枢纽格式转换 + epoch-fenced 事实层 + CURRENT 原子发布 + watermark 投影,这四件事都做扎实了**,还配了真实竞争的并发测试。这是这个 crate 值得保留的资产,任何重构都不该破坏它们。 -2. **唯一能被外部输入直接触发的资源耗尽路径是 SQL 查询入口**:`query()` / `query_jsonl()` 全量 collect 且默认无内存上限。有预算的流式路径已经写好了,只是便捷 API 绕过了它。 -3. **README 写得非常具体(承诺了无损边界、能力矩阵、预算行为、门面结构),这是优点**——但具体的承诺一旦漂移,代价比含糊的文档更大,因为下游会当契约用。目前有 5 处明确漂移。 - -## 现状盘点 - -### 分层评分 - -设计 = 抽象与边界是否成立;实现 = 代码是否兑现了该抽象。 - -| 子系统 | 设计 | 实现 | 最该关注的一件事 | -|---|:---:|:---:|---| -| 格式转换枢纽 `formats/` + `convert/` | A | B | capabilities 里的 `streaming_input` 与 codec 内部无界 unknown limits 都不是实话 | -| unknown fields 保真 | A | A− | 机制本身可证明;缺 proptest(最复杂的不变量只有单测) | -| 事实层 `events.lance` + manifest | A | A− | `FilterPushdown::Exact` 无条件上报;replay 两趟 scan | -| Storyline Lance + CURRENT | A− | B | `mod.rs` 已 1940 行;local CURRENT 写入不做 etag 比较,跨进程只靠 flock | -| 投影管线 `projection/` | A− | B+ | watermark / lineage 逻辑扎实,但缺 kill -9 中途 sync 的恢复测试 | -| 写入队列 `append_queue` | B+ | B | `in_flight` 语义错位 + 忙等;maintenance channel 满时静默丢工作 | -| 查询引擎 `query_engine` | B+ | C+ | 只读门禁与 `_file_` join 守卫是好设计,但便捷 API 无预算、默认无内存上限 | -| AgenticMD 编解码 | B+ | B | byte-span upsert 很漂亮;无 `length` 时的 marker 截断是唯一真 fragility | -| `layout/` + `resolve` 路径推断 | C+ | C+ | 800 行启发式,行为由文件系统驱动,无性质测试 | -| 公共 API 门面 | B | C | 四模块是文档意图,不是编译约束;CLI 深度绑定 storage 全表面 | - -### 已建成的设计资产 - -| 资产 | 位置 | 说明 | -|---|---|---| -| 单枢纽格式转换 | `convert/mod.rs:1-12` | 所有外围格式只与 `StorylineDocument` 互转,转换复杂度 O(N) 而非格式两两组合的 O(N²)。`TrajectoryFormat` trait + 静态 registry 让新增 codec 只需 impl + 注册 | -| unknown fields 无损机制 | `formats/unknown_fields.rs:362-401`、`815-817` | RFC 6901 JSON Pointer + 按源格式命名空间 + version-1 `_storyline` envelope + 冲突一律 fail closed。跨格式多跳有集成测试 | -| 事实层 epoch fencing | `store/events/manifest.rs:187-251`、`472-477` | writer 先写私有 segment 再做 epoch-fenced CAS 发布;崩溃在发布前只留不可达的 Lance 版本,读者 pin manifest 完全免受影响 | -| CURRENT 原子发布 | `store/storyline/mod.rs:943-975`、`991-1022` | 三表 + objects 版本全部就绪才移动 CURRENT;失败释放 lease 并删除未提交 generation。读者永远看到完整快照 | -| 投影 lineage 保守优先 | `projection/storyline.rs:430-432`、`237-240`、`271-274` | watermark 用 `fact_version` / `fact_rows`,纯 compaction 的 `layout_revision` 变化不算 stale;recipe 变更或 watermark 非单调时返回 `RequiresRebuild` 而不是猜 | -| content offload + 延迟物化 | `store/storyline/datafusion.rs:191-200` | 大 payload 进 `objects.lance`,表内只留 preview/ref,查询走 `ContentHydrationExec`。这一层最实在的性能设计 | -| 时间戳保留源形态 | `formats/timestamp.rs:7-17` | `StorylineTimestamp` 同时保留 wire scalar 和 canonical instant,拒绝亚纳秒精度。比统一转 RFC3339 字符串高明一档 | -| bounded 流式解析 | `formats/common/json_stream.rs:77-196`、`205-291` | 手写 depth / string escape 跟踪 + 复用 buffer 的 `read_bounded_json_object`,安全与性能兼顾,有 proptest | -| analysis 编译器分层正确 | `analysis_compile.rs:4-5`、`196-379` | `AnalysisSpec` → 只读 SQL,白名单 intent / grain / measure / dimension,明确不碰 DataFusion 执行 | -| 测试约定写进文档并被遵守 | `tests/README.md:52-62`、`store/events/manifest.rs:777-801` | 明确禁止「用进程级 `root_write_lock` 把并发测试串行化后宣称覆盖了 CAS」,要求断言精确计数、回归测试先证明 bug;有 32-writer CAS 竞争测试 | - -## Review 发现 - -### P0 —— 正确性与资源,建议尽快处理 - -| ID | 问题 | 位置 | 影响 | -|---|---|---|---| -| P0-1 | SQL 查询入口无行/字节预算,默认无内存上限 | `store/query_engine.rs:348-370`(`query` / `query_jsonl` 全量 collect)、`442-481`(`memory_limit_bytes` 默认 `None`) | 对外暴露 SQL 等于暴露 DoS 面。流式有预算的路径 `write_query_jsonl_bounded` 已实现且 CLI 在用,但便捷 API 无任何上限,也没有 query timeout | -| P0-2 | unknown fields 预算没有贯通到各 codec | `formats/atif.rs:328`、`formats/actf/mod.rs:173`、`formats/openai_corpus.rs:230` 硬编码 `UnknownFieldLimits::default()`(= `usize::MAX`);`document.rs:76` 在 decode 之后才校验 `DocumentCodecOptions` | 畸形输入的超大 unknown payload 会先完整进内存,最后才可能被拒。README 承诺的「显式配置的有限上限」在 codec 内部拿不到 | -| P0-3 | 解码路径存在静默数据丢失 | `formats/codex.rs:145`、`formats/claude_code.rs:148`(`from_rfc3339(..).ok()` 丢弃非法时间戳);`formats/common/jsonl.rs:99`(JSON 解析失败降级为整段 string)、`:49`(multimodal 数组拼成单字符串) | 与 crate 其他部分一贯的 fail-closed 风格直接矛盾。事实层丢时间戳 / 丢结构且不报错,下游无从发现 | -| P0-4 | 每次调用新建 Tokio runtime | `discovery.rs:95-100` `expand_story_locations_blocking` | 在已有 runtime 的线程上调用会嵌套 runtime(panic)或阻塞 worker;每次调用还付一次多线程 runtime 构建成本 | - -### P1 —— 设计一致性与可维护性 - -| ID | 问题 | 位置 | 影响 | -|---|---|---|---| -| P1-1 | 四模块公共门面只是文档意图,不是编译约束 | `lib.rs:31` `pub mod analysis_compile`;`lib.rs:71-81` search feature 下 `pub use messages::*` / `operations::*`;`tests/public_api.rs` 只是正向编译测试 | README 声称「默认功能面只通过四个模块组织」,实际默认就有 5 个公开模块,search 开启后 6 个 + 一批 crate 根 re-export。没有 `compile_fail` 守卫,回归无法拦住 | -| P1-2 | capabilities 上报与实现脱节 | `formats/actf/mod.rs:42-48` 声明 `streaming_input: true` 但 `:145-153` 是 `read_to_string` 全量读(Storyline / OpenAI 同);`store/events/datafusion.rs:124-127` 对任意 `Expr` 无条件返回 `FilterPushdown::Exact` | README 把「能力由实际打开的 `DocumentSource` 报告,不按格式名推断」当设计卖点,但报告值本身有部分不可信。Exact 是否成立取决于 Lance 对该 Expr 的完整求值,缺验证测试 | -| P1-3 | 多个模块已超过可维护体量 | `store/storyline/mod.rs` ≈1940 行(`replace_storyline_stream_with_projection` 单函数 ~330 行)、`formats/actf/convert.rs` ≈1961、`formats/openai_corpus.rs` ≈1915、`store/catalog/mod.rs` ≈920、`store/events/mod.rs` ≈1095、`layout/resolve.rs` ≈824 | 读写路径、DataFusion 适配、lease、maintain 混在同一文件,改动半径大,评审成本高 | -| P1-4 | append 队列的关停语义靠隐式顺序 + 忙等 | `append_queue.rs:132-151`(`in_flight` 只覆盖 `try_send` 窗口)、`:166-168` 与 `:535-537`(`yield_now` 自旋);`:490-493`(maintenance channel 满时只 warn) | `in_flight` 名字暗示「未完成的工作量」,实际不表示队列深度;`finish()` 等到 0 也不代表队列已空,正确性依赖 `Finish` 消息顺序而非计数。compaction 可能长期滞后 | -| P1-5 | AgenticMD 缺 `length` 时按 marker 子串截断 body | `agenticmd/codec.rs:249-253`;`docs/src/pchronicle/reference/agenticmd.md:25-27` 明确允许省略 length | 手工编辑过的文件若正文含 `