diff --git a/.agents/skills/unidesk-sub2api/SKILL.md b/.agents/skills/unidesk-sub2api/SKILL.md index 416b338d..49d5c000 100644 --- a/.agents/skills/unidesk-sub2api/SKILL.md +++ b/.agents/skills/unidesk-sub2api/SKILL.md @@ -23,6 +23,7 @@ bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-report - 仓库长期开发边界见 `docs/reference/platform-infra.md`,本 skill 承担日常操作手册。 - 配置真相是 YAML:`config/platform-infra/sub2api.yaml` 和 `config/platform-infra/sub2api-codex-pool.yaml`。 +- 业务策略和具体数值只以 YAML 为准。已有字段的数值调整只改 YAML 并跑 `plan` / `sync --confirm` / `validate`;不要自动补代码硬编码、schema 硬范围、合同测试、单元测试或长期参考文档。配置校验只校验格式、类型、必填和可渲染性,不判断数值策略是否“合理”。 - 本 skill 目录下若存在 `agents/*.yaml`,只作为 skill/agent 展示与调用元数据,不是 Sub2API 或 Codex pool 运行配置;不要在 skill 目录维护第二份账号、capacity、priority、endpoint 或 Secret 配置。 - Runtime 在 `G14:k3s` 的 `platform-infra` namespace;master server 只是控制端和消费者,不部署 Sub2API/PostgreSQL/Redis。 - Secret、`~/.codex/config.toml*`、`~/.codex/auth.json*` 是运行时输入或本地状态,不提交。 @@ -74,6 +75,7 @@ bun scripts/cli.ts platform-infra sub2api codex-pool cleanup-probes --confirm - `pool.minOwnerBalanceUsd`: pool key owner 最低余额,sync/validate 会补齐。 - `pool.minOwnerConcurrency`: 可选统一消费 API key owner 最低并发;省略时 CLI 自动使用所有已解析账号 capacity 的总和,sync/validate 会补齐。显式 YAML 值只作为 override,仍必须不小于账号 capacity 总和;未显式写 `profiles.entries[].capacity` 的账号会使用 `pool.defaultAccountCapacity` 参与求和,不要用提高某个 provider capacity 来掩盖用户并发层 WS 1013。 - `pool.defaultTempUnschedulable`: 默认账号级临时下线规则;只声明 Sub2API 已支持的错误路径能力,用于在上游返回容量、限流、overload、service unavailable、gateway timeout、稳定模型路由错误或认证状态异常时,让 Sub2API 冷却该账号并切换到同组其他账号。不要用 YAML、UniDesk CLI、k8s 热补或本地 fork 魔改 Sub2API 不支持的行为。 +- `pool.defaultTempUnschedulable` 的 `durationMinutes` 等业务数值只从 YAML 读取并同步到 Sub2API;不要在 TypeScript 默认值、schema、合同测试或文档 prose 中另写一份上限、下限或分层策略。 - 自动冻结/切号失败时,必须修复 `temp_unschedulable` 与 failover 机制本身,并用运行时证据证明失败账号被临时冻结且请求切到其他可调度账号;禁止通过手动禁用账号、删除账号、移除 YAML entry、降低 membership 或临时改调度策略来替代自动恢复。只有明确的上游退役或所有权变更才走删除/禁用上游流程。 - YAML 只选择和配置 Codex 上游,不声明 `schedulable` 长期字段;`schedulable=true` 只能作为 `codex-pool sync --confirm` 的过程控制基线恢复。自动冻结必须表现为 `temp_unschedulable_until` / `temp_unschedulable_reason`,避免把永久不可调度误当成自动冻结。 - `profiles.entries`: 从 master `~/.codex/` 选择上游 profile 并映射到 Sub2API account。 @@ -190,7 +192,7 @@ bun scripts/cli.ts platform-infra sub2api codex-pool configure-local --confirm - `codex-pool sync --confirm` 或 `codex-pool validate` 超时:先区分 CLI 传输超时和 Sub2API 运行失败。受控 CLI 应返回远端作业进度和 stdout/stderr tail;如果只是低层 `trans` 60s 超时,不能据此判定 Sub2API failover 不工作。改用或修复 CLI 的远端 job/poll 路径后重跑,并以最终结构化结果作为证据。 - Codex 报 weekly-limit、`less than 10% of your weekly limit left`、`Run /status for a breakdown` 等账号状态/软配额提示并要求切号:如果上游以 403/429 等错误状态返回,把稳定 body 关键词放进 `pool.defaultTempUnschedulable` 的对应规则,跑 `codex-pool sync --confirm`,再用 `codex-pool validate` 确认每个 managed account 的 runtime 规则包含这些关键词。若该文案是 HTTP 200 成功内容,不要写 Sub2API 原生 YAML 200 规则、不要热补 Sub2API、不要绕过 sync;启用账号级哨兵时由 marker-only 哨兵按非 marker 响应统一指数冻结。 - 上游 400/503 响应体出现 `invalid_encrypted_content`、`bad_response_status_code`、`invalid_request_error` + 稳定 unsupported-model 文案、unsupported-model、`暂不支持` / `可用模型`、`model_not_found`、`No available channel for model ...` 或同类稳定模型路由 / Responses encrypted-content 兼容性失败:把稳定 body 关键词放进 `pool.defaultTempUnschedulable` 的对应 400/503 规则,跑 `codex-pool sync --confirm`,再用 `codex-pool validate` 确认目标 account 的 runtime rule 包含这些关键词;不要用 account membership、priority、capacity、loadFactor、WebSocket mode 或 User-Agent 改动掩盖该错误族。 -- 上游错误反复触发:默认错误冷却按严重程度分层;临时问题可从 10 分钟起步,网关/服务不可用/过载/模型路由类应更长,认证/权限/配额/账号状态/账号兼容类使用最长冷却。`invalid_encrypted_content`、unsupported-model、`Recovered upstream error ...`、`Bad Gateway`、`Gateway Timeout`、Cloudflare `524`、Codex-facing `Upstream request failed`、`Unknown error`、`context deadline exceeded`、`context canceled`、`model_not_found`、`No available channel for model`、大上下文 `413` 和 `openai_error` 这类稳定包装文案都应留在对应 YAML 冷却政策里,特别是普通 `/responses` 与 compact 链路里上游兼容性错误或 524 可能最终表现为客户端 502/504 + `Unknown error`。具体数值只以 YAML 为准,修改后必须 `codex-pool sync --confirm` 和 `codex-pool validate`。长期判定见 `docs/reference/platform-infra.md`。 +- 上游错误反复触发:`invalid_encrypted_content`、unsupported-model、`Recovered upstream error ...`、`Bad Gateway`、`Gateway Timeout`、Cloudflare `524`、Codex-facing `Upstream request failed`、`Unknown error`、`context deadline exceeded`、`context canceled`、`model_not_found`、`No available channel for model`、大上下文 `413` 和 `openai_error` 这类稳定包装文案都应留在对应 YAML 冷却政策里,特别是普通 `/responses` 与 compact 链路里上游兼容性错误或 524 可能最终表现为客户端 502/504 + `Unknown error`。冷却时长等具体数值只以 YAML 为准,修改后只需要 `codex-pool plan`、`codex-pool sync --confirm` 和 `codex-pool validate`;不要为数值调整新增合同测试、代码硬范围或长期参考数值口径。长期判定见 `docs/reference/platform-infra.md`。 - Codex auto compact 后丢上下文:先确认 YAML `localCodex` 是否声明启用 WSv2;若启用,再确认本机 `~/.codex/config.toml` 是否有 `supports_websockets = true` 和 `responses_websockets_v2 = true`,并看 `codex-pool validate` 的 WSv2 candidate 和 Sub2API 日志里的 `transport=responses_websockets_v2`。若 YAML 当前禁用 WSv2,则按 HTTP Responses 稳定性排查,不把旧 WS 口径当成验收要求。 - Codex smoke 有 reconnect/1013:这是上游并发/可用性问题,和 HTTP-only compact context-loss 分开处理;记录 session/log 证据并关联专项 issue,不要用运行时手补覆盖 YAML 容量。 diff --git a/AGENTS.md b/AGENTS.md index a4ab474a..151ced6b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,12 +5,13 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 ## P0 最高优先级:自有配置 YAML 优先规则 - P0: UniDesk 自有配置一律优先使用 YAML(`.yaml`/`.yml`),包括 `config/` 下的运行面、平台基础设施、节点/lane、部署参数和可调版本配置;除非外部工具硬性要求 JSON/TOML/ENV 等格式,禁止新增 JSON 作为 UniDesk 自有配置真相。 -- P0: 需要代码读取的 YAML 配置必须显式校验 schema、字段类型和必填项;禁止静默 fallback、宽松猜测或把配置藏进脚本常量,后续版本、镜像、namespace、endpoint 等可调项必须从 YAML 配置进入受控 CLI。 +- P0: 需要代码读取的 YAML 配置必须显式校验格式、字段类型和必填项;配置校验只保证“能被正确读取和渲染”,不得把业务策略、调度策略或数值选择写成代码硬编码、schema 硬范围、合同测试或隐藏默认值。后续版本、镜像、namespace、endpoint、容量、冷却时间、退避窗口等可调项必须从 YAML 配置进入受控 CLI,具体数值以 YAML 为准。 ## P0 最高优先级:G14 platform-infra 规则 - P0: `platform-infra` 是 G14 k3s 上 UniDesk 运维的平台基础设施 namespace;Sub2API、Codex pool、FRP 暴露、统一消费 API key 和后续平台基础设施迁移的长期边界、路由与探针口径统一见 `docs/reference/platform-infra.md`,Sub2API 日常操作统一见 `$unidesk-sub2api`(`.agents/skills/unidesk-sub2api/SKILL.md`)。 - P0: Codex pool 账号容量与调度候选必须从 `config/platform-infra/sub2api-codex-pool.yaml` 进入受控 CLI;当前数值以 YAML 为准,禁止用代码常量、Secret、运行时手补或长期参考文档里的硬编码数值覆盖 YAML。 +- P0: Codex pool 的业务策略和数值只做 YAML 配置与运行面同步验证;除非用户明确要求实现新能力,修改既有 YAML 数值不得自动扩展为代码 schema、合同测试、单元测试或长期参考文档变更。 - P0: `devops-infra` 仅作为既有控制面基础设施逐步迁移来源,不再作为新增平台服务的默认 namespace;新增/迁移必须优先落到 `platform-infra`,并通过 `config/platform-infra/*.yaml` 与 `bun scripts/cli.ts platform-infra ...` 受控。 ## P0 最高优先级:CaseRun 无服务与单步调试规则 @@ -37,6 +38,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - P0: 用户最新明确要求优先于旧测试、旧门禁、旧预检、旧断言、旧 guard 和旧 gate;开发过程中遇到任何阻碍最新目标的旧测试、旧门禁、旧预检或旧断言,一律拆除,禁止继续维护、修补、叠例外或用兼容路径绕行。 - P0: 短连接 CLI、临时工具、文档和轻量 helper 不套用常驻服务、镜像、Job、GitOps、PR、CI/CD 或重型发布流程的旧门禁;如果旧流程要求与最新架构定位冲突,以最新架构定位为准并删除旧流程入口。 - P0: 任何测试、预检或自检只允许表达当前最新目标行为;旧历史断言不得作为回归保护保留,避免把旧路线固化成长期摩擦。 +- P0: 不做合同测试。验证只保留两类:高频热点或明确曾修复 bug 回归风险时补最小单元测试;以及通过原入口/端到端 CLI 交互测试验证真实运行面。配置数值调整通常只跑对应 plan/sync/validate。 ## Critical Long-Term Reference Docs Rule @@ -65,6 +67,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - P0: 当用户明确给出最新验收要求或纠偏原则时,旧断言、旧门禁和旧兼容路径一律拆除;测试只按最新要求表达目标行为,不保留与最新目标无关或相冲突的历史断言。 - P0: 不做兼容迁移,不做分支/开关,不用 feature flag、legacy mode 或双路径长期并存来绕开最新要求;实现、测试和文档必须直接收敛到最新目标状态。 +- P0: 合同测试不是允许的测试形态;验证只使用最小单元测试或端到端 CLI 交互测试。历史上命名含 `contract` 的命令不得作为默认验证入口,业务策略和配置数值不得通过测试硬编码成额外门禁。 ## Critical Remote Patch Transport Rule @@ -82,7 +85,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 ## Critical HWLAB Issue Closure CLI Validation Rule -- P0: HWLAB/G14/v0.2 的用户反馈、CLI、Cloud Web、AgentRun、device-pod、公开 API 或运行面工作流 issue,关闭前必须完成用户入口或原入口的真实验证;仅有 targeted test、unit/contract test、构建检查、PR 合并或源码层证据不得关闭 issue。 +- P0: HWLAB/G14/v0.2 的用户反馈、CLI、Cloud Web、AgentRun、device-pod、公开 API 或运行面工作流 issue,关闭前必须完成用户入口或原入口的真实验证;仅有 targeted test、unit test、构建检查、PR 合并或源码层证据不得关闭 issue。 - P0: CLI 相关 issue 未完成目标 runtime 上的真实 CLI 验证时必须保持打开或重新打开;关闭评论必须写明实际 CLI/入口命令、目标 lane/URL/namespace、trace/session/thread/PipelineRun 等证据和结果,细则见 `docs/reference/g14.md`。 ## Critical CI/CD CLI Control Rule @@ -136,7 +139,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 ## Critical D601 UniDesk Workspace Rule -- P0: `D601:UniDesk` 的固定开发 workspace 是 D601 节点上的 `/home/ubuntu/workspace/unidesk-dev`,固定使用 `master` 分支和 `origin git@github.com:pikasTech/unidesk.git`;所有需要在 D601 上改 UniDesk 代码、跑轻量合同测试、做分布式敏捷实验补丁收敛或验证 Code Queue runner/trans/tran 的工作,都必须优先使用这个目录。 +- P0: `D601:UniDesk` 的固定开发 workspace 是 D601 节点上的 `/home/ubuntu/workspace/unidesk-dev`,固定使用 `master` 分支和 `origin git@github.com:pikasTech/unidesk.git`;所有需要在 D601 上改 UniDesk 代码、跑轻量单元测试、做分布式敏捷实验补丁收敛或验证 Code Queue runner/trans/tran 的工作,都必须优先使用这个目录。 - P0: 每次开始 `D601:UniDesk` 分布式开发、切换任务、恢复中断或上下文压缩后,必须重新读取目标 workspace 的 `/home/ubuntu/workspace/unidesk-dev/AGENTS.md`,并以该文件和其引用的 UniDesk repo 内规则为当前任务约束;禁止只凭压缩摘要或主 server 记忆继续改代码。 - P0: UniDesk CLI/trans/tran/SSH 透传客户端工具链改进可以直接在 master server `/root/unidesk` 做轻量源码修改、提交和推送;这不允许在 master server 运行仓库级 check、browser smoke、镜像构建或编译,细则见 `docs/reference/dev-environment.md`。 - `/home/ubuntu/cq-deploy`、`/root/unidesk`、`/app`、Code Queue pod 内 `/root/unidesk` 和 `/tmp/unidesk-*` 都是运行副本、部署副本或一次性实验面,不是 `D601:UniDesk` 日常开发 source truth;运行面热修可以直接作用于 pod/容器,但必须随后把持久化修复落回 fixed workspace 和 Git remote。 diff --git a/docs/reference/platform-infra.md b/docs/reference/platform-infra.md index 2f8c7264..2e94b60d 100644 --- a/docs/reference/platform-infra.md +++ b/docs/reference/platform-infra.md @@ -51,7 +51,7 @@ When Codex startup repeatedly reports WebSocket reconnects or HTTPS fallback, pr Do not encode current availability assumptions in long-term reference prose. If an account needs a higher concurrency or load factor than the pool default, make that a deliberate YAML override and verify it with `codex-pool validate`; the reference document should describe the rule, not repeat the current numeric value. -Do not enable Sub2API `pool_mode` for UniDesk-managed Codex accounts. `pool_mode` retries the same selected account path, while UniDesk's desired failover behavior is to mark the failing account temporarily unschedulable and let Sub2API choose another account from the group. `codex-pool validate` reports each managed account's temporary-unschedulable runtime alignment and should be used after `codex-pool sync --confirm`. Generic 502/503/504 bodies such as `Recovered upstream error 502`, `Bad Gateway`, `Gateway Timeout`, Codex-facing `Upstream request failed`, `Unknown error`, context-deadline/canceled wrappers, stable 400 `invalid_encrypted_content` / unsupported-model wrappers, and stable `model_not_found` / "no available channel for model" wrappers must stay in the YAML cooldown policy so an intermittently bad account is cooled down instead of repeatedly adding latency at the next compact or Responses request. The Codex pool default error cooldown is severity-tiered: temporary signals should use the shortest cooldown, gateway/service/overload/model-routing failures should cool down longer, and credential, permission, quota, account-compatibility, or account-state failures should use the longest cooldown. Exact current values belong in YAML and runtime validation output. +Do not enable Sub2API `pool_mode` for UniDesk-managed Codex accounts. `pool_mode` retries the same selected account path, while UniDesk's desired failover behavior is to mark the failing account temporarily unschedulable and let Sub2API choose another account from the group. `codex-pool validate` reports each managed account's temporary-unschedulable runtime alignment and should be used after `codex-pool sync --confirm`. Generic 502/503/504 bodies such as `Recovered upstream error 502`, `Bad Gateway`, `Gateway Timeout`, Codex-facing `Upstream request failed`, `Unknown error`, context-deadline/canceled wrappers, stable 400 `invalid_encrypted_content` / unsupported-model wrappers, and stable `model_not_found` / "no available channel for model" wrappers must stay in the YAML cooldown policy so an intermittently bad account is cooled down instead of repeatedly adding latency at the next compact or Responses request. Exact current cooldown values and any business-policy grouping belong only in YAML and runtime validation output; do not repeat those values here, encode them as code/schema hard limits, or require contract tests for value changes. Sub2API temporary-unschedulable rules require both an HTTP status match and a response-body keyword match in the upstream failure/error path. Do not treat them as a general successful-response content filter, and do not add a YAML 200 cooldown rule, patch Sub2API in place, fork Sub2API behavior in UniDesk, or bypass `codex-pool sync` to make the native pool pretend that HTTP 200 content cooling exists. HTTP 200 private content, maintenance text, quota prompts, ads, and similar semantic failures are handled by the external account-level sentinel when that sentinel is enabled, not by Sub2API native `temp_unschedulable_rules`.