默认端口 8765 与 WorkBuddy Copilot 冲突:改为系统自动分配端口 待报告者确认
t-20260713-6317d1 · 故障 · 创建于 2026-07-13 07:29:38 · 版本 main@95f7581 · macOS 15 (Darwin 25.5.0)
问题描述
背景:本机另一项目 WorkBuddy Copilot 的 Hook、学员端、导师端固定依赖 127.0.0.1:8765,而本工具 src/cutpoint_lab/studio/server.py 的 --port 默认值恰为 8765。两者同机运行时,WorkBuddy 的导师台地址会命中本工具的服务,导致页面/API 版本不一致等故障。双方已协商:8765 永久保留给 WorkBuddy,本工具让出。期望改动:① --port 默认值从 8765 改为 0(由操作系统自动分配空闲端口);② 启动时打印、以及 --open 自动打开的地址必须使用实际绑定的端口(server 绑定后可从 socket 取真实端口);③ 保留 --port 显式指定的能力且行为不变(需要固定端口的用户仍可指定);④ scripts/studio_web.py 的 usage 文案与相关文档同步更新。验收标准:不带 --port 连续启动两个实例可同时运行互不冲突;--open 打开的地址真实可用;显式 --port 8765 时行为与现在完全一致;python3 scripts/run_tests.py 全绿。备注:这是创始人已拍板的产品决策(让出 8765),属于启动配置默认值变更,不涉及 HTTP API 的行为语义——不应被约束第 5 条误伤。
用户日志
lsof -nP -iTCP:8765 -sTCP:LISTEN → python3.1 11039 michael TCP 127.0.0.1:8765 (LISTEN)(本工具进程);WorkBuddy 侧 AI 确认导师台因此命中错误服务
分诊结论
结论:接受
判断理由:
- 问题描述清晰:端口冲突症状明确(lsof 日志证实本工具占用 8765),根因可理解
- 期望改动具体可执行:四点需求均有明确行为定义(默认改 0、打印真实端口、--open 使用真实端口、保留显式指定能力)
- 验收标准完整:可独立验证(双实例并存、--open 可用、显式 8765 行为不变、测试全绿)
- 改动范围有限且不违反约束:仅改启动配置默认值,不涉及 HTTP API 行为语义,不引入新依赖
修复摘要
将 server.py 的 --port 默认值从 8765 改为 0(OS 自动分配),并在测试中添加正确的回归断言:通过 patch bind_server 捕获 main([]) 实际传入的 port 参数断言为 0,不再创建独立 ArgumentParser。
改动文件:
src/cutpoint_lab/studio/server.pytests/test_studio_app.py
合并提交 29440fd1de52f96f907fc2ca0355fec457ee9188
事件时间线
- 2026-07-13 07:29:38工单已创建
技术细节
- 类型
- bug
- 含用户日志
- 是
- 2026-07-13 07:30:06状态已更新:已接收 → 排队中
技术细节
- 触发方式
- triage
- 2026-07-13 07:30:06状态已更新:排队中 → 修复中
- 2026-07-13 07:31:53已完成验证
技术细节
- ok
- 是
- steps
- name
- verify
- ok
- 是
- required
- 是
- 2026-07-13 07:31:53状态已更新:修复中 → 待评审
技术细节
- files
- 2
- 2026-07-13 07:31:53状态已更新:待评审 → 评审中
- 2026-07-13 07:32:59已完成策略判定
技术细节
- action
- human
- tier
- medium
- reasons
- judge 无法判定:Bug 真实存在:server.py 原 default=8765 与 WorkBuddy 固定端口冲突,日志可证实。;需求 ① 已满足:argparse default 从 8765 改为 0,help 文本同步更新。;需求 ② 无法从 diff 验证:工单要求 '启动时打印、以及 --open 自动打开的地址必须使用实际绑定的端口'。diff 未展示 main() 的 URL 打印逻辑和 --open 的 webbrowser.open 调用。若这两处仍拼 args.port(=0),用户会看到 http://127.0.0.1:0 或空白浏览器,修复实际无效。;需求 ④ 修复者自认未完成:scripts/studio_web.py 的 docstring/usage 未更新,以 '保护路径' 为由搁置,工单验收标准明确要求文档同步。;回归测试第一部分是冗余测试:test_default_port_is_zero_not_8765 中创建了独立的 ArgumentParser 并断言其 default=0,这个断言测的是测试自己写的 parser 而非 server_main 的 parser,即使 server.py 没改也能通过,属于无效断言。第二部分(--help 不含 8765)是有效的,但整体测试未覆盖 --open 实际打开 URL 这一关键路径。;pipeline 报错(源媒体不存在)系测试设计内预期错误,与本次改动无关,已确认 86/86 全绿。
- 2026-07-13 07:32:59状态已更新:评审中 → 待人工审批
技术细节
- 决策卡
- d-20260713-4ff3d6
- reasons
- judge 无法判定:Bug 真实存在:server.py 原 default=8765 与 WorkBuddy 固定端口冲突,日志可证实。;需求 ① 已满足:argparse default 从 8765 改为 0,help 文本同步更新。;需求 ② 无法从 diff 验证:工单要求 '启动时打印、以及 --open 自动打开的地址必须使用实际绑定的端口'。diff 未展示 main() 的 URL 打印逻辑和 --open 的 webbrowser.open 调用。若这两处仍拼 args.port(=0),用户会看到 http://127.0.0.1:0 或空白浏览器,修复实际无效。;需求 ④ 修复者自认未完成:scripts/studio_web.py 的 docstring/usage 未更新,以 '保护路径' 为由搁置,工单验收标准明确要求文档同步。;回归测试第一部分是冗余测试:test_default_port_is_zero_not_8765 中创建了独立的 ArgumentParser 并断言其 default=0,这个断言测的是测试自己写的 parser 而非 server_main 的 parser,即使 server.py 没改也能通过,属于无效断言。第二部分(--help 不含 8765)是有效的,但整体测试未覆盖 --open 实际打开 URL 这一关键路径。;pipeline 报错(源媒体不存在)系测试设计内预期错误,与本次改动无关,已确认 86/86 全绿。
- 2026-07-13 07:35:45已完成人工审批
技术细节
- 决策卡
- d-20260713-4ff3d6
- 所选项
- requeue
- 批注
- 保留现有改动(default=0 正确;--open/打印已实证使用真实绑定端口 server.py:611-615,无需改动)。只需修一处:test_studio_app.py 里 test_default_port_is_zero_not_8765 的第一部分断言无效——它新建了一个独立 ArgumentParser 再断言 default=0,测的是测试自己而非 server 的 parser,server.py 回退到 8765 它也能通过。请改为对 server 真实入口的断言(例如导入 server 模块解析空参数列表后断言 args.port==0,或等价方式);--help 不含 8765 的第二部分断言保留。不要碰 scripts/**(usage 文档由运维另行处理)。
- 2026-07-13 07:35:45状态已更新:待人工审批 → 排队中
技术细节
- 触发方式
- human
- 批注
- 保留现有改动(default=0 正确;--open/打印已实证使用真实绑定端口 server.py:611-615,无需改动)。只需修一处:test_studio_app.py 里 test_default_port_is_zero_not_8765 的第一部分断言无效——它新建了一个独立 ArgumentParser 再断言 default=0,测的是测试自己而非 server 的 parser,server.py 回退到 8765 它也能通过。请改为对 server 真实入口的断言(例如导入 server 模块解析空参数列表后断言 args.port==0,或等价方式);--help 不含 8765 的第二部分断言保留。不要碰 scripts/**(usage 文档由运维另行处理)。
- 2026-07-13 07:35:45状态已更新:排队中 → 修复中
- 2026-07-13 07:38:02已完成验证
技术细节
- ok
- 是
- steps
- name
- verify
- ok
- 是
- required
- 是
- 2026-07-13 07:38:03状态已更新:修复中 → 待评审
技术细节
- files
- 2
- 2026-07-13 07:38:03状态已更新:待评审 → 评审中
- 2026-07-13 07:38:39已完成策略判定
技术细节
- action
- human
- tier
- medium
- reasons
- 风险等级 medium 的门槛配置为人工审批
- 2026-07-13 07:38:39状态已更新:评审中 → 待人工审批
技术细节
- 决策卡
- d-20260713-0d427e
- reasons
- 风险等级 medium 的门槛配置为人工审批
- 2026-07-13 07:50:11已完成人工审批
技术细节
- 决策卡
- d-20260713-0d427e
- 所选项
- approve
- 批注
- 无
- 2026-07-13 07:50:11状态已更新:待人工审批 → 已批准
技术细节
- 触发方式
- human
- 2026-07-13 07:50:11状态已更新:已批准 → 合并中
- 2026-07-13 07:50:13修复已合并
技术细节
- sha
- 29440fd1de52f96f907fc2ca0355fec457ee9188
- 2026-07-13 07:50:13状态已更新:合并中 → 已合并
技术细节
- sha
- 29440fd1de52f96f907fc2ca0355fec457ee9188
- 2026-07-13 07:50:13已通知报告者
技术细节
- mode
- log
- confirmUrl
- http://localhost:8123/confirm/t-20260713-6317d1?token=***
- 2026-07-13 07:50:13状态已更新:已合并 → 待报告者确认