12 KiB
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Local-Development-and-Verification wiki_url: https://git.ilapage.cn/OPC/lexgo/wiki/Local-Development-and-Verification.- wiki_revision: c9c0de7a0bb1e610c1cb31b829f286a40048c855 synchronized_at: 2026-09-10T12:09:34Z
本地开发与验证
环境要求
当前工作区为 Windows PowerShell,文档工具使用 Python 3。产品 Go、Node、MySQL 8 小版本、Redis、NLP 和模型版本在 M0 锁定,尚无产品运行环境。
Windows PowerShell 与 UTF-8
读中文使用 Get-Content -Encoding utf8,复杂路径使用 -LiteralPath。Python 输出可设置进程 PYTHONIOENCODING=utf-8;文件解码与终端显示分别处理。不得打印凭据。
PowerShell 语法与外部命令
不要套用 Bash heredoc;Python 脚本可用单引号 here-string。通过 $LASTEXITCODE 检查外部命令,使用原生 PowerShell 路径操作,避免跨 shell 拼接。
第一次运行
从仓库根目录执行:
| 命令 | 预期与边界 |
|---|---|
python dev_scripts/harness.py --help |
退出码 0,列出工具命令 |
python dev_scripts/harness.py check --strict |
退出码 0,正式主题结构与镜像元数据完整;不单独证明线上状态 |
python dev_scripts/harness.py sync --verify |
从配置目标读取并同步全部映射页面,再严格检查,预期退出码 0 |
python -m unittest discover -s tests -v |
全部治理测试通过,不证明阅读器、NLP、SRS 已实现 |
git status --short --branch |
显示分支与待提交变化,提交后应无意外改动 |
同步会保护已有未提交镜像改动。新项目首次导出前先保存原有资料并提交引导材料;不跳过脏文件检查。凭据只通过安全配置或环境变量 GITEA_TOKEN 提供,不进入命令文本、日志或 Git。当前 MCP 连接其他站点,使用 API 的原因见初始化记录。
常用调试方式
先处理第一个可定位错误。页面缺失先发布、回读,不伪造 revision;配置错误先核对 owner/repository。产品阶段按用户/语言、任务、API、Worker/NLP 和数据文件逐层追踪,日志避免个人正文和凭据。
完成修改前
文档检查来源、链接、事实/建议区分和工作量加总;工具运行受影响的现有测试。产品阶段按具体工单测试隔离、Unicode、幂等、复习或恢复,未执行部分如实记录。当前没有 go.mod、package.json 或 Compose,不能声称产品能启动。
可复制 Shell 示例
PowerShell 语法与外部命令
- Windows 环境默认使用当前 PowerShell 语法,不套用 Bash 的 heredoc、变量、路径、引号或反斜杠转义规则。只有明确调用 Bash、WSL 或 Git Bash,并确认路径与编码边界时,才使用 Bash 专用语法。
- 不需要变量展开的正则和字符串优先用单引号;单引号字符串内部的单引号写成两个单引号。需要变量展开时才使用双引号。
- 正则同时包含单双引号或转义复杂时,优先赋值给变量、使用
rg -e,或拆成语义等价的简单查询;不得为了避开转义改变 AND/OR 条件或重复执行无关搜索。
rg -n 'error|warning' docs
$pattern = 'can''t match "value"'
rg -n -e $pattern docs
PowerShell 不支持 Bash heredoc。需要把多行 Python 送入标准输入时,使用单引号 here-string,避免 PowerShell 展开 Python 中的 dollar sign($)等内容。起始标记后必须立即换行,结束标记必须单独占一行:
@'
print("hello")
'@ | python -
foreach、if 等语句块不能裸放在管道左侧;需要管道输出时使用 $()、@() 或先赋值。普通命令输出无需包装:
@(foreach ($number in 1..3) { $number }) |
Measure-Object
不要把含 * 的搜索路径直接作为 rg 路径参数。优先传入真实目录,并用 -g/--glob 让 ripgrep 筛选路径:
rg -n -g '*.md' 'PowerShell' docs
只有确实需要把实体路径列表交给其他命令时,才使用 Get-ChildItem 展开并传递 .FullName;不要把 Get-ChildItem -Filter 设为所有 rg 搜索的固定前置。
示例预期:Python 输出 hello;Measure-Object 返回 Count 为 3;rg 返回当前文档中匹配 PowerShell 的行(有匹配时退出码 0,无匹配时为 1)。这些是 Shell 使用示例,不是产品测试命令。
学习端工程创建后的验证方向
学习端拟使用 create-vue + Vite,测试组合为 Vitest + Playwright;管理端保持指定 go-admin-ui 的现有工具链。当前未创建学习端工程,因此尚无可执行的产品 npm/pnpm 脚本。本轮技术方案记录不改变该事实。
正式工程建立时记录精确 Node/包管理器/依赖版本、锁文件、构建和测试命令;分别验证两端构建、共享登录/API 授权,以及阅读选择、Unicode 定位和学习闭环。具体测试范围依赖后续 MVP,不提前声称全部业务场景已有覆盖。
工程基础运行与验证(#2)
已验证主机为 Windows PowerShell;Node 22.22.1、pnpm 9.15.1、Go 1.26.5、MySQL 8.4.3。默认本地入口:学习端 http://127.0.0.1:5173、管理端 http://127.0.0.1:5174、API http://127.0.0.1:8000。前端 /api 由开发代理转发到后端,不开启宽泛跨域。
- 在 MySQL 8 中准备独立空库 lexgo_dev 与 lexgo_test_issue2(utf8mb4);不要把既有业务库用作测试库。
- 复制根 .env.example 为 .env.local,填写本机 DB 凭据与初始管理员密码;.env.local 已被 Git 忽略。优先读取进程中已有 LEXGO_* 配置,文件仅补缺项。
- 在仓库根执行以下后端命令。migrate 显式建表,bootstrap 仅首次执行,serve 不修改结构。
python scripts/server.py migrate
python scripts/server.py bootstrap
python scripts/server.py serve
分别开终端启动两个前端:
npx --yes pnpm@9.15.1 --dir admin install --frozen-lockfile
npx --yes pnpm@9.15.1 --dir admin dev
npx --yes pnpm@9.15.1 --dir learner install --frozen-lockfile
npx --yes pnpm@9.15.1 --dir learner dev
验证命令(仓库根执行):
python scripts/server.py test-integration
python scripts/server.py build
npx --yes pnpm@9.15.1 --dir admin test
npx --yes pnpm@9.15.1 --dir admin lint
npx --yes pnpm@9.15.1 --dir admin build
npx --yes pnpm@9.15.1 --dir learner test:unit --run
npx --yes pnpm@9.15.1 --dir learner test:e2e
npx --yes pnpm@9.15.1 --dir learner build
test-integration 默认使用 lexgo_test_issue2,可由 LEXGO_TEST_DB_NAME/LEXGO_TEST_DSN 指定其他 lexgo_test_ 前缀专用库;拒绝其他名字。迁移测试创建随机同前缀空库并仅清理自己创建的库,因此测试账号需具备该测试实例中的建库权限。普通 test 命令在没有测试库设置时跳过 MySQL 用例,不能当作集成通过。
学习端 Playwright 用例使用已安装的 Chrome 和虚构 API 响应;真实 MySQL/API 的浏览器联测结果在工单记录,不能混为同一种测试。管理端会话测试使用 Node 内置 runner。新增功能需针对行为写测试,而不是只验证打包。
本次本机初始管理员名为 admin,密码由工具随机生成,保存在忽略的 .env.local 的 LEXGO_BOOTSTRAP_PASSWORD;虚构浏览器学习账号 learner_a/learner_b 的本机测试口令记录在忽略的 .local/browser-accounts.json。这些本机文件不随 Git 交付,其他环境应自行设置。
停止开发服务器使用对应终端 Ctrl+C。回退本单代码可切换前一提交,保留项目库;前一版本只有文档,不存在需要启动的旧产品。删除测试/开发库不是自动回退步骤;生产升级与完整备份恢复由交付工单 #15 另行验证。
本机 supervisor 启动实例(2026-09-10)
用户要求将两端开发服务接入 D:/supervisord。配置文件为 D:/supervisord/supervisord.conf,控制台为 http://127.0.0.1:9009。使用现有 supervisor 启动入口;三个实例随 supervisor 启动,并在意外退出后自动重启。这不代表已配置 Windows 开机启动,也不替代 #15 的生产部署。
| 实例 | 工作目录 | 页面地址 | 日志 |
|---|---|---|---|
| lexgo-learner | D:/opc_project/lexgo/learner | http://127.0.0.1:5173 | D:/supervisord/lexgo-learner_out.log、lexgo-learner_err.log |
| lexgo-admin | D:/opc_project/lexgo/admin | http://127.0.0.1:5174 | D:/supervisord/lexgo-admin_out.log、lexgo-admin_err.log |
两端通过 C:/nodejs/node.exe 直接调用已经安装的 Vite / Vue CLI,启动时不安装依赖。学习端附带 --strictPort,避免端口冲突时自动换端口。管理端实例单独设置 npm_config_manage_package_manager_versions=false,防止 Vue CLI 编译后的 pnpm --version 检查触发全局 pnpm 自动下载指定版本而卡住;没有修改全局 pnpm 设置或项目锁文件。
通过控制台对 lexgo-learner / lexgo-admin / lexgo-api 单独 Start、Stop、Restart。启用托管时不要再执行同端口的手动 dev 命令。更改配置前备份原文件;本次备份为 D:/supervisord/supervisord.conf.lexgo-20260910-193432.bak。该备份只在本机保存,不提交仓库。
当前使用的 Go supervisord v0.6.8 重载可添加、移除实例,但现有实例对象不重新读取 command/environment。修改已有实例配置时,先停止目标实例,临时移除该节并重载,再加入新节并重载;不要重启整个 supervisor。回退本次接入时仅停止和移除上述两个实例,再重载,不覆盖随后新增的其他配置。
用户随后确认将共用后端一起托管。新增 lexgo-api,工作目录 D:/opc_project/lexgo/server,命令 D:/opc_project/lexgo/server/lexgo.exe serve,监听 127.0.0.1:8000。日志为 D:/supervisord/lexgo-api_out.log、lexgo-api_err.log。已启用 autostart、autorestart,启动不执行迁移或 bootstrap。
supervisor 直接管理编译后的 Go 进程,运行时不调用 Python。数据库连接值从本机 .env.local 复制到该实例的 environment,仅保存在本机 supervisor 配置中,不包含 bootstrap 密码。今后数据库连接配置变化,需要同步更新两处本机配置并按下述方式重新创建实例;不要打印配置或提交 Git。API 仍依赖本机 MySQL。
修改后端源码后,从控制台停止 lexgo-api,在仓库根目录执行 python scripts/server.py build,再启动 lexgo-api。Windows 中运行的 exe 不能直接覆盖;如果构建失败,修复后重新构建成功再启动。Python 此时只是构建辅助脚本。手动 python scripts/server.py serve 仍可用于临时调试,但必须先停止托管实例,避免 8000 端口冲突。
后端交接验证:停止时 8000 端口释放,重新启动后 lexgo-api 为 Running、/healthz 返回 200,两端 /api/v1/me 均返回预期 401。原有 11 个实例(含两个前端)的 PID 与状态均未变化。
验证结果:两个实例均为 Running,两端首页 HTTP 200,未登录请求 /api/v1/me 经代理返回预期 HTTP 401;已有 9 个实例的状态和 PID 均未变化。已交接并停止之前的手动前端进程。
本机验收账号维护(2026-09-10)
用户指定的管理账号 admin 已更新密码,并创建普通学习账号 dev 及其独立英语空间。指定密码只保存在忽略的 .local/account-credentials.json;.env.local 的 LEXGO_BOOTSTRAP_PASSWORD 已同步管理员当前密码,但仍不可对已有数据库重复执行 bootstrap。此前 learner_a / learner_b 测试账号保持原样。
两个指定账号通过本机管理员事务设置密码哈希并撤销旧会话;这是已获用户授权的本地维护操作。普通管理页面新增账号要求 6~72 字节、重置密码要求 10~72 字节,登录则直接验证已有非空密码,不以新密码下限拒绝已有账号。
新增真实 MySQL 回归测试覆盖已有短密码登录、错误密码拒绝、创建/常规重置仍拒绝短密码;已观察测试先失败再通过,完整后端集成测试通过。重新编译并由 supervisor 启动 lexgo-api 后,admin 管理端登录和 dev 学习端登录均成功,dev 的 /accounts 返回 403、英语空间归属正确,退出后的 token 返回 401。
新增账号 6 字节密码验证:管理端会话测试 18 项及完整后端 MySQL 集成测试通过;新增覆盖 5/6/72/73 字节和多字节字符,创建成功后验证登录。管理端 lint、生产构建及后端构建通过,lexgo-api 已由 supervisor 重新启动。