* ci: move nix and docker off the merge validation path
Core ci.yml / Validate workspace / merge_group no longer schedule or require
Nix flake check or Docker image builds. Packaging lives on two standalone
workflows: nix.yml (flake check) and docker-image.yml (PR smoke build +
tag/release publish). Update scopes, topology tests, and agent docs.
* fix(ci): detect Docker publish from release inputs, not workflow_call event
Reusable workflow callers keep their own github.event_name (usually
workflow_dispatch), so matching event_name == workflow_call never fires and
stable GHCR publish would silently smoke-build only. Gate publish on tag push
or non-empty release_version / publish_latest inputs instead.
* fix(ci): keep smoke-only Docker sha tags off the publish path
Gate pr-/manual-sha metadata tags on publish != true so release-stable
workflow_dispatch callers do not push extra manual-sha-* tags to GHCR.
* Consolidate PR validation into ci
* Tune absorbed CI runner tiers
* Fold visual validation into CI Playwright shards
* Run PR shards during manual CI dispatch
Plan K4 / spec §15.5 / spec §16 Phase 5.
.github/workflows/docker-image.yml builds and pushes
ghcr.io/<owner>/od on three triggers:
- push to main → :edge + :sha-<short> + :main-<UTC>
- tag vX.Y.Z → :X.Y.Z + :latest + :sha-<short>
- pull request → smoke build only (no push)
- workflow_dispatch → manual trigger
Multi-arch via QEMU + Buildx (linux/amd64 + linux/arm64).
Authenticates against GHCR via GITHUB_TOKEN with packages:write.
Uses GitHub Actions cache (type=gha) to keep rebuilds fast.
The build-args override to node:24-bookworm-slim that spec §15.1
nominates is intentionally NOT applied yet — the in-tree
deploy/Dockerfile uses alpine + apk for build tooling, and switching
the base needs the apk lines re-cast as apt-get. That's a follow-up;
the canonical alpine image is functionally equivalent for v1.
Co-authored-by: Tom Huang <1043269994@qq.com>