跳到正文
Scopwis
开发

参与开发

Scopwis 把代码、machine contract、测试和文档视为同一个变更面。用户可见行为不应该和过期文档或未验证协议例子一起落地。

初始化

git clone https://github.com/scopwis/scopwis.git
cd scopwis
cp .env.example .env
make setup
make doctor

本地运行:

make dev

只需要浏览器客户端时使用 make dev-web。

隔离后端 smoke

make backend-smoke 会构建并启动 API,使用全新的临时 data root,关闭公开数据加载和认证。就绪检查要求本次启动的子进程仍然存活,并先输出自身的 listening 日志,再验证其 bootstrap 响应;已经占用 smoke 端口的其他服务器不能让该检查通过。

通过还要求该子进程处理 SIGTERM 后,wait 返回成功。清理提供 10 秒的外部 drain 预算;强制终止、子进程非零退出或启动失败都会使 smoke 失败,并保留临时 root 和日志路径供排查。10 秒是 smoke 的验收上限,不代表所有生产环境 blocking 操作都能在此时间内完成。

这只验证隔离启动与正常停机,不等于完整的 Agent 取消或持久化验收。make backend-workspace-smoke 不同:它使用配置的持久化 root,启动时可能执行迁移、恢复以及数据源状态写入。不要把它当作对正在使用或不可替代的工作区数据的只读检查。

隔离 Agent 生命周期验收

在 POSIX 主机上,先构建当前二进制,再运行隔离进程 fixture:

cargo build --locked -p scopwis-server --bin scopwis-server
python3 -B crates/scopwis-server/tests/runtime_process_smoke_tests.py --binary target/debug/scopwis-server
python3 -B crates/scopwis-server/tests/runtime_process_smoke.py --binary target/debug/scopwis-server
python3 -B crates/scopwis-server/tests/runtime_process_smoke.py --binary target/debug/scopwis-server --report

脚本只使用全新的临时 root、受控的空 .env 和 loopback 阻塞模型 fixture,不继承 HOME、凭据或代理设置。它验证任务取消、模型连接关闭、SIGTERM 退出、SSE 终态后 EOF、完整持久化 snapshot 一致性,以及同 root 重启后不重放模型请求。强制终止算验收失败;成功后也会在输出的 evidence 路径保留日志与 fixture 数据。

必须开启 assertion:-O、-OO 和非零 PYTHONOPTIMIZE 会在创建临时文件、socket 或子进程前被拒绝。SSE 有 30 秒的绝对生命周期,以及 bytes、event 和 snapshot 数量上限;模型请求 socket 在读取任何 header 或 body 前设置 timeout。清理采用共享的 5 秒线程 deadline(包括注册表取锁),显式关闭自身连接,并确认 reader、deadline timer、accept loop 和模型 handler 全部退出后才输出 passed。清理超时或线程失败都会使验收失败并保留证据,不依赖无上限的 server_close() join。

--report 模式使用确定性 loopback 模型和 3 行临时 CSV,由真实服务端注册来源,经 OpenDAL/DataFusion 查询、校验分析引用并保存/重开报表。它核对公共载荷只投影绑定字段、私有 revision 修改后分享保持冻结、陈旧版本拒绝、同根重启,以及撤销状态在再次重启后保留。首次完成时冻结模型调用序列,在 handler 清理后再次比对;helper 用真实晚到 HTTP 请求验证守卫。传入 --binary 才执行完整 3 项 helper 测试,省略会跳过这项进程回归。

这只是使用假模型的服务端生命周期检查,不等于真实 provider、浏览器、敏感数据或六端 UI 验收。脚本的 30 秒停机 deadline 是外部测试预算,不是生产 drain 保证。

任务变更等待状态回归

cargo test --locked -p scopwis-server --lib serialized_mutation_future_size_is_independent_of_captured_payload -- --nocapture

该回归比较捕获 32 KiB 数组与最小捕获时事务 Future 的内联尺寸,并检查精确结果、仅执行一次和串行锁归属。事务入口在 async gate 等待前拥有一个堆上的工作单元。此测量只覆盖保留的等待状态布局,不代表进程总 RSS、瞬时栈使用或吞吐量;取消与关停行为继续由上面的生命周期验收验证。

提交前

至少执行:

cargo fmt --all --check
make lint
cargo test --locked --workspace
git diff --check

UI 变更继续跑 Flutter analyze/tests;公开文档变更必须跑网站构建。

文档规则

公开文档位于:

docs/public/en/
docs/public/zh-Hans/

两棵 locale 树必须拥有完全相同的 document key。某个公开页面只存在一种语言时,网站构建直接失败。

实现级规范继续位于 docs/specs/;设计/架构记录位于 docs/design/。不要再把内部研究记录塞进公开导航。

网站构建

bash scripts/build-cloudflare-website.sh

输出为 site-dist,由仓库内 Rust renderer 生成。网站运行时不依赖 Node package graph。

保持边界清晰

修改 Agent、query、mining、report、capability、auth 或 release 行为时,代码、Rust test 与 machine/schema example 要一起更新。不要把本应由确定性 policy 解决的兼容逻辑塞进 UI 文案或 model prompt。

输入关键词搜索中文文档。