Skip to content

Releases: yes999zc/rui

rui 0.8.4

Choose a tag to compare

@yes999zc yes999zc released this 28 Oct 14:03

0.8.4

  1. LLM tool reminders keep the speaking room. A per-turn ToolContext (ContextVar) is scoped by TurnRunner.run; set_reminder stores room=context.room. The voice fixed-sentence and tool paths share one source-room resolver. An unnamed reminder from 次卧 stops/speaks only in 次卧; 客厅 stays silent.
  2. Ultra-short merge window 10 → 16 chars. 「一分钟后提醒你喝水,小志。」 (13 chars) is one TTS request; 19-char two-sentence replies still split; first audio unchanged.

No protocol/rui_compat change; plugins unchanged.

rui 0.8.3

Choose a tag to compare

@yes999zc yes999zc released this 28 Oct 12:45

0.8.3

  1. Ultra-short replies are one TTS request. When the model paused >300 ms after the comma (在,\n … 你说。), the short-hold cap released by splitting into two renditions; the vendor head/tail silence became an audible ~160 ms seam. Cap/force/tail now merge the whole ultra-short buffer; literal 在,你说。 was already one request. First audio unchanged.
  2. Reminder provenance. An unnamed voice reminder now keeps the room of the device that heard it instead of falling back to default_output; it rings/stops music only there, and an offline source still falls back with 「那台没在线」 + health counters.
  3. Diagnostics: per-TTS-call tts_call#k logs, trace call count/inter-call silence, and per-reply segment count/audio/seam/inner silence (additive Metrics/trace). Ledger closes on barge/stop.

No rui_compat change (>=0.8.1 <0.9.0).

rui 0.8.2

Choose a tag to compare

@yes999zc yes999zc released this 28 Oct 11:52

0.8.2

  • Reminders accept second-level relative times: when supports +10s, +1m30s, +90s (alongside +10m, +1h30m, HH:MM, ISO).
  • Voice fixed entry claims N秒后 / N秒钟后 / N秒之后 / N秒以后 (Arabic or Chinese digits) and uses the same parse_at arithmetic as the tool.
  • Reply wording is rendered from the final stored at: 10 s → 「10 秒后」, 90 s → 「1 分 30 秒后」 (no more 「马上」/「2 分钟后」 rounding); parse failure asks and creates nothing.
  • No rui_compat change (>=0.8.1 <0.9.0).

rui 0.8.1

Choose a tag to compare

@yes999zc yes999zc released this 28 Oct 11:02

0.8.1

  1. Close paths stop arming the follow-up window: stop words and the idle farewell still drain and apply post-playback mute, but no longer open a wake-free listening window (ReplyFinished.followup=False). Normal replies keep the ~1 s follow-up.
  2. Dot 2 model voice defaults: rui-dot2-bridge 1.3.3 declares followup_delay_ms: 300 / post_playback_mute_ms: 500; console/API expose both per-device. Requires core 0.8.1+ — install bridge 1.3.3 together with this release. LX06 unchanged.
  3. /v2/devices card grid: one card per device, 3/2/1 columns, same-room cards adjacent, summary/warnings above.
  4. Gap diagnostics: turn trace records playback_gap_chunks (chunk index + gap ms) via an additive Metrics field; no playback/barge behavior change.

Deploy note

Order: core 0.8.1 image first (plugins 1.3.2 still compatible), then rui-dot2-bridge 1.3.3 + xiaoai 0.2.3, then config (followup_max_wait_ms: 3000, dot2-b control_port: 0/loudness_file). Rollback is the reverse: plugins back to 1.3.2 first, then image back to 0.7.9 digest.

rui 0.8.0

Choose a tag to compare

@yes999zc yes999zc released this 28 Oct 09:54

Breaking changes (read first)

  1. Legacy console removed: /legacy and the 15 old panel links now return 404; / redirects to /v2/. v2 is the only console.
  2. adapter: xiaoai is rejected: the read-time migration is gone; an old config fails with a fix sentence (change devices[].adapter to 'lx06'). devices[].adapter and runtime.listen_port are now required.
  3. Compat window: rui_compat" title="rui_compat" is now >=0.7.0 <0.9.0. The dot2 bridge 1.3.2 and xiaoai bridge 0.2.3 are dual-window builds; install them before upgrading core or the loader refuses both adapters.

Audio facts ownership

Model manifests now own hardware facts (capture/playback rate, channels, bits, ack tail, AEC); explicit global config no longer silently overrides them. capture.rate remains a negotiated wire (client resampling). Every conflict is visible in the API/console; a plane refuses to start if its configured wire does not match the model/device (audio_config_mismatch), and bridge play() errors surface as device errors instead of per-chunk INFO.

Reminders (minimal C2)

A due reminder stops only the target room's music, announces, and does not resume it. An offline target falls back to default_output with "那台没在线"; failures are counted in /health.reminders (not log-only). No retry/scheduling/music resume in 0.8.0.

Follow-up window

audio.voice.followup_max_wait_ms defaults to 8000 ms. Set it to 0 in deployment for "wake word required every turn" (9哥 production choice).

Notes

  • No tags/releases for bridges were changed here; dot2 1.3.2 and xiaoai 0.2.3 are already published.
  • Real-device acceptance for the 4-device fleet is tracked separately; this release notes only code-level gates.

0.7.9 — intent layer narrowed (headless-verified only), ack moved up

Choose a tag to compare

@yes999zc yes999zc released this 27 Oct 05:37

Patch release. Two intent-layer behaviour changes, one log-noise fix, one audio
error-reporting fix, and the wake-acknowledgement ordering in the console.
No contract change. dot2 1.3.1 and xiaoai 0.2.2 stay compatible
(rui_compat >=0.6.0 <0.8.0 unchanged), so neither bridge is re-released.

Read this before trusting it

  • The intent changes are headless-verified only. 1716 passed, 6 skipped covers
    them; no speaker was involved. Hardware verification of 0.7.9 is folded into the
    next window (docs/acceptance-pending.md, N1/N2/N3 + R79-*), together with the
    second same-model dot2. This release does not claim the intent layer is fixed on
    device.
  • 0.7.9 is not deployed. Production still runs 0.7.8; deployment is a manual step
    done by the operator.
  • Nothing here claims that wake acknowledgement is the first group on the page or that
    the HE-02 echo-excision gap is fixed. Both are still open
    (docs/known-limitations.md L1/L15).

Intent layer

  • An end word with music playing now stops the music and closes the session
    (ddb7cbb). Previously "stop" while music played only stopped the music and kept
    the session listening — that was the reported symptom, where asking for the time and
    then saying "stop" left the session open. Paused counts as playing; there is no
    middle state.
  • stop_intent only matches a whole request (ddb7cbb): the exact word, an
    explicit alias, or one closed-set particle (吧/了/呀/啊/嘛). Question particles
    (吗/呢/么) are excluded. Deliberate narrowing: 停止你好, 停止了吗, 请停止,
    我要停止 no longer match and go to the model instead. 停止播放/别放了/别放了吧
    are kept as explicit aliases so the phrases people actually say still work.
  • Pause vocabulary is now two words (34e3629): 暂停 and 停一下.
    先停这儿/停会儿/停住/停在这 no longer pause anything and were not moved into the
    end-word list.
  • "暂停" with nothing playing answers instead of hanging up (34e3629): it replies
    现在没在放音乐。 and keeps the session open. Those two words are also end words, so
    before this the silent case fell through to a bare stop.

Console

  • Wake acknowledgement moved up (6117fb7, D-011=A): the catalog ack group goes
    from order 200 to 5, tier unchanged. In the v2 voice-assistant page it is now
    group 3 — first screen, no scrolling. In the legacy panel's audio tab it is group 1.
    Reaching group 1 in v2 needs a tier change or explicit page ordering: that is 0.8
    work, not this release.

Fixes

  • audio close() no longer masks the plane's real error (2977c3a): a child that
    died before the handshake used to turn audio plane refused: … RUI_MISSING_TOKEN …
    into [Errno 57] Socket is not connected, and skipped proc.terminate() on the way
    out. The same race was the one known flaky test; it is now covered by a deterministic
    regression test.
  • Swallowed ENOTCONN leaves a DEBUG line (8321099) instead of silence.
  • mcp <name>: down reconnect logging is throttled (3ed312f): one INFO for the
    first failure, a changed reason, or a successful reconnect; an unchanged reason at
    most once every 5 minutes; the rest at DEBUG.
  • dot2 volume read-back answers the level the mixer reports (d2c9895);
    「唱首歌」 routes to random play and legacy links explain themselves (e85b4bb);
    the console shows Home Assistant and MCP servers as two sections (91cac91,
    presentation only — GET /api/v1/mcp is unchanged).

Images

  • Index: sha256:0f6c89ceb217d79471017bf24860dd74f1135f20b2d612e106277d5abc15bf05
  • amd64 platform digest (what the NAS needs):
    sha256:5aa362f6b4f7d7fd24a7f01d41c31e1523ce2401296ac3b203b9f684a314b9f7
    The NAS's older docker rejects the OCI index (unsupported media type); pin the
    platform digest instead.

Rollback

Roll forward is one compose command; rollback is the same with the previous tag. Always
pass both -f flags (docker-compose.yml + rui-dot2-override.yml) or compose
reads a stale RUI_IMAGE from .env. Full steps:
docs/release-candidate-0.7.9.md §5 and docs/deploy-runbook-0.7.8.md §8.

rui 0.7.8 — the v2 console becomes the default

Choose a tag to compare

@yes999zc yes999zc released this 27 Oct 00:27

rui v0.7.8 — 发布说明

日期:2026-10-27
范围:rui 0.7.8(核心仓);rui-dot2-bridge 1.3.1 与 rui-xiaoai-bridge 0.2.2 无代码改动、不 bump(0.7.6 把 LX06 语义测试挪进桥仓是测试搬迁,不改插件行为)。

主题:四张卡合并成一次发版——安装路径 TLS(0.7.5)、两台平面可见性(0.7.5)、
小爱真正摘出核心(0.7.6)、控制台审计 + 默认切 v2(0.7.7/0.7.8)。API 与契约窗口不变
(C-002/1,>=0.6.0 <0.8.0),没有 schema 迁移。
镜像 digest 记录在 GitHub release body 与 docs/HANDOFF.md 的发布表;本文件不重复,
避免 tag 树内出现占位值。GitHub release body 即本文件(中英双语)。

版本口径

0.7.5–0.7.7 的开发合并进 0.7.8,未单独发版;原因是它们的验收项依赖 0.7.8 的完整代码与真机窗口。 具体说:Done 6 真机、内置 vs 外置双跑对比、升级与回滚,都要等 0.7.8 的代码齐了才能一次做完;事后补 tag 等于假装「发版时已验证」。0.7.8 是唯一的验收节点,本文件与 CHANGELOG 的 0.7.8 段一起记录这四块。

行为变更

场景 0.7.4(上一发布) 0.7.8
两台设备,默认 multi_device.enabled=false 只起配置里第一台的平面,/health 只有聚合 audio_plane 行为不变,但 /health.planes 逐台给出 state 与 reason;rui doctor 在「2 台且 multi_device 关」时 WARN 并给修复句
dot2 开 tls_port / listen_port 但缺 secrets/server.pem / server.key audio_plane=false + missing TLS material 行为不变;0.7.5 把证书路径做进 examples/two-speakers(./secrets 挂载 + scripts/make_dev_tls.sh),三仓安装提示同步
第三方设备清单未声明 wake_words_residual(0.7.6 新增字段) — 已知行为变更:不再 early-yield 设备自己的 vendor 短语,只靠 is_echo / is_noise;内置 lx06 清单声明三条,行为不变
配置写 adapter: xiaoai 内置插件可用 读入时重写为 lx06 + 弃用 WARNING(/health.adapter_plugins.warnings、设备级 legacy_adapter_spelling);需要外置 rui-xiaoai-bridge 插件
GET /(配置里没有 console 键) 200 旧壳(默认 legacy) 302 → /v2/(默认 v2,保留 query)
GET /(console: legacy) 200 旧壳 200 旧壳(不变;这是一版回滚)
老链接 /panel/<id>(11 条)、/setup、/secrets、/diagnostics、/channels 200 旧壳 302 → 对应 v2 页面;providers / system / channels 三条 v2 暂无对应页 → /v2/?from=<旧路径>
旧控制台位置 /(legacy 模式下 /legacy 也可以) /legacy(200,顶部中英弃用横幅,0.8.0 移除)
/health.console legacy v2(默认;显式 legacy 时仍报 legacy)
/api/v1/*、/api/v2/*、CONFIG_VERSION、契约窗口 — 不变(0.7.5 的 /health.planes 是 additive A-8)

升级注意(必须知道):升级到 0.7.8 后,配置里没写 console 键的老部署会静默
变成 v2 入口
(/ → /v2/),无需改配置、也无法从配置文件看出变化——看
/health.console 或根地址的 302。想保持旧入口,写 web.console: legacy 后重启。

?from= 目前只是标记:v2 不读取、不提示,/v2/ 的 SPA redirect 会带着 query 进
/v2/devices;所以 providers / system / channels 三条老书签最终停在设备页
(审计 console-functional.md §8.9)。

变更

0.7.5 — 安装路径 TLS + 两台平面可见性

  • TLS 材料进安装路径(43d18df,house;dot2 1826e87、xiaoai 1c1aa35):
    examples/two-speakers/compose.yaml 把 ./secrets 挂到 /opt/rui-secrets
    (DOT2_SECRETS_DIR),新增 scripts/make_dev_tls.sh 生成自签 server.pem /
    server.key,三仓安装提示加 TLS 步骤。dot2 的 listen_port / tls_port 开启时
    证书是硬要求,缺失 → audio_plane=false + missing TLS material。
  • 三矩阵实测(258d72a;docs/audit/tls-required-2026-10.md,3 组 × 2 次):
    ① dot2 无证书 → false + missing TLS material;② lx06+dot2 无 TLS 且
    RUI_DEVICE_TOKEN 空 → false + RUI_DEVICE_TOKEN is empty(默认单平面只起第一台);
    ③ 证书 + 两个 token、dot2 在前 → true + dot2 link: wss listening on 8871。
    自签只证明平面能启动,真机是否接受取决于设备信任的 CA(原 controller 证书不可重建)。
  • 逐台平面可见性(5e16026):GET /health.planes 每台 enabled 设备一行
    (device / room / state(running / error / not_started)/
    reason(multi_device_disabled / plane_not_started / audio_not_started)/
    error / multi_device),旧 audio_plane 保留为聚合值;rui doctor 在两台且
    multi_device 关闭时 WARN;config.example.yaml 补 multi_device 示例;C-002 A-8;
    7 条新测试,全量 1659/17。

0.7.6 — 小爱真正摘出核心

  • 仓内插件与别名模块删除(c713916):plugs/xiaoai/ 移到
    tests/fixtures/legacy_lx06(测试夹具,不进镜像),src/rui/adapter_aliases.py 删除;
    Dockerfile 去掉 COPY plugs,/opt/rui-plugins 归 rui:rui 且构建期验证可写。
    B1a 收口时全量 1654/17。
  • adapter: xiaoai 配置迁移(c713916):读入时重写为 lx06 + 弃用 WARNING,
    /health.adapter_plugins.warnings 与设备级 legacy_adapter_spelling 各报一条;
    默认 adapter 改 lx06(等价、不告警)。兼容模块 rui/config/legacy_adapters.py
    (旧拼写 + 隐式 4412 端口默认)是唯一允许出现旧名字的文件,0.8.0 整模块删除。
  • vendor 唤醒兜底改数据驱动(c2ed7fd,桥 0810885):设备清单新增可选
    devices[].wake_words_residual;未声明则不过滤 vendor 短语(见「行为变更」)。
    文档写在 docs/socket-plug-v1.md。
  • 54 条设备语义测试搬桥仓(300b2a9,桥 575b443):credit 5 / device-services 7 /
    kws 5 / led 18 / playback 1 / turn-audio 6 / vendor 11 / console-secret 1,逐条字节
    一致。core 1655/17 → 1612/6;桥仓 44 → 87 passed / 11 skipped(+54 collected);
    20 条通用 test_security_fixes 留在 core。
  • 门禁:核心 src/**/*.py 的 xiaoai|lx06|小爱|4412 grep 0 命中(仅
    legacy_adapters.py 豁免;本树复跑确认)。

0.7.7 — 控制台审计(C)

  • db179f8:172 行交互 / 159 可用 / 12 未验证 / 0 不可用(4 个实例、76 张截图;
    夜间无真机、无声音),交付 docs/audit/console-functional.md。
    口径:172 = 159 可用 + 1 文案错误行 + 12 未验证 + 0 不可用。
  • 4 组文案/校验修正:setup 空屋误报、旧控制台提示过期、死 v2.config.stub* i18n key、
    设备写入 7 条中文校验 message 改英文(C-002 §4.4)。

0.7.8 — 默认切 v2(D)

  • efab571:WebConfig.console 默认 "v2"(config.example.yaml、
    src/rui/config/template.yaml 同步写出);/ → 302 /v2/(保留 query);
    /legacy 旧壳 + 中英弃用横幅(data-testid="legacy-deprecation",CTA 到 /v2/,
    0.8.0 移除)。
  • 15 条老链接 302(映射表 src/rui/web/api/legacy_links.py;legacy 模式保持
    200 旧壳);?from= 仅标记。README 中英 hero 换 v2 设备页 + 「控制台入口」段。
  • 测试:新增 tests/test_legacy_links.py(15 条精确 Location + 查询串 + tab 子路径 +
    未知 panel + legacy 模式 200s);重写 tests/test_console_switch.py(默认 v2 /
    回滚 / /health.console 两态 / 示例配置断言)。
  • task-18 文档收口:docs/deploy.md §3.8 改为「v2 默认 / legacy 一版回滚」(含老链接
    302、?from= 标记、0.6.x 兼容说明);CHANGELOG 0.7.8 段;本文件;README 英文 hero;
    legacy_links.py 注释修正;?from= 限制写进审计 §8.2/§8.9。

门禁(逐项可核)

卡 结论
0.7.5 task-9 TLS 安装路径 PASS + VERIFIED;house 43d18df、dot2 1826e87、xiaoai 1c1aa35
0.7.5 task-10 TLS 三矩阵 PASS + VERIFIED;258d72a;docs/audit/tls-required-2026-10.md 6 次实跑
0.7.5 task-11 平面可见性 PASS + VERIFIED;5e16026;7 新测试;全量 1659/17
0.7.6 task-12 插件/别名摘出 PASS + VERIFIED;c713916;全量 1654/17
0.7.6 task-13 语义测试/门禁 PASS + VERIFIED;c2ed7fd + 桥 0810885;桥 44 passed;核心 grep 0
0.7.6 task-14 54 条测试搬桥 PASS + VERIFIED;300b2a9 + 桥 575b443;core 1612/6;桥 87 passed / 11 skipped
0.7.7 task-16 控制台审计 PASS + VERIFIED(reviewer-audit R1/R2 收回);db179f8;172/159/12/0(172 = 159 + 1 文案错误行 + 12 + 0)
0.7.8 task-17 默认切 v2 + 302 + 横幅 reviewer-d PASS + verifier-tests VERIFIED;commit efab571(15/15 302、跟随跳转全 200 v2 壳、legacy 两态实测)
0.7.8 task-18 文档收口 本卡:reviewer-core 评审 → verifier-tests 验证;结论由 Lead 在 tag 前确认

测试基线(0.7.8 工作树,house-ear):1642 passed / 6 skipped;ruff check . 全绿;
cd web && npm run typecheck && npm run build 绿;git diff --check 0。

产物

  • 镜像:ghcr.io/yes999zc/rui:0.7.8(digest 记录在 GitHub release body 与
    docs/HANDOFF.md 的发布表;本文件不重复,避免 tag 树内出现占位值)。
  • 下游薄层(如重新构建):FROM ghcr.io/yes999zc/rui:0.7.8;完整 digest 用 GitHub
    release body / docs/HANDOFF.md 发布表记录的值固定。
  • /api/v2/meta:rui_version=0.7.8、compat=0.6.0..<0.8.0(版本已落库,uv lock --check 绿);
    实际输出记录在 docs/HANDOFF.md 发布表。

已知限制(不阻塞发布)

0.7.5–0.7.8 相关:

  1. 自签证书不保证真机链路:只证明音频平面能启动;设备以固定 ServerName 校验,
    原 controller 证书无法重建,丢失时需重新配网(docs/audit/tls-required-2026-10.md)。
  2. 双设备默认仍只起第一台平面:multi_device.enabled: true + max_planes >= 2
    才会为每台起平面;/health.planes 与 doctor 现在会明说,不再静默。
  3. wake_words_residual 未声明的第三方清单可能让设备自己的 vendor 短语进入回合
    (内置 lx06 已声明三条,不受影响)。
  4. providers / system / channels 在 v2 没有对应页:老链接落
    /v2/?from=<旧路径>,?from= 只是标记(v2 未消费),最终停在设备页 /v2/devices。
  5. v2 空态仍有两处 /legacy 出口(DevicesView.vue / RunView.vue):这是“v2 做
    不了、去旧壳做”的明确出口,/legacy 带弃用横幅;0.8.0 删旧壳时必须一并处理。
  6. 0.7.7 审计的 12 行未验证(6 类,原因见审计 §11):需真机/需特定异常环境,本轮
    没有构造,不做推断。
  7. 条件性 500:音乐凭据路径不可写时 PUT /api/v1/music/credentials 返回 409(0.7.8 已修,原来是 500)(应为 4xx),
    见审计 §8.1。

沿用 0.7.4 的运行时限制(cue 回声边界、单会话 runner、告别尾音不可追回、唤醒词不按房间
隔离、多设备并发未测)与 0.7.7 的 v1 功能缺口(话术编辑器、供应商卡片/试听、音乐播放
6 按钮、system/web/security 字段、渠道、工具注册表、设备探测、MCP/HA 写入)——均未在
0.7.8 改变。

合规

  • 三仓 LICENSE 均为 MIT。
  • 未新增品牌字样、未新增对外宣传话术;文档与截图不含内网地址与凭证(README hero 与
    审计横幅截图均无 IP / token)。

升级与回滚

  • 升级:RUI_IMAGE=ghcr.io/yes999zc/rui:0.7.8 bash deploy/install.sh,或把 override 的
    image: 改为 ghcr.io/yes999zc/rui:0.7.8 后 docker compose up -d。
  • 无 schema 迁移;rui_compat 仍为 >=0.6.0 <0.8.0;dot2 保持 1.3.1,xiaoai 为 0.2.2。
  • 升级检查:
    1. 两台设备要同时出声 → 配置加 multi_device: {enabled: true, max_planes: 2}。
    2. 用 LX06 → 确保外置 rui-xiaoai-bridge 插件已挂到 /opt/rui-plugins(镜像需同时带
      RUI_ADAPTER_PLUGINS 与 PYTHONPATH=/opt/rui-plugins);配置里的
      adapter: xiaoai 会自动迁移为 lx06 并告警。
    3. dot2 的 tls_port 开启 → 把 server.pem / server.key 放进挂载的 ./secrets,
      没有就 bash scripts/make_dev_tls.sh(自签不保证真机接受)。
    4. 确认入口:curl -s http://127.0.0.1:8080/health | jq -r .console → v2;
      curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' http://127.0.0.1:8080/
      → 302 …/v2/;老书签如 /panel/logs 也应返回 302 到 /v2/logs。
  • 回滚到旧入口(保留 0.7.8 镜像):配置写 web.console: legacy 后
    cd ~/rui && docker compose up -d --force-recreate —— / 与 15 条老链接恢复 200 旧壳,
    /health.console 报 legacy。操作细节见 docs/deploy.md §3.8。
  • 回滚到旧镜像:把 image 改回 rui:0.7.4(或生产组合 rui-dot2:1.3.1)后
    docker compose up -d --pull never;配置无需回退(0.7.x 都读 console 键,0.6.x
    忽略它并按旧壳运行)。

English (release notes summary / for the GitHub release)

rui 0.7.8 — MIT-licensed. rui-dot2-bridge 1.3.1 and rui-xiaoai-bridge
0.2.2 are unchanged (the 0.7.6 test move does not change plug behaviour).

Theme: four cards in one release — the TLS install path (0.7.5), per-device plane
visibility (0.7.5), the LX06 plug leaving core (0.7.6), and the console audit plus the
v2 default (0.7.7/0.7.8). No API or contract change (C-002/1, window
>=0.6.0 <0.8.0), no schema migration.

Versioning

0.7.5 / 0.7.6 / 0.7.7 get no tag of their own; they ship inside 0.7.8. Their exit
conditions (Done 6 on hardware, the built-in-vs-external dual run, upgrade and
rollback) all need the complete 0.7.8 tree and one hardware window; tagging them after
the fa...

Read more

rui 0.7.4 — P0/P1 fixes

Choose a tag to compare

@yes999zc yes999zc released this 26 Oct 15:09

rui v0.7.4 — 发布说明

日期:2026-10-26(待发布)
范围:rui 0.7.4 + rui-dot2-bridge 1.3.1(无改动,不 bump)+ rui-xiaoai-bridge 0.2.2(含 #25/xiaoai#1 重连复位修复)

主题:P0/P1 修复。本版新增一个状态码 413(请求体超限),401/422 语义不变。
镜像 digest 记录在 GitHub release body 与 docs/HANDOFF.md 的发布表;本文件不重复,避免 tag 树内出现占位值。
GitHub release body 即本文件(中英双语)。

行为变更

场景 0.7.3 0.7.4
请求体 > 1 MiB(默认;RUI_MAX_REQUEST_BYTES 可调) 进入解析/鉴权路径,无上限 413 {"detail":"request body too large"}(Content-Length 或流式累计超限)
无 token + 小 body 401 401(不变)
有效 token + 非法 JSON 422 422(不变)

其余 HTTP 状态码/handler 契约行为不变;31 个 v1 handler 的解析位置未动。

变更

rui 0.7.4(核心)

卡 内容
task-5 #18 请求体上限:新增 BodySizeLimitMiddleware(纯 ASGI,1 MiB,RUI_MAX_REQUEST_BYTES),Content-Length 超限直接 413、流式 body 累计超限 413;GET/HEAD 穿透;413 带安全响应头。#17 _greet 忙等:10 ms 轮询让出事件循环,握手 read_frame 用绝对 deadline;transient socket(Errno 57/reset/短读)在预算内重试,子进程退出时保留 exit code + stderr 末行
task-6 #28 微信渠道:cursor 保存进 finally;语音下载 10 MiB 上限 + 告警;pilk/ffmpeg 解码移到 asyncio.to_thread。#25 / xiaoai#1 重连复位:连接替换时复位 _playing/consumed/sink_generation;挂起的旧 play() 不会复活旧代际;旧 socket 的 consumed 事件不再推进新队列
task-7 发布材料:版本 0.7.4(pyproject / src/rui/__init__.py / uv.lock)、本 CHANGELOG 段、本文件、README quickstart 镜像 pin 0.7.3 → 0.7.4
C-002 docs/contracts/C-002-console-v2-api.md A-7:413/401/422 边界与「handler 解析位置不变」

rui-dot2-bridge 1.3.1

  • 无代码改动、不 bump;契约窗口不变。

rui-xiaoai-bridge 0.2.2

  • 含 #25/xiaoai#1 的重连复位修复(adapter.py),版本 0.2.1 → 0.2.2;契约窗口不变。

门禁(逐项可核)

卡 结论
task-5 #18/#17 reviewer-core PASS + verifier VERIFIED(含 flaky 30/30 与连续 3 次全量绿);commit cf42695
task-6 #28/#25 reviewer-core PASS(两轮 CHANGES 后)+ verifier VERIFIED;house 4468521、xiaoai 8f3ac46
task-7 发布材料 本卡:reviewer-core 评审 → verifier-tests 验证;结论由 Lead 在 tag 前确认

测试基线(0.7.4 工作树):house-ear 1652 passed / 17 skipped、rui-xiaoai-bridge 13 passed、rui-dot2-bridge 145 passed;三仓 ruff 全绿。

CI:tag v0.7.4 上的 ci / security / secret-scan / docker-publish 四绿(run 链接见 GitHub Actions 与 docs/HANDOFF.md 的发布表)。

产物

  • 镜像:ghcr.io/yes999zc/rui:0.7.4(digest 记录在 GitHub release body 与 docs/HANDOFF.md 的发布表;本文件不重复,避免 tag 树内出现占位值)。
  • 下游薄层(如重新构建):FROM ghcr.io/yes999zc/rui:0.7.4;完整 digest 用 GitHub release body / docs/HANDOFF.md 发布表记录的值固定。
  • /api/v2/meta 期望:rui_version=0.7.4、compat=0.6.0..<0.8.0;实际输出记录在 docs/HANDOFF.md 发布表。
  • 回滚:把 override / compose 的 image 改回上一稳定版本(rui:0.7.3 或生产 rui-dot2:1.3.1 组合),docker compose up -d --pull never。

已知限制(不阻塞发布)

沿用 0.7.3 的运行时限制:

  1. cue 回声的边界情形:冷启动且不削波且设备滞后 >800 ms、或用户与 cue 重叠 <110 ms 时,cue 仍可能进入 ASR。
  2. runner.abort() 仍是全局单标志:A 房唤醒会中止 B 房正在合成的回复。
  3. 已播出的告别尾音无法追回:只能阻止后续 chunk。
  4. 唤醒词不按房间隔离;DOT2_CONTROL_PORT 是全局 env。
  5. 多设备并发未测(音量/指示灯/四台同时在线)。

0.7.4 新增(来自本轮实现边界):

  1. 微信流式超限分支未被测试覆盖:测试只覆盖了 Content-Length 超限;无长度头的累计超限路径有实现、无单测。
  2. getupdates 响应未设上限:轮询响应仍由 httpx 整体读入,未加字节上限(语音下载已加)。
  3. 413 响应缺 Permissions-Policy:已带 X-Content-Type-Options / X-Frame-Options / Referrer-Policy / Cache-Control,未带 Permissions-Policy(该头对 JSON 无实际作用)。

合规

  • 三仓 LICENSE 均为 MIT。
  • 未新增品牌字样、未新增对外宣传话术;文档不含 VPN/穿透/代理内容,不含内网地址与凭证。

升级与回滚

  • 升级:RUI_IMAGE=ghcr.io/yes999zc/rui:0.7.4 bash deploy/install.sh,或把 override 的 image: 改为 ghcr.io/yes999zc/rui:0.7.4 后 docker compose up -d。
  • 无配置变更、无 schema 迁移;rui_compat 仍为 >=0.6.0 <0.8.0;dot2 保持 1.3.1,xiaoai 为 0.2.2。
  • 回滚:改回 rui:0.7.3 后重启;配置无需回退。

English(release notes 摘要 / for the GitHub release)

rui 0.7.4 · rui-dot2-bridge 1.3.1 · rui-xiaoai-bridge 0.2.2 — three MIT-licensed repos.

Theme: P0/P1 fixes. 0.7.4 adds exactly one status code, 413 for an oversized
request body; the 401 and 422 semantics are unchanged.

What changed in rui 0.7.4

  • Request bodies are bounded before parsing (#18). A pure ASGI middleware rejects
    a declared Content-Length above 1 MiB (configurable via RUI_MAX_REQUEST_BYTES)
    with 413, and counts streamed bodies so a chunked upload cannot grow memory past
    the cap. Missing/bad token stays 401 and invalid JSON with a valid token stays 422.
  • _greet no longer blocks the event loop (#17). The socket wait yields every
    10 ms, and the handshake read_frame uses one absolute deadline for header and
    payload. Transient socket errors are retried within the greet budget; if the child
    exited, the error keeps its exit code and the last stderr lines.
  • The WeChat channel survives one bad message (#28). The getupdates cursor is
    saved in finally, voice downloads are capped at 10 MiB, and pilk/ffmpeg decoding
    runs in asyncio.to_thread.
  • Reconnecting resets the player (#25 / xiaoai#1). Replacing the speaker socket
    resets _playing / consumed / sink_generation; a suspended old play() cannot
    resurrect it, and events from the replaced socket cannot advance the new player.
    Mirrored in rui-xiaoai-bridge 0.2.2.

Evidence

  • house-ear 1652 passed / 17 skipped; rui-xiaoai-bridge 13 passed;
    rui-dot2-bridge 145 passed; ruff green in all three.
  • Each fix has a reverse-mutation check: removing its guard makes the targeted test
    fail.

Known limitations

Unchanged from 0.7.3 (cue-echo edges, single-session runner, non-recallable goodbye,
per-room wake words, concurrent multi-device untested). New: the WeChat streamed
over-limit path has no test (only Content-Length), getupdates responses have no
size cap, and 413 omits Permissions-Policy (the other security headers are present).

rui 0.7.3 — test baseline and reproducible CI

Choose a tag to compare

@yes999zc yes999zc released this 26 Oct 14:05

rui v0.7.3 — 发布说明

日期:2026-10-26(待发布)
范围:rui 0.7.3 + rui-dot2-bridge 1.3.1 + rui-xiaoai-bridge 0.2.1(三仓 MIT;两个桥本版无代码改动,不 bump)

本版无行为变更:0.7.3 只做测试与 CI 基建、未覆盖清单与文档口径收口,不改运行路径、不改契约。
镜像 digest、tag 链接与 /api/v2/meta 输出在 Lead 打 tag / 构建镜像后回填 §产物。
GitHub release body 即本文件(中英双语)。

变更

rui 0.7.3(核心)

卡 内容
task-1 覆盖率基建与基线:pyproject.toml dev extra 增加 pytest-cov;CI test job(Python 3.11 / 3.12)跑 --cov=rui --cov-branch 并上传 coverage.json / pytest-report.xml / python-version.txt;新增 scripts/coverage_report.py、docs/audit/coverage-baseline.md + .json(0.7.3 基线 80.95% 行 / 69.55% 分支)
task-2 未验证清单 batch-1:HE-03(first_response_ms 为 null 时保持「证据不足」,不补 0)、HE-12(源码 plugs/ fallback 授权 in-process adapter)、D2-06(dot2 stop_playback 活跃流 flush 不吞下一段回复);每条都有反向变异验证
task-3 缺口台账与 8 处文档矛盾收口:docs/audit/unverified-inventory.md 增加每包覆盖率台账、三类缺口、26 条真机协议(命令/判据/记录表)、8 条终态;三仓 README/ CHANGELOG/规范文档口径统一
task-4 发布材料:版本号 0.7.3(pyproject / src/rui/__init__.py / uv.lock)、本 CHANGELOG 段、本文件、README quickstart 镜像 pin 0.7.2 → 0.7.3

rui-dot2-bridge 1.3.1

  • 无代码改动、不 bump;与 rui 0.7.3 的 rui-device/v1 契约一致(新增 D2-06 回归测试在桥仓 tests/)。

rui-xiaoai-bridge 0.2.1

  • 无代码改动、不 bump;契约窗口不变。

门禁(逐项可核)

卡 结论
task-1 覆盖率基建 reviewer-core PASS + verifier VERIFIED;coverage artifacts coverage-3.11 / coverage-3.12 存在(发布 CI 的四绿见下方「CI」行)
task-2 batch-1 三条测试 reviewer-core PASS + verifier VERIFIED(verifier 独立复做 D2-06 变异并还原);house 全量 1634 passed / 17 skipped
task-3 覆盖台账与 8 处矛盾 reviewer-core PASS + verifier-docs VERIFIED(两轮 FAILED 后修正 2 条事实错误 + 3 处引用行号);三仓 docs 改动无代码影响
task-4 发布材料 本卡:reviewer-core 评审 → verifier-tests 验证;结论由 Lead 在 tag 前确认

测试基线(0.7.3 工作树):house-ear 1651 collected / 1634 passed / 17 skipped / 0 xfail、dot2 145 passed、xiaoai 9 passed;覆盖率 80.95% 行 / 69.55% 分支(docs/audit/coverage-baseline.md);三仓 ruff 全绿。

CI:tag v0.7.3 上的 ci / security / secret-scan / docker-publish 四绿(run 链接见 GitHub Actions 与 docs/HANDOFF.md 的发布表)。

产物

  • 镜像:ghcr.io/yes999zc/rui:0.7.3(digest 记录在 GitHub release body 与 docs/HANDOFF.md 的发布表;本文件不重复,避免 tag 树内出现占位值)。

  • 下游薄层(如重新构建):FROM ghcr.io/yes999zc/rui:0.7.3;完整 digest 用 GitHub release body / docs/HANDOFF.md 发布表记录的值固定。

  • /api/v2/meta 期望:rui_version=0.7.3、compat=0.6.0..<0.8.0;实际输出记录在 docs/HANDOFF.md 发布表。

  • 回滚:把 override / compose 的 image 改回 rui:0.7.2(或生产当前 rui-dot2:1.3.1 组合),docker compose up -d --pull never。

已知限制(不阻塞发布)

沿用 0.7.2 的运行时限制(未在 0.7.3 改变):

  1. cue 回声的边界情形:冷启动且不削波且设备滞后 >800 ms、或用户与 cue 重叠 <110 ms 时,cue 仍可能进入 ASR。
  2. runner.abort() 仍是全局单标志:A 房唤醒会中止 B 房正在合成的回复(runner 单会话限制)。
  3. 已播出的告别尾音无法追回:只能阻止后续 chunk。
  4. 唤醒词不按房间隔离;DOT2_CONTROL_PORT 是全局 env。
  5. 多设备并发未测(音量/指示灯/四台同时在线)——见 HANDOFF「待设备」段。

0.7.2 的第 6 条(uv.lock 内仍写旧版本号 0.2.0)已在 0.7.3 修复:uv.lock 的 rui version = 0.7.3,uv lock --check exit 0。

合规

  • 三仓 LICENSE 均为 MIT。
  • 未新增品牌字样、未新增对外宣传话术;文档不含 VPN/穿透/代理内容,不含内网地址与凭证。

升级与回滚

  • 升级:RUI_IMAGE=ghcr.io/yes999zc/rui:0.7.3 bash deploy/install.sh,或把 override 的 image: 改为 ghcr.io/yes999zc/rui:0.7.3 后 docker compose up -d。
  • 无配置变更、无 schema 迁移;rui_compat 仍为 >=0.6.0 <0.8.0,两个桥版本不变。
  • 回滚:改回 rui:0.7.2(digest sha256:d830a2ca029b27f5c25115680746ae533c7e0093e0fe61f1541bd5a0a4dd8018)后重启;配置无需回退。

English(release notes 摘要 / for the GitHub release)

rui 0.7.3 · rui-dot2-bridge 1.3.1 · rui-xiaoai-bridge 0.2.1 — three MIT-licensed repos.

This release has no behaviour change. 0.7.3 is test and CI infrastructure, a
coverage/gap ledger, and documentation consistency work; runtime paths and the
plugin contract are unchanged.

What changed in rui 0.7.3

  • Coverage is produced by every CI test job (Python 3.11 and 3.12) and uploaded
    as coverage-<py> artifacts. scripts/coverage_report.py generates the package
    table and the machine-readable baseline; 0.7.3 is 80.95% line / 69.55% branch.
  • An independent rui plug-test smoke runs against tests/fixtures/sample-plug,
    with no dependency on plugs/xiaoai (removed in 0.7.5).
  • Batch-1 unverified items became automated tests: a null first_response_ms
    stays evidence-insufficient (never 0), the source-run plugs/ fallback authorises
    an in-process adapter, and dot2 stop_playback on an active stream no longer
    swallows the next reply. Each test has a reverse mutation check.
  • Documentation: a per-package coverage ledger with a three-way gap
    classification, 26 real-device protocols (command / criterion / record table),
    and eight resolved document contradictions across the three repos.

Bridges

  • rui-dot2-bridge 1.3.1: no code change, version unchanged; adds a D2-06 regression
    test only. rui_compat stays >=0.6.0 <0.8.0.
  • rui-xiaoai-bridge 0.2.1: no code change, version unchanged.

Evidence

  • house-ear: 1651 collected / 1634 passed / 17 skipped / 0 xfail; dot2 145
    passed
    ; xiaoai 9 passed; coverage 80.95% line / 69.55% branch
    (docs/audit/coverage-baseline.md); ruff green in all three repos.
  • CI: ci / security / secret-scan / docker-publish are green on tag v0.7.3
    (run links live in GitHub Actions and the release table in docs/HANDOFF.md).

Known limitations

Unchanged from 0.7.2: cue-echo edge cases, single-session dialogue runner,
non-recallable spoken goodbye, per-room wake-word isolation, and untested
concurrent multi-device behaviour. The 0.7.2 uv.lock stale-version limitation is
fixed in 0.7.3.

rui 0.7.2

Choose a tag to compare

@yes999zc yes999zc released this 26 Oct 11:24

rui v0.7.2 — 发布说明

日期:2026-10-26(已发布)
范围:rui 0.7.2 + rui-dot2-bridge 1.3.1 + rui-xiaoai-bridge 0.2.1(三仓 MIT)

镜像 digest、tag 链接与 /api/v2/meta 输出见 §产物(发布后回填,已核对)。
GitHub release body 即本文件(中英双语)。

变更

rui 0.7.2(核心)

commit 内容
87bb704 fix(audio):唤醒后的 ack cue 不再进入 ASR——包络在 skip+hold 整段定位 cue、学习设备滞后 EMA(仅首轮命中更新)、_quiet_after 防把 TTS 回复当 cue;削波时保守丢 cue+1000 ms
3bbf93f fix(arbiter):播放态与 turn 态按房间隔离——一屋放歌不再拒另一屋的唤醒(试跑实测跨房 lost_playing 从 6 分钟 18 次降到 0)
989baa1 fix(session):普通唤醒撞上进行中的告别 TTS 时,flush 已入队语音 + 阻塞迟到 PLAY_PCM;farewell 在 abort 后不再清标志;所有 gate.disarm() 出口统一收口为 _disarm_gate(),静音唤醒后 reminder/console 语音不会被吞
dee693f chore(release):版本 0.7.2;rui_compat 窗口维持 >=0.6.0 <0.8.0
文档 docs/analysis/dot2-vs-xiaoai.md(P0 矩阵 + P1 归因)、docs/analysis/wake-vs-command-range.md(含结论更正:早期"指令要凑近"系未校准音源的装置伪影)、docs/device-access.md(设备接入索引,无凭证)

rui-dot2-bridge 1.3.1

  • 兼容窗口不变(>=0.6.0 <0.8.0),桥侧无破坏性改动;与 rui 0.7.2 的 rui-device/v1 契约一致。

rui-xiaoai-bridge 0.2.1

  • 兼容窗口不变;仓库已公开(历史扫描通过,见 §合规)。

门禁(逐项可核)

卡 结论
task-15 ack cue 不进 ASR reviewer-barge PASS + verifier VERIFIED(限定范围);真机 A/B cue 泄漏 0/10(修复前 13/26)
task-18 播放态按房间隔离 reviewer PASS + verifier VERIFIED;真机回归:客厅放歌时卧室 4/4 admitted、跨房 lost_playing 0
task-19 音乐中短指令 reviewer PASS + verifier VERIFIED(5 轮后收口);真机人声 A/B:下一首 5/5、停止播放 5/5(合计 10/10)
task-16 距离/电平分析 reviewer PASS(两轮修正后);校准后人声 1 m / 2 m 均 9/9 功能成功
task-20 xiaoai 扫描+公开 reviewer PASS + verifier VERIFIED(HEAD d741876)
task-17 AEC-lite PARKED(一轮门禁 CHANGES 后按熔断停止,见 §已知限制)

测试基线(发布提交):house-ear 1626 passed / 17 skipped、dot2 143 passed、xiaoai 9 passed;三仓 ruff 全绿。

产物

镜像 digest 备注
rui:0.7.2 sha256:d830a2ca029b27f5c25115680746ae533c7e0093e0fe61f1541bd5a0a4dd8018(ghcr.io/yes999zc/rui, tag commit ad11936) 由 docker-publish 从 tag v0.7.2 构建,另带 0.7/latest/sha-ad11936
rui-dot2:1.3.1 本地镜像 ID sha256:92ea98f436bbadbce118bfa6e63864fe160fdb2ebfcae25444cb96397ebf8a6a(未推 registry) 下游薄层:FROM ghcr.io/yes999zc/rui:0.7.2@sha256:d830a2ca… + dot2 plug 1.3.1,NAS 上构建
生产部署 NAS 168 已切到 rui-dot2:1.3.1(2026-10-26 19:31,healthy) /api/v2/meta → rui_version=0.7.2、compat=0.6.0..<0.8.0
  • 回滚:override 改回上一稳定组合(rui-dot2:1.3.0-r071)+ docker compose -f docker-compose.yml -f rui-dot2-override.yml up -d --pull never。
  • p21/p22/p23 是开发期测试薄层镜像,不是发布产物。

已知限制(不阻塞发布)

  1. cue 回声的边界情形:冷启动且不削波且设备滞后 >800 ms、或用户与 cue 重叠 <110 ms 时,cue 仍可能进入 ASR(task-17 的 AEC-lite 已 park,未合入)。
  2. runner.abort() 仍是全局单标志:A 房唤醒会中止 B 房正在合成的回复(runner 单会话限制;按房隔离目前只在 arbiter 层)。
  3. 已播出的告别尾音无法追回:只能阻止后续 chunk,彻底消音需「本机 TTS 参考消减」。
  4. 唤醒词不按房间隔离;DOT2_CONTROL_PORT 是全局 env,加第 2 台 Dot2 前必须清。
  5. 多设备并发未测(音量/指示灯/四台同时在线)——见 HANDOFF「待设备」段。
  6. uv.lock 内仍写旧版本号(0.2.0),不影响运行,记入 post-release backlog。

合规

  • 三仓 LICENSE 均为 MIT。
  • rui-xiaoai-bridge 公开前完成全历史扫描:token/私钥、内网 IP、个人绝对路径、MAC 均为 0;commit author 邮箱为公开元数据;公开后 secret scanning 与 push protection 已启用、alerts 0(d741876)。
  • 文档已不含内网地址(cf05f58),secret-scan CI 转绿。

升级与回滚

  • 升级:RUI_IMAGE=rui-dot2:1.3.1 docker compose up -d --pull never(或改 override 的 image:)。
  • 回滚:改回 rui-dot2:1.3.0-r071 并 up -d;数据目录/配置不需要迁移(无 schema 变更)。

English(release notes 摘要 / for the GitHub release)

rui 0.7.2 · rui-dot2-bridge 1.3.1 · rui-xiaoai-bridge 0.2.1 — three MIT-licensed repos, released together.

What changed in rui 0.7.2

  • The wake acknowledgement cue no longer reaches ASR. The gate matches the cue envelope across the skip window and the hold buffer, learns the device's playback lag, and requires silence right after the cue so a TTS reply is never mistaken for it. Device A/B: cue leakage 0/10 (previously 13 of 26 turns).
  • Playback and turn state are scoped per room. One room playing music used to reject every other room's wake with lost_playing (18 rejections in six minutes of two-room sampling); cross-room wakes are now admitted, while cross_echo still guards a second plane inside the playing room.
  • Our own stale speech is dropped when a wake arrives. Queued goodbye chunks are flushed on an accepted wake, late PLAY_PCM is blocked until that turn's utterance lands, and every gate close path clears the block so reminders keep working after a silent wake.

Bridges

  • rui-dot2-bridge 1.3.1: no behavioural change; rui_compat stays >=0.6.0 <0.8.0, validated against 0.7.2 (wake 30/30, commands 26/30, barge-in 8/8, short commands during music 10/10).
  • rui-xiaoai-bridge 0.2.1: the repo is now public after a full-history secret scan (0 tokens/keys, 0 internal IPs, 0 personal paths, 0 MACs); secret scanning and push protection are enabled.

Known limitations

  • Cue echo can still reach ASR on a cold start with no clipping and >800 ms device latency, or when the user overlaps the cue by less than 110 ms.
  • The dialogue runner is single-session: a wake on one device aborts a reply being synthesised for another.
  • A goodbye already spoken cannot be recalled; only queued chunks are dropped.
  • Wake words are not isolated per room yet; concurrent multi-device behaviour is untested.