Flux Purr
Flux Purr 是 embedded firmware + React control console 的设备 mono-repo。README.md 将仓库组织为 firmware/、web/、tools/flux-purr-devd/、docs/specs/、docs/hardware/、.
- Device mono-repo
- Embedded Rust
- Rust source quality
- ESP32 firmware
- React app
- shadcn/ui
- Storybook accessibility
- Storybook component QA
- PR label release
- Release failure notification
- Quality gates
- GitHub Actions scheduling
- MCU flashing integration
- Worktree bootstrap
目录
技术栈
运行与交付
- CI 工作流
- ci-main.yml
- ci.yml
- label-gate.yml
- notify-release-failure.yml
- release-completion.yml
- release-preparation.yml
- release.yml
- 能力标记
- bun_lock
- cargo_toml
- github_actions
- package_json
依赖与工具
- package.json
- 开发依赖
- @commitlint/cli
- @commitlint/config-conventional
- commitlint-plugin-function-rules
- lefthook
- 项目脚本
- bootstrap:dev
- build:firmware:web
- check:devd
- check:e2e
配置与质量
- 配置文件
- .env.example
- .gitattributes
- .gitignore
- Cargo.toml
- espflash.toml
- lefthook.yml
- package.json
- rust-toolchain.toml
{
"ci_workflows": [
"ci-main.yml",
"ci.yml",
"label-gate.yml",
"notify-release-failure.yml",
"release-completion.yml",
"release-preparation.yml",
"release.yml"
],
"configs_root": [
".env.example",
".gitattributes",
".gitignore",
"Cargo.toml",
"espflash.toml",
"lefthook.yml",
"package.json",
"rust-toolchain.toml"
],
"markers_present": [
"bun_lock",
"cargo_toml",
"github_actions",
"package_json"
],
"package_json": {
"deps_dev": [
"@commitlint/cli",
"@commitlint/config-conventional",
"commitlint-plugin-function-rules",
"lefthook"
],
"scripts": [
"bootstrap:dev",
"build:firmware:web",
"check:devd",
"check:e2e",
"check:firmware:build",
"check:firmware:clippy",
"check:firmware:fmt",
"check:storybook",
"check:web",
"check:web:build",
"hooks:install",
"prepare",
"test:worktree-bootstrap",
"worktree:setup"
]
}
}Purpose
Flux Purr 是 embedded firmware + React control console 的设备 mono-repo。README.md 将仓库组织为 firmware/、web/、tools/flux-purr-devd/、docs/specs/、docs/hardware/、.github/ 和 scripts/;它是从硬件研究、固件 bring-up 到控制台、host tooling 与 release workflow 的完整产品,而非单一前端或 crate。
Taxonomy
- Tags: Device mono-repo, Embedded Rust, Rust source quality, ESP32 firmware, React app, shadcn/ui, Storybook accessibility, Storybook component QA, PR label release, Release failure notification, Quality gates, GitHub Actions scheduling, MCU flashing integration, Worktree bootstrap
- Why / evidence: 产品结构由
README.md、firmware/Cargo.toml、web/package.json、tools/flux-purr-devd/Cargo.toml、web/components.json与web/.storybook/main.ts支撑。Rust source-quality contract 由docs/solutions/engineering/rust-style-debt-remediation.md、docs/guides/flux-purr-developer-policy.md、package.json、scripts/check-firmware-fmt.sh、scripts/check-firmware-clippy.sh、scripts/check-firmware-clippy-xtensa.sh、scripts/check-rust-style.sh、firmware/clippy.toml、tools/flux-purr-devd/clippy.toml与tools/rust-style-check/支撑。发布与质量 contract 由.github/quality-gates.json、.github/workflows/label-gate.yml、.github/workflows/release-preparation.yml、.github/workflows/release-completion.yml、.github/workflows/release.yml与.github/workflows/notify-release-failure.yml支撑;已合并的 PR #102 将 required-gate scheduling 收敛为queue: max与 runtime label snapshot。根VERSION与scripts/product-version.py定义统一产品 identity。
Repository map
firmware/是 Rustno_stdESP32-S3 domain crate,firmware/Cargo.toml暴露flux-purr主 binary 和 host-preview binaries。web/是 Vite/React/shadcn/ui 控制台,web/components.json记录new-yorkstyle、Tailwind CSS variables、Lucide icon library 和@/components/uialiases。tools/flux-purr-devd/提供本机 daemon 与flux-purrCLI;它与 firmware、Web 共同消费产品 identity。VERSION、scripts/product-version.py与.github/scripts/release_chain.py分别定义版本解析及 VERSION-only preparation / main-merge provenance 验证。.github/quality-gates.json、label-gate.yml、release-preparation.yml、release-completion.yml、release.yml与notify-release-failure.yml构成统一产品 release surface,不再以过期的 firmware/Web 独立发布表示产品身份。
Runtime and delivery
根 package.json 编排 firmware fmt/clippy/build、Web check/build、Storybook build 与 e2e;Web 保持独立的 Storybook、交互测试与 bundle build;firmware 与 UI 也不共享一个“build succeeded”的含义。Worktree bootstrap 恢复 root/web Bun 依赖和 Cargo fetch 预热,同时把 Playwright browser cache 与系统前置条件保留为 warning 或手工修复路径(scripts/bootstrap-dev.sh、scripts/test-worktree-bootstrap.sh)。
根 VERSION 是唯一产品版本权威。开发、测试、firmware、flux-purr-devd、CLI、Web build、bundle、manifest 与 release 都只读它;开发 identity 是 nextPatch(VERSION)-dev.<short-sha>,不会写回文件。Cargo/NPM package metadata、Git tag、PR label、snapshot、环境变量和旧 manifest 都不得成为数字版本来源或 fallback(docs/specs/version-source/SPEC.md、scripts/product-version.py)。
产品 PR 在完整 PR CI 与 Validate PR labels 成功后,由 Prepare product version 在同一分支追加只修改 VERSION 的 preparation commit。其 trailers 固化 source SHA、产品版本和已验证 intent;Release completion 核验准备提交、base、labels 与源提交 CI,PR 仍以普通 merge commit 进入 main。Release Product 从合并后的 main 读取锁定 VERSION,一次构建、发布、校验 Web、public demo、firmware 与 host-tools 资产,并从同一归档各部署一次。v0.23.1 是这条完整链路已验证发布;recovery 只能重发同一 main commit/version(docs/adr/0005-pr-local-version-preparation.md、docs/adr/0006-tag-reservation-and-legacy-release-reconciliation.md、.github/workflows/release.yml)。
当 GitHub Actions 需要在 signed-commit 规则下创建该 preparation commit 时,workflow 将写入权限限定为 contents: write,并按 PR/check metadata 验证需要声明 pull-requests: read、checks: read,再使用 job 的 GITHUB_TOKEN 调用 GraphQL createCommitOnBranch。mutation 将 source SHA 作为 expectedHeadOid,只添加 VERSION,并在返回 OID 前后核对 PR branch head;因此并发 source 更新会失败,而不会被静默覆盖。它不配置 RELEASE_GPG_PRIVATE_KEY 或 RELEASE_GPG_PASSPHRASE。无论 preparation 是刚创建还是已存在,后续都验证 branch head、单父/仅 VERSION/trailers provenance,并在有界重试后要求 GitHub commit verification.verified 为真;任一检查失败即停止,而不降低 signed-commit 规则(.github/workflows/release-preparation.yml、.github/scripts/release_chain.py、.github/scripts/test-release-workflows.sh、docs/solutions/release/github-native-verified-version-commit.md)。
Architecture notes
可复用的架构记忆是“双运行面 + 共享验收 + 单一产品 identity”:firmware 负责 ESP32-S3 front-panel 行为,Web 负责控制台和组件状态,tools/flux-purr-devd/ 负责本机控制面,docs/specs/ 持有可执行验收合同。host-preview binary 在无板条件下提供固件早期验证。
当工程同时有 firmware、daemon、CLI、Web 与 release manifest 时,不能让各 consumer 从 package manifest 或环境变量各自重算版本。此仓库通过 scripts/product-version.py 集中派生稳定/RC、开发 qualifier、channel、source SHA 与 build ID,再投递给各 runtime 与 asset identity(docs/specs/version-source/IMPLEMENTATION.md)。
Workflow and quality gates
.github/quality-gates.json 要求 signed commits、PR-only main 与 workflow-backed checks。每个 PR 必须且仅能有一个 type:* 和一个 channel:*;Validate PR labels 是 merge 前 required check,但 labels 只表达发布意图,不能计算或覆盖 VERSION 数字内容(.github/workflows/label-gate.yml、docs/adr/0003-version-file-is-the-product-version-source.md)。
Validate PR labels 与 Release completion 是每 PR 的 required gate:它们分别使用 label-gate-<pr> 和 release-completion-<pr> concurrency group,并设 queue: max、不设 cancel-in-progress: true,使已排队的 gate 以非抢占方式完成。每个 job 都在 trusted base revision github.event.pull_request.base.sha || github.sha checkout;它以 pull-requests: read 的 job token 在运行时调用 gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq '.labels',把当前 labels JSON 传入 validator。这样 gate 不会信任可能在排队期间过时的 event payload labels,也不会为读取 labels 执行不可信 PR 内容(.github/workflows/label-gate.yml、.github/workflows/release-completion.yml)。
Rust source-quality gate 独立于产品 release gate,按四层执行:cargo fmt --all -- --check 负责格式;firmware 与 devd 的 crate-local clippy.toml 配合 -D warnings、too_many_lines、too_many_arguments、excessive_nesting 负责语义 lint;cargo +esp clippy 在 Xtensa target 和 12V/20V/28V feature matrix 上覆盖 target-only code;tools/rust-style-check/ 使用 syn 检查入口文件预算、inline tests 和结构性 allow/expect。这些入口由 package.json、scripts/check-firmware-fmt.sh、scripts/check-firmware-clippy.sh、scripts/check-firmware-clippy-xtensa.sh 与 scripts/check-rust-style.sh 编排。100/7/4 是当前 firmware/devd 的 crate-local 配置和 checker profile,不是跨项目阈值;零结构债务和禁止结构性豁免是该仓库的本地边界,也不替代 target-aware lint(firmware/clippy.toml、tools/flux-purr-devd/clippy.toml、tools/rust-style-check/src/main.rs、docs/solutions/engineering/rust-style-debt-remediation.md)。
PR #102 已于 2026-09-09 合并到 f34dffcac6b3385237e0fe6a31d21f52867b0bc1;其 .github/scripts/test-release-workflows.sh 直接断言两个 required workflow 都含 queue: max、不含 cancel-in-progress: true,并使用当前 labels API snapshot。该验证也记录了本地 actionlint 1.7.12 尚不识别该 GitHub 已文档化语法:在 GitHub Actions concurrency documentation 与 runtime 支持明确之前,它们是权威;兼容性进展跟踪在 actionlint #687。
完整 PR CI 只针对产品源提交运行一次;preparation commit 只做结构验证,CI Main 验证 normal merge relation。带有效 preparation 的 merge 才可进入产品发布。type:docs 与 type:skip non-product merge 使 Release Product 成功 skip,不发布、不部署,也不触发失败通知(.github/workflows/release.yml、.github/workflows/notify-release-failure.yml)。发布失败后,预先锁定在 main/VERSION 的版本必须通过同 SHA recovery 收口,不能计算 successor 或把多次变更压缩为一个 release(docs/specs/version-source/SPEC.md)。
Reusable decisions
- 将 Rust source quality 拆成格式、语义 lint、源码结构和 target/features coverage 四层;入口脚本分别表达这些层,避免把
rustfmt或 host Clippy 当成完整质量证明。 - 把函数行数、参数数和嵌套深度放进 crate-local
clippy.toml,让 firmware 与 host tooling 可以共享方向但独立演进;当前100/7/4只代表 Flux Purr 的参考 profile。 - 对 firmware 入口同时保留 host feature matrix 与 Xtensa target matrix;target-only code 必须在实际 release target 上 lint,不能用 host 结果替代。
- 用
synchecker 约束 source shape 和结构性豁免边界,配合按职责拆分入口文件;不设全仓文件长度阈值,也不通过allow/expect或宏隐藏结构债务。 - 将
components.json与 Storybook a11y 保持在 Web 子项目,避免 shadcn/ui 约定扩散至 firmware。 - host preview binary 是硬件项目降低验证成本的有效模式。
- Worktree bootstrap 负责 repo-managed dependency recovery,但不应在 hook 中隐式进行不可控外部下载。
- 用一个 checked-in 产品版本文件作为唯一权威,让 tags、package metadata、labels、snapshots 与环境变量退回为派生或 intent 信息。
- 用同一个 resolver 为 runtime、CLI、bundle、Web build-info 和 manifest 提供 identity,避免多语言 mono-repo 版本漂移。
- 将版本写入置于同一产品 PR、完整 CI 之后且 normal merge 之前:preparation 只改
VERSION并携带可验证 provenance。 - 对受 signed-commit 规则保护且由 GitHub Actions 创建的 preparation,使用 GitHub-native
createCommitOnBranch、GITHUB_TOKEN与expectedHeadOid,而非请求或保存仓库 GPG 私钥/口令;created 与 existing 两种状态都必须验证 GitHub 签名。 - 保留 label gate 作为 required intent gate;自动 patch 与受控 exact 只决定写入操作,写入后版本文件独占数字版本事实。
- 普通 PR candidate 可按最新提交取消过期工作;
Validate PR labels与Release completion这类 required gate 则用 per-PRqueue: max非抢占排队,并在 job runtime 取得当前 labels snapshot。 - 当
actionlint版本落后 GitHub workflow syntax 时,不为静态工具绿灯删除 required-gate 调度语义;以 GitHub 官方文档、runtime 和项目 workflow fixture 作为临时权威,并保留 issue 跟踪。 - 从 normal main merge 一次构建、校验、发布并部署归档;发布失败时只允许同 SHA recovery。
Risks and open questions
- 主分支必须保留 merge commit,且
Release completion与Validate PR labels同为远端 required checks;否则无法证明 preparation 仍是受保护合并的一部分。 - 版本解析、preparation diff/provenance、main merge relation 与 asset manifest 必须一起验证;只检查 Web display 或 Git tag 会漏掉跨 consumer 漂移。
- tag reservation 需要在 preparation 前和 release build 前重复检查;已有 tag 只有精确指向同一 main merge 时才可被 recovery 复用。
- GitHub 的签名状态可能晚于 mutation 返回;不能把 existing preparation 或返回的 OID 当作签名证明,必须在有界重试后 fail closed。
queue: max最多保留 100 个 pending run,且 FIFO 以开始等待 concurrency group 的时间计;不要把 dispatch 时间当成严格全序,也不要与cancel-in-progress: true组合。- label snapshot 必须随 required gate 的实际执行重新读取;只以事件 payload 或 preparation 前的 labels 推断 release intent,会让延迟 gate 对当前 PR 状态作出过时判断。
Evidence index
README.mdfirmware/Cargo.tomlfirmware/clippy.tomlweb/package.jsonpackage.jsontools/flux-purr-devd/Cargo.tomltools/flux-purr-devd/clippy.tomltools/rust-style-check/Cargo.tomltools/rust-style-check/src/main.rsweb/components.jsonweb/.storybook/main.tsVERSIONscripts/product-version.py.github/scripts/release_chain.py.github/quality-gates.json.github/workflows/label-gate.yml.github/workflows/release-preparation.yml.github/workflows/release-completion.yml.github/workflows/release.yml.github/workflows/notify-release-failure.yml.github/scripts/test-release-workflows.shscripts/check-firmware-fmt.shscripts/check-firmware-clippy.shscripts/check-firmware-clippy-xtensa.shscripts/check-rust-style.shscripts/bootstrap-dev.shscripts/test-worktree-bootstrap.shdocs/specs/version-source/SPEC.mddocs/specs/version-source/IMPLEMENTATION.mddocs/adr/0003-version-file-is-the-product-version-source.mddocs/adr/0005-pr-local-version-preparation.mddocs/adr/0006-tag-reservation-and-legacy-release-reconciliation.mddocs/solutions/release/github-native-verified-version-commit.mddocs/solutions/engineering/rust-style-debt-remediation.mddocs/guides/flux-purr-developer-policy.md- Flux Purr PR #102
- GitHub Actions concurrency documentation
- actionlint issue #687
相关内容
Config-driven ops
主题Config-driven ops 表示操作命令、硬件目标、端口、artifact、backend 或运行策略优先通过 checked-in 配置声明,而不是让维护者每次手写临时命令。它适合 MCU flashing、服务端口、部署资源和多 Agent 协作场景。
Device mono-repo
主题Device mono-repo 表示一个仓库同时承载硬件资料、固件、Web/desktop UI、docs/specs、测试工具或发布流程。它强调边界协调:硬件、firmware、UI 和文档互相影响,不应把仓库当作单一应用。 这个 Topic 的核心是设备级知识不能被某一个技术栈吞掉。
Embedded Rust
主题Embedded Rust 表示 Rust 代码运行在 MCU、driver、firmware 或硬件 bring-up 环境中,通常涉及 no_std、Embassy、esp-hal、STM32/ESP32、probe-rs、espflash 或 embedded-hal。它不是所有 Rust 项目的泛化标签。
ESP32 firmware
主题ESP32 firmware 表示项目把 ESP32 家族 MCU 作为正式固件目标来维护,并围绕 toolchain、烧录、板级职责、连接能力和与其他 MCU/上位机的分工建立了稳定约定。这里的重点不是“芯片型号”,而是 ESP32 在系统里承担什么角色。 这个 Topic 往往不只是单片机源码。
GitHub Actions scheduling
主题GitHub Actions scheduling 表示仓库把 workflow 触发事件、并发 namespace、cancel-in-progress 和 required check 可见性组织成可审计的运行调度合同。目标不是让每个事件只跑一次,而是让当前 PR head 获得正确且可观察的 gate,同时不让无关 PR、main、deploy 或手工任务被同一个并发键误取消。
MCU flashing integration
主题MCU flashing integration 表示项目通过 espflash 管理 ESP32 系列,通过 probe-rs 管理 STM32/其他 probe-supported MCU,并把这些 backend 接入项目配置或明确的本地操作入口。Topic token 使用可复用工程模式命名;espflash 与 probe-rs 作为具体工具名放在定义和证据里。 这个 Topic 关注的是“硬件操作入口可复现且可审计”。
PR label release
主题PR label release 是逐 PR 的产品发布协议:PR labels 只提供经过 gate 验证的发布操作与发布阶段;最高的合格 final vX.Y.Z Git release tag 是唯一数字版本基线,VERSION 只锁定 trusted preparation 已决定的精确产品版本。label 不能计算、覆盖或为版本提供 fallback。
Quality gates
主题Quality gates 表示仓库把“什么叫可以合并、什么叫可以发布”写成了显式、可审计的契约,并通过本地脚本、CI workflows、review/signature policy、GitHub required checks 或同类机制把它执行出来。它关注的是 gate contract,而不是某一门具体技术。 这个 Topic 用来回答“仓库怎样防止低质量或不完整的改动穿过默认分支”。
React app
主题React app 标记 React 是主要用户界面、管理台、控制台或嵌入式操作面 runtime。这里关心的是 route、component tree、client state、表单流、dashboard 交互和前端构建后的真实运行边界,而不是“项目依赖里有 React”。 这个 Topic 用来回答“用户实际操作的是不是一个 React runtime,以及它在系统里承担什么职责”。
Release failure notification
主题Release failure notification 指一个仓库为所有“预期成功但最终以 failure 结束”的交付 workflow 建立显式、可审查的告警路径。范围包括 release、deploy、CI、Docs Pages 和 required gate,但必须由 checked-in allowlist 声明;成功、skipped、cancelled 和通知 workflow 自身不属于通知条件。
Rust source quality
主题Rust source quality 指把 Rust 源码的可读性、结构边界和 lint 可执行性写成可重复运行的 contract。它至少区分格式化、语义 lint、源码结构检查和 target/features coverage,并把每一层绑定到仓库内可运行的命令、配置或 checker,而不是把“能编译”当成质量结论(projects/flux-purr.md、data/topics/rust-source-quality.
shadcn/ui
主题shadcn/ui 表示项目采用官方 shadcn/ui 风格的 checked-in component layer:components.json、@/components/ui aliases、Radix primitives、Tailwind utilities、class-variance-authority、tailwind-merge、clsx 和 Lucide icons 共同构成组件约定。
Storybook accessibility
主题Storybook accessibility 表示 Storybook 不只是组件展示,还明确引入 a11y audit 能力,通常是 @storybook/addon-a11y 或等价的 browser-backed Axe sweep。它关注 story-level 可访问性信号,例如对比度、ARIA 基础错误、表单语义和交互状态,而不是泛化的 Storybook 文档能力。
Storybook component QA
主题Storybook component QA 表示仓库把 Storybook 当作组件级文档、状态枚举、视觉检查或 interaction smoke 的稳定入口。它不等同于 Storybook accessibility:只有项目明确引入 a11y addon 或等价 Axe sweep 时,才同时打 accessibility Topic。这个拆分用于避免“只要有 Storybook 就叫 a11y”的误判。
TypeScript web
主题TypeScript web 表示项目把 TypeScript 作为一个或多个 Web surface 的主语言,并围绕它建立 workspace scripts、typecheck、bundler、lint/format、env contract 和前端构建门禁。这里的主语不是“仓库里出现了 .ts 文件”,而是 TypeScript 已经决定了维护者怎样启动、构建、校验和交付实际 Web surface。
UI version display
主题UI version display 指产品有意识地把“当前运行的到底是哪一版”暴露给用户或操作者查看,而不是把版本号藏在构建日志或开发者工具里。它通常包含一个稳定的人类可读显示位点,以及一条由运行时或构建链提供的版本真相路径,用于支持排障、远程协作和发布确认(projects/codex-vibe-monitor.md、projects/dockrev.
Worktree bootstrap
主题Worktree bootstrap 表示仓库把 linked worktree 的“首次进入可开发状态”当成正式 contract 来维护,而不是依赖维护者记忆、散落且无统一入口的手工 checklist,或假定只有主工作区才值得被照顾。