docs: record browser verification

This commit is contained in:
Yoilun
2026-05-25 22:03:21 +08:00
parent 0047448e9d
commit 8c1093a53c
7 changed files with 50 additions and 14 deletions

View File

@@ -56,7 +56,7 @@ pnpm test
pnpm build
```
如果需要浏览器视觉验证,由主智能体或可用浏览器工具访问 `http://127.0.0.1:13083/` 后记录截图结果;不要伪造截图记录
浏览器视觉验证已在 2026-05-25 使用本机 Chrome 访问 `http://127.0.0.1:13083/` 完成,覆盖项目视图、工作流视图、智能体视图、草稿和设置页。内置浏览器插件若返回 `Browser is not available: iab`,可改用 Chrome 做只读页面核验,并在 `progress.md` 记录 fallback
## API 概览

View File

@@ -87,7 +87,7 @@ cd web
pnpm dev
```
前端开发地址为 `http://127.0.0.1:13083/`。前端按视图调用 API项目视图读取 `/api/projects``/api/runtime/threads`,工作流视图读取 `/api/workflow/events`,智能体视图读取 `/api/agents`,并仅对当前选中的智能体调用 `/api/agents/{id}/validate``/api/agents/{id}/write`。静态示例数据仅在接口连接失败时作为 fallback 展示,并必须明确标注“示例/等待连接”;真实接口返回空列表时展示空状态和来源证据,不回退到示例数据。前端可保留 `local_sample``api_missing` 等内部 source kind但用户界面必须显示中文来源和 `高 / 中 / 低` 置信度。
前端开发地址为 `http://127.0.0.1:13083/`。前端按视图调用 API项目视图读取 `/api/projects``/api/runtime/threads`,工作流视图读取 `/api/workflow/events`,智能体视图读取 `/api/agents`,并仅对当前选中的智能体调用 `/api/agents/{id}/validate``/api/agents/{id}/write`。静态示例数据仅在接口连接失败时作为 fallback 展示,并必须明确标注“示例/等待连接”;真实接口返回空列表时展示空状态和来源证据,不回退到示例数据。前端可保留 `local_sample``api_missing` 等内部 source kind但用户界面必须显示中文来源和 `高 / 中 / 低` 置信度。2026-05-25 已通过 Chrome 验证项目视图、工作流视图、智能体视图、草稿和设置页;内置浏览器插件返回 `Browser is not available: iab`,视觉核验使用本机 Chrome 完成。
## API Overview
@@ -125,6 +125,6 @@ pnpm dev
- Codex 内部 SQLite schema 可能变化。
- 运行状态由多来源推断,必须显示置信度。
- 真实 SQLite 读取已覆盖临时测试库;如果真实 Codex schema 新增字段或缺少可选字段,应继续走 schema-aware 查询和来源证据,而不是让 API 500。
- Agent 列表接口返回原始 TOML 文本;智能体编辑区展示的是接口返回的已解析字段,并在代码区说明“接口未返回原始 TOML”
- 浏览器视觉验证需要可用浏览器工具或主智能体执行;文档记录不得伪造截图结果
- Agent 列表接口当前返回原始 TOML 文本供草稿编辑;前端仍必须只在“校验 TOML -> 查看差异 -> 创建备份并写回”的显式流程中写回
- 内置浏览器插件可能不可用;若返回 `Browser is not available: iab`,可使用本机 Chrome 做只读页面核验,并在进度记录中注明 fallback
- 写回只覆盖单个已有 agent TOML不支持创建新 agent、批量写回或自动保存草稿。

View File

@@ -184,7 +184,16 @@
| 2026-05-25 | `cd web && pnpm test` | PASS | Phase 7 前端单测通过13 个测试全部通过 |
| 2026-05-25 | `cd web && pnpm build` | PASS | Phase 7 前端生产构建通过Vite 构建成功 |
| 2026-05-25 | `git diff --check` | PASS | Phase 7 whitespace 检查通过 |
| 2026-05-25 | Browser visual verification | PENDING_MAIN_AGENT | 阶段 7 不伪造浏览器截图;待主智能体执行并记录 |
| 2026-05-25 | Browser plugin visual verification | DONE_WITH_CONCERNS | 内置浏览器仍返回 `Browser is not available: iab`,改用本机 Chrome 执行同等页面核验 |
| 2026-05-25 | Chrome visual verification | PASS | `http://127.0.0.1:13083/` 项目视图、工作流视图、智能体视图、草稿和设置页均显示中文;真实项目/线程矩阵、工作流阶段与监管、智能体 TOML 草稿校验/差异/备份写回控件可见 |
| 2026-05-25 | `cd web && pnpm test` | FAIL | TDD 红灯:设置页仍显示“本阶段不会写回 / 不保存智能体 TOML”与 Phase 6 单文件写回能力冲突 |
| 2026-05-25 | `cd web && pnpm test` | PASS | 设置页安全文案修复后前端单测通过14 个测试全部通过 |
| 2026-05-25 | Chrome settings re-check | PASS | 设置页显示“安全配置摘要”“仅校验后单文件写回”“不自动保存或批量写回”,旧文案不再可见 |
| 2026-05-25 | Final code review | PASS | 代码审查员复核无阻塞问题;建议将智能体页“只读编辑区”改为更准确的草稿编辑文案 |
| 2026-05-25 | `cd web && pnpm test` | FAIL | TDD 红灯:智能体页仍出现“智能体只读编辑区 / 只读编辑区”旧文案 |
| 2026-05-25 | `cd web && pnpm test` | PASS | 智能体页改为“字段预览与草稿编辑区”后前端单测通过15 个测试全部通过 |
| 2026-05-25 | `cd web && pnpm build` | PASS | 智能体页审查建议修复后前端生产构建通过 |
| 2026-05-25 | Chrome agent view re-check | PASS | 智能体视图显示“字段预览与草稿编辑区”,并保留校验 TOML、查看差异、创建备份并写回控件 |
## Bug Loop
@@ -217,3 +226,5 @@
| 6 | 写回备份/rename 前路径身份可能变化,且备份后并发修改可能被覆盖 | 写回加进程内临界区,记录 agents 目录和目标文件 inode identity备份前和 rename 前复核 identity 与 expectedHash | `go test ./internal/agents ./internal/server` PASS |
| 6 | validate/write POST 可接收超大 body、trailing JSON且错误响应透传路径和英文系统错误 | validate/write 使用 1MiB `MaxBytesReader`、拒绝 trailing JSON并将错误映射为安全中文响应 | `go test ./internal/agents ./internal/server` PASS |
| 6 | 复核后到备份/rename 前仍有父目录路径替换窗口 | 使用 `Openat`/`Renameat` 将目标读取、备份、临时文件和 rename 绑定到已打开的 `agents` 目录 fd并继续复核目录路径身份和目标 hash | `go test ./internal/agents ./internal/server` PASS |
| 7 | 设置页安全边界文案停留在只读阶段,误导用户以为智能体 TOML 不会保存 | 改为“仅校验后单文件写回”,明确项目/运行线程/工作流仍只读,且不自动保存或批量写回 | `cd web && pnpm test` PASSChrome re-check PASS |
| 7 | 智能体页编辑区域文案仍叫“只读编辑区”,与草稿编辑和写回按钮不一致 | 改为“字段预览与草稿编辑区”,并补文案回归测试 | `cd web && pnpm test` PASSChrome re-check PASS |

View File

@@ -9,7 +9,7 @@
- [x] 所有阶段完成
- [x] Go 测试通过
- [x] 前端构建通过
- [ ] 浏览器验证关键页面
- [x] 浏览器验证关键页面
- [x] docs/project.md 记录目标、架构、配置、运行方式、安全边界和恢复方式
- [x] 无 blocking bug 或未处理高风险问题
@@ -24,7 +24,7 @@
| 4 | complete | 中文 UI 只读工作台 | 项目/工作流/智能体视图可浏览;空数据可用 |
| 5 | complete | API 集成和只读数据显示 | 前端连接只读 API显示真实 agent 数据和错误状态 |
| 6 | complete | 草稿、TOML 校验、diff、备份、写回 | 草稿不覆盖原文件;无效 TOML 阻止写回;备份成功后才能写回 |
| 7 | complete | 集成验证与文档 | 测试/构建通过;浏览器验证待主智能体执行;文档完整 |
| 7 | complete | 集成验证与文档 | 测试/构建通过;Chrome 浏览器验证关键页面;文档完整 |
## Errors Encountered
@@ -42,3 +42,4 @@
| 2026-05-25 | 6 | 规格审查发现 malformed TOML 会通过 `strconv.Unquote` 泄漏英文 `invalid syntax` | TDD 补 List/Validate/Write 中文错误断言后包装字符串解析错误 | 已通过最终验证 |
| 2026-05-25 | 6 | 安全审查发现写回 TOCTOU、备份后 CAS 缺失、POST body 无限制、错误响应泄漏路径/英文 | TDD 补目录替换、备份后修改、请求体限制和错误脱敏测试后加身份复核/CAS/MaxBytesReader/中文错误映射 | 已通过最终验证 |
| 2026-05-25 | 6 | 安全复审发现复核后到 createBackup/rename 前仍通过路径重新解析父目录 | TDD 补复核后替换 `agents` 为 symlink 测试后,将备份、临时文件和 rename 绑定到已打开的 agents dirfd | 已通过最终验证 |
| 2026-05-25 | 7 | 设置页仍显示“本阶段不会写回 / 不保存智能体 TOML”与单文件确认写回能力冲突 | TDD 补设置页安全文案测试后改为“仅校验后单文件写回”,并声明不自动保存或批量写回 | 已通过前端测试和 Chrome 页面验证 |

View File

@@ -1,5 +1,7 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import {
formatConfidence,
@@ -92,6 +94,27 @@ test('empty agent and settings copy stay Chinese', () => {
assert.ok(settings.every((item) => item.name !== 'Codex home'))
})
test('settings safety copy matches confirmed single-file writeback phase', async () => {
const thisFile = fileURLToPath(import.meta.url)
const viewPath = new URL('../views/SettingsView.vue', `file://${thisFile}`)
const source = await readFile(viewPath, 'utf8')
assert.doesNotMatch(source, /本阶段不会写回/)
assert.doesNotMatch(source, /不保存智能体 TOML/)
assert.match(source, /仅校验后单文件写回/)
assert.match(source, /不自动保存或批量写回/)
})
test('agent editor copy reflects preview and draft editing, not readonly-only mode', async () => {
const thisFile = fileURLToPath(import.meta.url)
const viewPath = new URL('../views/AgentView.vue', `file://${thisFile}`)
const source = await readFile(viewPath, 'utf8')
assert.doesNotMatch(source, /智能体只读编辑区/)
assert.doesNotMatch(source, /<p class="eyebrow">只读编辑区<\/p>/)
assert.match(source, /字段预览与草稿编辑区/)
})
test('normalizes empty runtime without falling back to fake real data', () => {
const runtime = normalizeRuntime({
items: [],

View File

@@ -140,10 +140,10 @@ async function writeDraft() {
</button>
</aside>
<section class="panel editor-panel" aria-label="智能体只读编辑区">
<section class="panel editor-panel" aria-label="字段预览与草稿编辑区">
<div class="panel-heading horizontal">
<div>
<p class="eyebrow">只读编辑区</p>
<p class="eyebrow">字段预览与草稿编辑区</p>
<h2>{{ selectedAgent?.name || '没有可显示的智能体' }}</h2>
</div>
<StatusBadge

View File

@@ -9,9 +9,9 @@ import { settings } from '../data'
<div class="panel-heading horizontal">
<div>
<p class="eyebrow">设置</p>
<h2>只读配置摘要</h2>
<h2>安全配置摘要</h2>
</div>
<StatusBadge label="接口只读" status="complete" source="计划文件" confidence="中" />
<StatusBadge label="配置受控" status="complete" source="计划文件" confidence="中" />
</div>
<div class="settings-list">
@@ -29,13 +29,14 @@ import { settings } from '../data'
<aside class="panel">
<div class="panel-heading">
<p class="eyebrow">安全边界</p>
<h2>本阶段不会写回</h2>
<h2>仅校验后单文件写回</h2>
</div>
<ul class="safety-list">
<li>不读取或展示 `.codex/auth.json`</li>
<li>不写入 Codex SQLite</li>
<li>不保存智能体 TOML</li>
<li>真实数据通过本阶段只读接口展示</li>
<li>智能体 TOML 仅在校验备份和确认后写回当前文件</li>
<li>不自动保存或批量写回</li>
<li>项目运行线程和工作流仍通过只读接口展示</li>
</ul>
</aside>
</section>