docs: record browser verification
This commit is contained in:
@@ -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 概览
|
||||
|
||||
|
||||
@@ -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、批量写回或自动保存草稿。
|
||||
|
||||
13
progress.md
13
progress.md
@@ -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` PASS;Chrome re-check PASS |
|
||||
| 7 | 智能体页编辑区域文案仍叫“只读编辑区”,与草稿编辑和写回按钮不一致 | 改为“字段预览与草稿编辑区”,并补文案回归测试 | `cd web && pnpm test` PASS;Chrome re-check PASS |
|
||||
|
||||
@@ -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 页面验证 |
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user