From 7cd5b2533764c4b6c50114d64163090210fed364 Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 19 May 2026 03:18:28 +0000 Subject: [PATCH] docs: record release governance decision --- AGENTS.md | 2 + docs/reference/arch.md | 6 ++ docs/reference/artifact-registry.md | 2 + docs/reference/ci.md | 10 +++- docs/reference/cli.md | 2 + docs/reference/deploy.md | 6 +- docs/reference/deployment.md | 2 + docs/reference/dev-ci-runner.md | 4 +- docs/reference/dev-environment.md | 4 +- docs/reference/devops-hygiene.md | 4 +- docs/reference/release-governance.md | 86 ++++++++++++++++++++++++++++ 11 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 docs/reference/release-governance.md diff --git a/AGENTS.md b/AGENTS.md index 84c8f6b1..c32cd88f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,6 +8,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - 任何开发、文档或部署配置变更开始前,必须先在当前 worktree 执行 `git status` 并从主线拉取最新源码:`git pull --ff-only origin master`;若本地并行变更或远端推进导致不能快进,必须当即分清来源并解决冲突后再继续。 - 任何需要保留的代码、文档或配置变更,在完成必要自测/部署验证后必须立刻按 `git-spec` 提交并 push 到 remote;禁止让未推送的本地修改成为部署真相或后续任务依赖。 - 提交前必须用 `git status` 和 `git diff` 区分并只提交当前任务相关文件,保留并避开并行任务产生的无关修改;所有 UniDesk agent 变更只允许在 `master` 上开发并 `git push origin master`,禁止新建、切换到或推送其他分支;长期规则见 `docs/reference/arch.md`。 +- `release/v1` 是规划中的稳定维护线,不是普通 feature/fix 分支;创建、更新或启用必须作为显式 release operation,先满足 `docs/reference/release-governance.md` 和 GitHub issue #6 的 CLI/CI/CD/文档条件。当前常规 agent 任务仍按 master-only 规则执行。 ## Critical Provider Gateway Upgrade Rule @@ -75,6 +76,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - `docs/reference/pipeline-model-proxy.md`:Pipeline v2 model proxy 链路架构、D601 宿主 proxy 服务部署、harness token 注入规则和 smoke test 验证流程。 - `docs/reference/deploy.md`:`deploy.json` desired-state、target-side build、一次性构建 proxy、直管/代管服务部署 executor 和 live commit 验证规则。 - `docs/reference/devops-hygiene.md`:Git-backed deployment truth、dirty worktree/manual repair 边界、受限手动操作和 CI 私有仓库 source-auth 规则。 +- `docs/reference/release-governance.md`:`release/v1` 稳定维护线、`master` 集成线、CI/CD server 版本固定、master CLI 兼容和 feature flag 治理规则;决策记录见 GitHub issue #6。 - `docs/reference/artifact-registry.md`:D601 host-managed CNCF Distribution registry、loopback-only 边界和 backend-core artifact CD 目标流程。 - `docs/reference/dev-environment.md`:D601 `unidesk-dev` persistent dev 环境、18083 dev frontend proxy、`deploy apply --env dev` 服务范围和 Rust backend-core 只在 D601 编译的边界。 - `docs/reference/ci.md`:D601 k3s Tekton CI、只读主数据库性能门禁和 CLI 入口规则。 diff --git a/docs/reference/arch.md b/docs/reference/arch.md index 0bba4a8a..b7a655fb 100644 --- a/docs/reference/arch.md +++ b/docs/reference/arch.md @@ -89,6 +89,12 @@ - All UniDesk agent changes must be developed on `master` and pushed to `origin master`. Agents must not create, switch to, or push feature/fix branches for UniDesk work. - Live deployment should run from a known commit or from a change set that is immediately committed and pushed; local-only hotfixes must not become the implicit dependency for later tasks. - Secrets, tokens, generated runtime state, and node-local env files stay outside Git, but their required contract, storage location, and recovery path must be documented so pushing source changes is not blocked by runtime-only data. + - Release And CI/CD Governance + - Release-line governance is owned by `docs/reference/release-governance.md` and [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6). + - `master` remains the integration branch for normal agent work and high-risk architecture development. A future `release/v1` line is an explicit stable maintenance/runtime line, not a general-purpose feature or fix branch. + - Production and stable-dev runtime must be commit-pinned through `deploy.json` and verified with runtime metadata. They must not float with the latest `master`, a local worktree, copied files, or copied images. + - CI/CD server and control-plane services follow the same commit-pinned runtime rule. A CLI built from `master` is allowed only when it remains compatible with the pinned server and obeys server-reported capabilities. + - Feature flags are short-lived risk controls. Long-lived architecture divergence must be expressed with release lines, service boundaries, or deployment boundaries instead of permanent in-process flag paths. - Critical Task Deployment Principles - Single-point components such as the database, core scheduler logic, and API gateway are deployed on the main server - The high-availability environment of the main server ensures the critical scheduling path never breaks diff --git a/docs/reference/artifact-registry.md b/docs/reference/artifact-registry.md index d474c88f..2e80b479 100644 --- a/docs/reference/artifact-registry.md +++ b/docs/reference/artifact-registry.md @@ -4,6 +4,8 @@ D601 artifact registry 是为 backend-core 轻量 CD 准备的本地镜像制品 backend-core 的长期分工是:CI 在 D601 构建并发布 commit-pinned 镜像,CD 在 master server 只拉取、替换和验证该镜像。registry 是这条链路的本地制品缓存,不是构建编排器,也不是生产部署控制面。 +Production CI/CD runtime pinning and release-line boundaries follow `docs/reference/release-governance.md` and [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6). The registry may cache commit-pinned artifacts, but it must not become a floating replacement for `deploy.json`, `release/v1`, or `master` source history. + ## Architecture registry 运行在 D601 host/WSL OS 上,由 systemd 管理 Docker Compose 项目: diff --git a/docs/reference/ci.md b/docs/reference/ci.md index 5b5d5027..a8df829b 100644 --- a/docs/reference/ci.md +++ b/docs/reference/ci.md @@ -1,6 +1,6 @@ # UniDesk CI On D601 k3s -UniDesk CI is hosted on the D601 native k3s cluster with Tekton Pipelines and Tekton Triggers. It is CI only. CD remains separate from Tekton. No Tekton task may roll out production services. +UniDesk CI is hosted on the D601 native k3s cluster with Tekton Pipelines and Tekton Triggers. It is CI only. CD remains separate from Tekton. No Tekton task may roll out production services. CI/CD runtime-version governance follows `docs/reference/release-governance.md` and [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6). ## Components @@ -31,6 +31,14 @@ Git clone and dependency downloads inside the repo check task use `d601-provider Private repository source authentication is part of the CI contract and follows `docs/reference/devops-hygiene.md`. If the repo-check task fails at `git clone` because credentials are unavailable, treat it as a CI infrastructure/auth gap, not as an application test result. +## CI/CD Runtime Governance + +CI/CD server and control-plane runtime is production-like infrastructure. Its service version must be pinned by `deploy.json` and verified through runtime commit metadata; it must not float with the latest `master` just because the operator's CLI is newer. + +The CLI may be run from `master` if it remains backward compatible with the pinned server version. When the CLI needs a newer server capability, it must detect that through a health or capability response and fail explicitly. It must not replace the missing server capability with raw SSH, direct `kubectl`, direct SQL, direct production namespace mutation, or another hidden deployment path. + +CI/CD services should report their source commit, API/schema capability, supported environments and supported operations. CI diagnostics should include that information when rejecting an operation as unsupported. + Steps that call the Kubernetes API directly clear inherited proxy variables so service-account HTTPS calls to `kubernetes.default.svc` do not accidentally use the Code Queue image's Docker Compose proxy defaults. The rollout poll reads the Deployment main resource rather than the `/status` subresource, keeping CI RBAC limited to the same app/service resources it creates and deletes. The performance probe scans recent Code Queue tasks until it finds one with trace steps, so a newly selected task without persisted step detail does not make the whole gate fail before measuring the trace endpoints. diff --git a/docs/reference/cli.md b/docs/reference/cli.md index fed92b29..29c503ae 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -2,6 +2,8 @@ UniDesk 的统一 CLI 入口是根目录 `scripts/cli.ts`,运行方式固定为 `bun scripts/cli.ts `。CLI 默认输出 JSON,所有成功和失败路径都必须向 stdout 写出结构化对象,避免无输出造成状态不可观测。 +CLI 可以从 `master` 快速演进,但必须兼容 `deploy.json` 固定的 CI/CD server 和生产运行面。CLI/server 能力协商、unsupported-version 失败语义和 release-line 边界由 `docs/reference/release-governance.md` 与 [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6) 约束。 + ## Command Model - `help` 输出命令索引,适合作为交互式入口。 diff --git a/docs/reference/deploy.md b/docs/reference/deploy.md index cc4c6603..7b4f7628 100644 --- a/docs/reference/deploy.md +++ b/docs/reference/deploy.md @@ -2,7 +2,7 @@ UniDesk deployment is driven by a desired-state manifest. The manifest answers only one question: which service should run which repository commit. Runtime topology, ports, providers, compose files, Kubernetes manifests, health paths and proxy policy remain in `config.json` and the existing service manifests. -Persistent D601 dev environment rules, including the public dev frontend port, `deploy apply --env dev` service scope and Rust backend-core build boundary, are owned by `docs/reference/dev-environment.md`. This document owns the generic desired-state reconciler and target-side build contract. +Persistent D601 dev environment rules, including the public dev frontend port, `deploy apply --env dev` service scope and Rust backend-core build boundary, are owned by `docs/reference/dev-environment.md`. Release-line governance, CI/CD runtime pinning and the `release/v1` transition policy are owned by `docs/reference/release-governance.md` and [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6). This document owns the generic desired-state reconciler and target-side build contract. ## Manifest @@ -42,6 +42,10 @@ The optional non-service execution declaration under `environments.dev` is inten Environment mode never reads the local dirty working tree manifest. `deploy check --env ...`, `deploy plan --env ...` and `deploy apply --env ...` fetch `origin/master`, read `origin/master:deploy.json`, select `environments.`, and report the manifest commit/blob, service commit IDs, target namespace, database fingerprint and Provider identity. `deploy apply --env dev` is currently enabled only for persistent D601 dev `backend-core` and `frontend`; all other D601 services remain rejected before runtime mutation. `deploy apply --env prod` remains disabled until the production environment executor and authorization policy are explicitly added. Production backend-core artifact CD is a separate executor because its build target is D601 CI while its runtime target is the master server. +The current implementation has not yet enabled separate stable and integration dev lanes. Future lane names such as `dev-v1` and `dev-master`, or an equivalent nested schema, must be added as explicit `deploy.json` and CLI semantics before use. A deploy command must print the manifest ref it used and must not infer `release/v1` from a local branch, a dirty file, or an undocumented environment alias. + +CI/CD server and control-plane services are normal deployable services for versioning purposes: production runtime must be pinned by `deploy.json` to a known commit. A CLI built from `master` may orchestrate the pinned server only through backward-compatible APIs and server-reported capabilities; it must not bypass server-side deploy policy when the pinned server does not support a requested operation. + The only D601 direct-service exception in local manifest mode is `k3sctl-adapter`, because it is the UniDesk-managed control bridge outside the k3s fault domain and owns the Kubernetes service catalog used by the dev public frontend path. Updating it must still use the normal target-side deploy reconciler from a pushed commit. D601 Code Queue, Decision Center, MDTODO, ClaudeQQ and future k3s-managed workloads remain blocked from maintenance-channel direct deploy. `config.json.microservices[].repository.commitId` is retained for catalog compatibility, but `deploy.json` is the deployment version authority for the reconciler. diff --git a/docs/reference/deployment.md b/docs/reference/deployment.md index 60765b0b..dc9993ad 100644 --- a/docs/reference/deployment.md +++ b/docs/reference/deployment.md @@ -2,6 +2,8 @@ 主 server 使用根目录 `docker-compose.yml` 统一编排 database、backend-core、frontend、dev-frontend-proxy、provider-gateway 以及必须留在主 server 的用户服务。当前环境本身就是主 server,因此 provider-gateway 也在同一台机器上启动,用与普通计算节点相同的 WebSocket 方式接入 core。Code Queue 按“master 低资源低抖动控制面、D601 高资源高抖动执行面”拆分:队列 CRUD、任务提交、历史摘要和轻量 Trace 读取由主 server Compose 中的 `code-queue-mgr` 直管 PostgreSQL;Codex/OpenCode scheduler、runner、dev-container、active run steer/interrupt 和执行态写回仍由 D601 原生 k3s/k8s Code Queue 执行面承担。 +Production runtime and CI/CD control-plane versioning follow `docs/reference/release-governance.md` and [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6): server-side runtime is commit-pinned through `deploy.json`, while a newer `master` CLI may operate it only through compatible APIs and server-reported capabilities. + ## Services - `database` 使用 `postgres:16-alpine`,数据保存到 named volume `unidesk_pgdata_10gb`,当前容量预算为 15 GB,初始化 SQL 位于 `src/components/database/init/`。 diff --git a/docs/reference/dev-ci-runner.md b/docs/reference/dev-ci-runner.md index 5c6cb2e4..7cb89939 100644 --- a/docs/reference/dev-ci-runner.md +++ b/docs/reference/dev-ci-runner.md @@ -4,7 +4,7 @@ ## Knowledge Ownership -This document is the authoritative source for the `ci run-dev-e2e` architecture, manifest contract, short launcher payload, host-vs-Tekton fetch boundary, result directory and no-CD safety rules. `AGENTS.md`, `docs/reference/ci.md`, `docs/reference/cli.md`, `docs/reference/deploy.md` and `docs/reference/codex-deploy.md` may mention the command only as an index entry or one-line cross-reference. If a future change would require editing the same runner rule in multiple documents, update this file as the single source and replace other copies with links here. +This document is the authoritative source for the `ci run-dev-e2e` architecture, manifest contract, short launcher payload, host-vs-Tekton fetch boundary, result directory and no-CD safety rules. Release-line and dev-lane governance is owned by `docs/reference/release-governance.md` and [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6). `AGENTS.md`, `docs/reference/ci.md`, `docs/reference/cli.md`, `docs/reference/deploy.md` and `docs/reference/codex-deploy.md` may mention the command only as an index entry or one-line cross-reference. If a future change would require editing the same runner rule in multiple documents, update this file as the single source and replace other copies with links here. ## Goal @@ -17,6 +17,8 @@ The runner exists to prove the dev desired state without interrupting production - CI only: the flow may create CI-owned temporary resources, but it must not deploy backend-core, frontend, Code Queue, Decision Center, k3sctl-adapter or any other direct/managed service. - Code Queue reproducibility: the runner must use the `code-queue` commit from `environments.dev.services`, build or reuse a labeled image from that Git commit on D601, import it into native k3s containerd, and validate the HTTP API inside a temporary namespace. +Future stable and integration dev lanes such as `dev-v1` and `dev-master` must be explicit runner inputs before use. The current runner continues to validate `origin/master:deploy.json#environments.dev` and must not infer a release lane from local branch state or dirty manifests. + ## Design Boundary The first-principles requirement is to validate `origin/master:deploy.json#environments.dev` without interrupting production. Persistent DevOps services, run brokers, webhook listeners, generic remote command protocols and full CD are secondary abstractions and are out of scope for this phase unless this document is deliberately superseded. The only automatic execution path is: diff --git a/docs/reference/dev-environment.md b/docs/reference/dev-environment.md index b907fad6..1036f52f 100644 --- a/docs/reference/dev-environment.md +++ b/docs/reference/dev-environment.md @@ -1,6 +1,6 @@ # D601 Dev Environment -This document is the authoritative source for the persistent `unidesk-dev` environment, the public dev frontend port, `deploy apply --env dev`, and the Rust backend-core build boundary. If the same dev-environment rule would need edits in `AGENTS.md`, `docs/reference/cli.md`, `docs/reference/deploy.md`, `docs/reference/ci.md`, `docs/reference/deployment.md`, `docs/reference/e2e.md` or `TEST.md`, keep the detailed rule here and leave only a short cross-reference elsewhere. +This document is the authoritative source for the persistent `unidesk-dev` environment, the public dev frontend port, `deploy apply --env dev`, and the Rust backend-core build boundary. Release-line and dev-lane governance is owned by `docs/reference/release-governance.md` and [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6). If the same dev-environment rule would need edits in `AGENTS.md`, `docs/reference/cli.md`, `docs/reference/deploy.md`, `docs/reference/ci.md`, `docs/reference/deployment.md`, `docs/reference/e2e.md` or `TEST.md`, keep the detailed rule here and leave only a short cross-reference elsewhere. ## Goal @@ -32,6 +32,8 @@ The unrestricted public network entries are therefore production frontend, dev f `deploy.json` remains the only version intent file. Dev entries live under `environments.dev` and are read from `origin/master:deploy.json`, never from a dirty local file, when using `--env dev` or `ci run-dev-e2e`. +The target release-governance model is to split stable maintenance validation from high-risk master integration, for example with explicit lanes such as `dev-v1` and `dev-master`. That split is not active until `deploy.json`, deploy commands, CI, frontend labels and diagnostics support it explicitly. Until then, the documented `environments.dev` behavior remains the active contract and must not be emulated through local manifest edits or hidden branch conventions. + The persistent dev rollout currently supports only: - `backend-core` diff --git a/docs/reference/devops-hygiene.md b/docs/reference/devops-hygiene.md index 389884af..bdaee04e 100644 --- a/docs/reference/devops-hygiene.md +++ b/docs/reference/devops-hygiene.md @@ -1,6 +1,6 @@ # DevOps Hygiene -This document is the authoritative source for UniDesk deployment hygiene: Git-backed deployment truth, dirty-environment boundaries, bounded manual operations and CI source-auth rules. If the same hygiene rule would need edits in `docs/reference/dev-environment.md`, `docs/reference/deploy.md`, `docs/reference/ci.md`, `docs/reference/dev-ci-runner.md`, `docs/reference/deployment.md`, `AGENTS.md` or `TEST.md`, keep the detailed rule here and leave only a cross-reference elsewhere. +This document is the authoritative source for UniDesk deployment hygiene: Git-backed deployment truth, dirty-environment boundaries, bounded manual operations and CI source-auth rules. Release-line and CI/CD runtime-version governance is owned by `docs/reference/release-governance.md` and [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6). If the same hygiene rule would need edits in `docs/reference/dev-environment.md`, `docs/reference/deploy.md`, `docs/reference/ci.md`, `docs/reference/dev-ci-runner.md`, `docs/reference/deployment.md`, `AGENTS.md` or `TEST.md`, keep the detailed rule here and leave only a cross-reference elsewhere. ## Source Of Truth @@ -12,6 +12,8 @@ UniDesk deployment state is healthy only when all three layers point back to pus Local worktrees, D601 runtime files, copied scripts, copied images, ad-hoc Kubernetes objects and one-off curl results are never deployment truth. +When stable release lanes such as `release/v1` are enabled, the desired-state ref must be explicit in the command, job log and deploy output. Until that support exists, commands that are documented to read `origin/master:deploy.json` must keep doing so and must not silently switch to another branch or a dirty manifest. + ## Prohibited Deployment Truth The following practices are not acceptable as the long-term or hidden source of a working environment: diff --git a/docs/reference/release-governance.md b/docs/reference/release-governance.md new file mode 100644 index 00000000..4f59afc7 --- /dev/null +++ b/docs/reference/release-governance.md @@ -0,0 +1,86 @@ +# Release Governance + +This document owns UniDesk release-line, runtime-version, CI/CD control-plane and feature-flag governance. The decision record is [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6). + +## Decision Scope + +The governance decision covers four boundaries: + +- stable maintenance work for the current usable UniDesk architecture; +- high-risk integration work on `master`, including the Rust backend-core rewrite and next-generation infrastructure changes; +- CI/CD server runtime pinning versus CLI compatibility; +- short-lived feature flags versus long-lived release or service boundaries. + +This document records the target policy. It does not by itself create a `release/v1` branch, change `deploy.json` schema, or authorize production deployment. + +## Release Lines + +`master` remains the normal integration branch for UniDesk source changes. New architecture work, backend-core Rust migration, provider-gateway reshaping, Code Agent sandbox work, and other high-risk development can continue there, but `master` must not be treated as the implicit production or stable-dev runtime truth. + +`release/v1` is the planned stable maintenance line for the existing usable architecture. Its baseline should be the last known-good TypeScript backend-core version or an equivalent verified stable commit. After it is enabled, it may accept only: + +- bug fixes for existing behavior; +- high-availability, recoverability and observability fixes; +- CI/CD reliability fixes; +- security and compatibility fixes; +- narrowly scoped deployment fixes that preserve the existing architecture. + +`release/v1` must not carry new product features, large architecture changes, the default Rust backend-core switch, or speculative Code Agent sandbox behavior. Any exception requires an explicit issue and a deployment rollback plan. + +Until the release-line implementation is completed in CLI, CI, CD and documentation, the current repository rule still applies: UniDesk agent changes are developed on `master` and pushed to `origin master`. Creating or updating `release/v1` is an explicit release operation, not a replacement for arbitrary feature or fix branches. + +## Stabilization Mode + +UniDesk enters stabilization mode when core availability is threatened by control-plane, deployment, backend-core, provider-gateway, Code Queue, or CI/CD instability. During stabilization: + +- high availability, trace visibility, deploy reproducibility and rollback safety take priority over new features; +- production and stable dev should run only from commit-pinned desired state; +- live manual repairs are temporary and must be converted into pushed Git changes; +- high-risk architecture work may continue only on the integration lane and must not be promoted into stable runtime by default. + +Exit from stabilization requires CI/CD, deploy verification, Code Queue recoverability and dev/prod isolation to be demonstrably healthy. + +## CI/CD Runtime Versioning + +CI/CD server and control-plane services are production-like infrastructure. Their runtime version must be pinned by `deploy.json` to the production desired commit, not implicitly follow the operator's local worktree or the latest `master`. + +The CI/CD CLI may run from `master` because it is the command vocabulary and should evolve quickly. That compatibility is acceptable only when all of the following hold: + +- CLI changes are backward compatible with the pinned server version or fail with a clear unsupported-version error; +- server-side policy remains authoritative for deploy boundaries, allowed environments and dangerous operations; +- the CLI uses server capability data instead of guessing support from local code; +- an unsupported server capability must not be bypassed through raw SSH, direct `kubectl`, direct SQL, or hidden fallback commands. + +CI/CD services should expose their commit, API/schema capability, supported environments, supported services and supported operations through health or capability endpoints. The CLI must include the observed capability or server commit in diagnostics for failed operations. + +## Dev Environment Lanes + +The target model is to separate a stable maintenance dev lane from a master integration dev lane, for example with explicit names such as `dev-v1` and `dev-master` or an equivalent schema. The stable lane validates `release/v1` fixes without disrupting production. The master lane validates high-risk work and may be less stable. + +This split must be implemented explicitly in `deploy.json`, deploy planning, deploy apply, CI, frontend labels and diagnostics. Until that work is done, existing commands continue to read the currently documented manifest ref such as `origin/master:deploy.json#environments.dev`; operators must not simulate split lanes through dirty local manifests, hidden branches, or undocumented runtime edits. + +## Feature Flags + +Feature flags are short-lived risk controls, not a long-term architecture partitioning mechanism. Prefer release lines, service boundaries and deployment boundaries for durable divergence. + +Allowed feature flags: + +- release toggles with a named owner and removal condition; +- kill switches for availability protection; +- migration toggles that are observable in health output and removed after rollout; +- compatibility toggles needed for a bounded transition. + +Disallowed feature-flag patterns: + +- permanent flags with no owner or removal issue; +- nested flag combinations that create untested behavior matrices; +- flags that hide a second data, control, event, or deployment path; +- flags that let production bypass the documented desired-state or server-side deploy policy. + +Every feature flag must have a default, an owner, an observability signal, a removal condition and tests for both active states when both states can run in production. + +## Promotion And Backport Rules + +Stable-line fixes must remain traceable. A fix may land first on `master` and then be cherry-picked to `release/v1`, or land on `release/v1` and be forward-ported to `master`, but the chosen direction must be recorded in the related issue or pull request. + +Deployment truth remains commit-pinned. Neither `release/v1` nor `master` may be represented by mutable local runtime files, dirty worktrees, copied source trees, copied images, or manual hotfixes that are not committed and pushed.