-
execution_log_file 的行生命周期 U-013 早就管好了,但从来没有代码真的往 日志文件里写过内容——src/execution_log.py 新增 append_log() 补上这条 缺失的写路径,设计成 run_fn 执行过程中随时可调用,不关心节点在做什么。 get_log() 按 offset/limit 分页读,download=true 时走原始文件流。 c_ws_log_tail(WS /api/ws/work-nodes/:node_exec_id/log)复用 U-024 手写 的 RFC 6455 机制,轮询 execution_event(log_appended);节点一旦转终态 (done/blocked/failed)服务端主动发关闭帧断开,不让客户端一直轮询。 p_log_retention_cleanup 实现成纯函数 run_log_retention_cleanup():过期 扫描 + max_total_size_mb 超限按最旧优先追加候选 + 单个文件删除失败只 记录不阻塞其余项,没有配调度器(不在本 Unit 覆盖范围),留给未来的 调度进程周期调用。 过程中意外抓到一个真的并发 bug:_Server.server_close() 关闭共享 sqlite 连接时原来没拿 conn_lock,如果这时候正好有个 WS 轮询线程在 另一边持锁执行 SQL,两个线程无同步地并发操作同一个 C 级 sqlite3 连接 对象,实测直接把解释器崩了(SIGSEGV)——U-024 就已经有这个隐患,这次 高频 WS 测试把时序窗口撞开了。修好后连续跑几十次全部稳定通过,记录 在 05 §5.4.1.3。 frontend/app.js 的 v_log_viewer 挂在 v_task_detail 每个 to-do 节点的 展开详情里,首次展开才建连接(懒加载),运行中态走 c_ws_log_tail 实时 滚动、终态走 c_execution_log_get 静态拉取,活跃连接在任务级刷新/离开 页面时统一关闭。真实服务器 + Node 原生 WebSocket/fetch 端到端验证过 实时追加与终态自动断开的完整链路。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
三个页面需要的读接口此前都不存在,本 Unit 一并建了: - c_task_list/c_task_get(03-C §3.2,此前无 Unit 认领):新增 src/task_query.py + GET /api/tasks、GET /api/tasks/:task_id。 c_task_get 的返回比 03-C 字面契约更完整——额外带上 work_graph_run(含解析后的 graph_manifest)+ 每个 run 的 work_node_execution 列表,因为 v_task_detail 的 to-do 树需要这份数据, 03-C 已订正补全。 - c_org_loop_route(U-016 已实现 route_org_loop(),从未接 HTTP)第一次 接上 POST /api/tasks/:task_id/route,v_task_detail 的人工干预 (manual_resume)按钮需要它。 - 预算护栏此前没有任何读接口(03-C 只写了 PUT),新增 budget_guardrail.list_budget_configs() + GET /api/settings/budget 给仪表盘预算条用。 frontend/app.js 补上真实的 #/(org graph 三节点卡片、当前任务概要、 预算条、事件时间线,全部通过 c_ws_subscribe 实时刷新)、#/tasks (关键字/状态/org_node 过滤)、#/tasks/:task_id(task 字段、to-do 树、 关联 artifact/bug_record、blocked_pending_human 告警条 + manual_resume 按钮)。路由改成对象形式支持挂载态清理,切页面时关掉上一个页面的 WebSocket 连接。v_graph_visualizer/v_log_viewer 子模块明确标成占位 提示(随 U-026/U-027 补上),不是假造内容。 顺带把 U-023 里因 c_task_list 当时不存在而简化的 related_task_id 换回真下拉,goal_composer/bug_feedback 提交成功后也改回跳转真实的 v_task_detail。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Python stdlib 没有 WebSocket 支持,src/ws_subscribe.py 手写 RFC 6455 握手(hashlib+base64 算 Sec-WebSocket-Accept)+ 帧编解码(服务端帧不 加掩码,客户端帧强制解掩码),不引入 websockets 之类第三方库 (05 §5.7)。 推送用轮询而非写路径 hook:execution_event 的写入分散在十几个调用点 (org_node_trigger/work_graph_execute/work_node_run/task_create/ bug_record/...),没有单一写入路径可以插桩,backend_server.py 的 _handle_ws_subscribe 劫持 ThreadingHTTPServer 连接后每 0.5 秒按 rowid 增量查一次 execution_event(project_id/可选 task_id 过滤), 轻松满足 REQ-12 的 ≤2 秒目标。断线重连按 03-C §3.14 走 REST 快照,不 在 WS 层做消息重放,新连接只看连接那一刻起的新事件。 daemon_threads = True 避免长连接 WS 线程阻塞进程退出。 验证:test_backend_server.py 用原始 socket 走真实握手+推送延迟断言; 另外用 Node 原生 WebSocket 客户端做跨实现互操作性验证,连真实运行的 服务器,从建连到收到 c_task_create 触发的真实推送全程走通。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
c_task_create(U-009 已实现的 task_create.create_task())第一次接上 POST /api/tasks。c_bug_report_create 此前完全没有实现,新增 bug_record.create_bug_report() + POST /api/bug-reports。 发现并订正 03-C 一处输入契约遗漏:c_bug_report_create 的 input_contract 没写 project_id,但 execution_event.project_id 是 NOT NULL、bug_record 表自己没有 project_id 列可以在 related_task_id 留空时兜底推导,字面上无法满足约束——按 c_task_create 同款处理方式把 project_id 变成必填,03-C 已订正。 frontend/app.js 补上 #/goals/new、#/bugs/new 真实交互;控制台还没有 "当前项目"状态的正式载体(v_dashboard 是 U-025 才做),project_id 暂存 localStorage,v_project_setup 创建成功时写入。related_task_id 因为 c_task_list 未被任何 Unit 认领,简化成文本输入而非下拉,等 U-025 补上 任务列表后再换。提交成功后原型写的是跳转 v_task_detail,该页面也是 U-025 才建,暂时改成原页面内展示确认信息。 端到端冒烟时额外发现一个真 bug:create_bug_report() 原本没校验 project_id/related_task_id 是否存在,坏 project_id 会在 execution_event 插入时触发未捕获的 IntegrityError,请求直接 500——补了存在性校验, 改为干净的 INVALID_PARAM/400。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
c_pick_folder 补上 Windows(PowerShell FolderBrowserDialog)和 Linux (zenity 优先、回退 kdialog)实现,三平台都覆盖到。c_project_create (U-002 已实现的 project_scaffold.create_project())第一次接上 HTTP 路由 POST /api/projects——backend_server.py 因此第一次需要持有 sqlite 连接,schema.connect() 加 check_same_thread=False 参数,配合 server.conn_lock 序列化 ThreadingHTTPServer 各请求线程的访问。 frontend/app.js 补上 #/setup 真实交互(选文件夹→校验 Git 仓库→非 Git 仓库二次确认→创建→跳转仪表盘),DOM class 命名对齐 docs/wireframes/v_project_setup.html。 REQ-11 完整 happy 用例(含创建 task)还需要 U-023 的 v_goal_composer/c_task_create,本 Unit 只完成 v_project_setup/ c_pick_folder/c_project_create 部分,development-plan.md 已记录。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
frontend/{index.html,app.js,style.css}: no build step, no npm, vanilla JS hash router (05 §5.7). Real page content is PH3 (U-022+, starting from docs/wireframes/); this is only the empty shell + working navigation the Done criterion asks for. backend_server.py serves the 3 files via an exact-path whitelist (not a generic static-file/directory server) -- no path-traversal surface to reason about for 3 fixed files. Verified in an actual browser this session (navigated to localhost, clicked all 3 nav links, screenshotted each) rather than only trusting stdlib tests -- a Python-only test can't exercise real hashchange/DOM behavior without a JS engine. Nav highlighting and content swap both confirmed working, no page reload, no build step. 7 new stdlib unittest cases covering what the server is actually responsible for (static files served with correct content-type, 404 on unknown GET path). 66 total across U-001-008, all passing. This closes out PH0 (U-001~U-008) -- all three Phase-acceptance criteria now hold for real: target-project directory scaffold, 15-table schema with constraint tests, and a real claude --agent round-trip. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
Pure stdlib http.server (ThreadingHTTPServer), zero third-party deps -- enforced by an AST-based test that parses backend_server.py's own imports and checks each against sys.stdlib_module_names, so this can't silently rot if someone adds a dependency later (05 §5.7). pick_folder(): macOS via `osascript 'choose folder'`; user-cancel maps to {"selected_path": null} (03-C §3.-1: not an error), non-macOS or any other osascript failure raises DialogUnavailableError -> HTTP 422 DIALOG_UNAVAILABLE. Windows/Linux native dialogs are PH3 (U-022). Known gap, noted rather than papered over: the Done criterion asks for a real popped dialog returning a real path, which needs an actual human click -- not something this agent can do non-interactively. Verified `osascript` itself is present and executes on this machine, and every code path is covered by mocked tests, but the literal "did a human click a real folder and get the right path back" check is still open for whoever runs this interactively next. 12 new stdlib unittest cases (server start/stop, pick_folder success/ cancel/non-macOS/other-failure, the same 4 cases through the HTTP route, zero-third-party-import check). 62 total across U-001-007 (60 real + 2 gated), all passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>