Skip to content

feat(steward): persist guided executor allocation - #4802

Merged
huangruiteng merged 3 commits into
mainfrom
codex/local-agent-allocation
Sep 20, 2026
Merged

huangruiteng merged 3 commits into
mainfrom
codex/local-agent-allocation

Conversation

@huangruiteng

@huangruiteng huangruiteng commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator

The steward's machine setting previously expressed only a preferred executor. A new manager Session could reinterpret that preference after configuration changes or restart, automatic fallback had no closed authorization boundary, and operators could not inspect why a route was selected.

This change delivers the guided allocation slice described by #4779:

  • upgrades steward_executor to a backward-compatible v1 contract with preferred, pinned, and flexible policies;
  • limits flexible fallback to an explicit eligible endpoint pool and observed availability, while pinned selection rejects a different explicit route;
  • keeps the shipped steward default on Codex and its default GPT model while preserving explicit owner intent and provider-specific model/effort settings;
  • persists the complete allocation and reason on the manager Session so restart and resume keep the same endpoint/model binding;
  • exposes policy, eligible pool, effective allocation, and reason through Personal Workspace settings, manager runtime details, and loopx chat-endpoint inspect-steward;
  • rebuilds the packaged Chat assets and documents the configuration, authority, and evidence contracts.

This stage covers explicit configuration, explicit user selection, and availability-based Agent choice inside an authorized pool. Semantic task-fit routing and live first-use/correction qualification remain in the RFC program; this PR does not claim those outcomes.

Validation:

  • 85 exact-head focused Python tests passed across machine configuration, allocation, Session persistence/resume, API, manager context, and channel binding.
  • Dashboard acceptance, capability-configuration smoke, Personal Workspace contract test, packaged browser smoke, DCO, and dependency review passed on head 3c5860b7d.
  • Strict mypy passed with zero issues in its 22-file target graph; Ruff, changed-module compile, diff checks, actual CLI readback, and the public/private boundary scan passed.
  • semantic-vocabulary-drift-smoke.py passed under the source-checkout Python 3.13 environment with repository Node dependencies. The premerge host's /usr/bin/python3 is 3.9 and fails before scanning at zip(strict=...) on both this branch and origin/main.
  • Exact-head premerge direct checks, module-ceiling colocation, all 8 risk-profile smokes, and public-boundary checks passed. Its overall status remains held by inherited origin/main failures: module budgets tracked by refactor(chat): remove inherited module-budget regressions #4793 and a date-expired Lark fixture tracked by test(lark): date the manager-context fixtures from the run #4798; this diff adds neither finding.
  • Change-quality receipt: cqr_0353f91fa205361083d3 (pass, exact head/diff).

The future-facing refactor moved allocation validation and runtime projections into the steward-executor contract. loopx/chat_runtime.py remains at its inherited 1,566-line ceiling with zero net growth.

No first-viewport presentation changed; the UI work is confined to the existing machine settings and collapsed manager runtime details.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

评审对象:PR #4802,精确 head e9d0103

动机

这个 PR 解决的是管家执行器“有默认值、没有完整决策边界和可追溯回执”的问题。原有 steward_executor 只能表达首选 endpoint、model 和 reasoning effort;显式调用方可以改选其他 endpoint,但机器配置无法表达“必须锁定”或“只允许在某个集合内自动切换”,Manager Session 也没有保存完整 allocation,因此配置变化和进程重启后,当前会话可能被重新解释。

本次交付是 #4779 路线中的一个完整阶段:显式配置、显式用户选择,以及授权池内基于 availability 的 Agent 选择。它没有提前声称已经实现语义任务匹配。这个边界合理,因为它已经让 Dashboard、Lark 和 CLI 共享同一套选择、持久化和回读语义,同时把后续语义路由留在同一个权限边界内演进。

改动思路

权威关系保持单一:

  1. steward_executor machine configuration 保存不可推导的 operator intent:preferred、pinned 或 flexible,以及 flexible 的 closed eligible pool。
  2. chat_manager.manager_executor_allocation 是唯一选择 owner。它综合 machine intent、显式 endpoint、capability availability 和既有 model resolution,产出一份完整 allocation。
  3. ChatRuntimeController 只执行这个决定:先检查 endpoint availability,再启动 adapter,成功后把 allocation 保存进 Manager Session。
  4. resume_latest 优先读取 Session allocation,所以 revision A 下启动的会话不会被后来 revision B 的机器配置静默改写。
  5. manager_channel_binding、Session public projection、Personal Workspace 和 inspect-steward 都只做回读,不重新决定路由。

最强的反对理由是:为了三个 policy 值修改了 runtime、store、CLI、UI、docs 和 packaged assets,范围看起来偏大。但只加 policy field 会留下 restart drift 和“为什么选中它”不可见的问题;只保存 endpoint 又会丢失 model、pool、reason 和 source revision。当前实现复用了既有 machine namespace、Chat owner、Session store 和 shared settings editor,没有建立第二套 selector 或配置库,因此这个 cross-surface 范围与用户可见结果相称。

具体改动

关键代码讲解

  • loopx/chat_manager.py:405 的 manager_executor_allocation 负责 policy enforcement。pinned 在 controller.open_session 之前拒绝不同的显式 route;flexible 的自动候选只由 primary 与 eligible_endpoints 构成,capability discovery 不会扩张授权池。
  • loopx/capabilities/steward_executor/allocation.py:63 的 normalize_manager_executor_allocation 固化 Session receipt:policy、reason、endpoint、pool、revision、model 和 effort 都是 closed/typed 字段。flexible endpoint 必须属于 pool,非 flexible allocation 不允许携带 pool。
  • loopx/chat_manager.py:834 的 open_manager_session 在隐式 resume_latest 时优先复用已有 Session allocation;显式新选择仍会经过当前 policy 重新授权。
  • loopx/chat_runtime.py:510 的 ChatRuntimeController.open_session 用 allocation 中的 model/effort 启动真实 adapter,并仅在启动成功后持久化 Manager Session。
  • machine-configuration-settings.tsx:42 的 guided editor 把 steward v0 编辑迁移到 v1,并在 preview 前拒绝空 pool、重复 endpoint、primary 不在 pool 等非法 flexible 状态;server normalizer 仍是最终 authority。

其余改动把同一事实投射到 Dashboard runtime details、Zod contract、inspect-steward CLI、RFC 和 operator/reference 文档。旧 v0 machine document 继续接受并映射成 preferred;旧 Manager Session 没有 allocation 时仍走原 resolver。Dashboard 首屏没有改变,新增信息位于现有 machine settings 和折叠 runtime details。

对主干的风险

最大的风险是 selector、Session restore 和 readback 之间出现分叉,导致一边显示 Codex/GPT,另一边实际启动 dsh,或 flexible 在 primary 不可用时越过授权池。当前 exact head 通过以下证据覆盖了这条链路:

  • 85 个 focused Python tests 通过,覆盖 policy validation、pinned/out-of-pool rejection、availability fallback、Session persistence/resume、API 和 manager binding。
  • base/head 使用相同输入比较,默认 Codex/gpt-6-astra 与 environment-selected dsh/deepseek-v4-flash 的既有字段保持一致。
  • source-checkout inspect-steward 回读 codex、gpt-6-astra、preferred、product_default 和空 pool;真实 steward binding smoke 通过。
  • Chat build、capability configuration smoke、Personal Workspace contract smoke、packaged execution-chip scenario,以及独立的 steward settings preview/apply browser probe通过;机器配置 apply 保留 exact preview revision。
  • git diff --check 通过,构建后 branch 保持干净。

完整 packaged Personal Workspace catalog 在本次复核中停在一个较早、与本改动无关的 Goal lifecycle timing 场景,因此我不把它记为 full pass。受影响的 execution readback 与 steward settings 路径随后独立运行并通过。Live provider request 也没有执行;这里的关键 contract 是 provider 启动之前的授权、model binding 与 Session persistence,真实 filesystem store 和 runtime boundary 已经覆盖。

语义与 CI 对齐

这次是对既有 steward_executor 和 manager_channel_binding vocabulary 的扩展,并新增范围准确的 manager_executor_allocation_v0;没有把 ephemeral selection 说成 peer Agent authority,也没有把 availability 当成授权。错误文本和文档保持 goal/domain neutral,machine policy 明确是 machine-enforced obligation,不是 guidance。评审 packet 的 wait_for_ci 为 false,所以结论基于 exact-head repository-native local validation,没有把 pending remote CI 当作通过证据。

我的整体评价

没有 blocking finding。这个 PR 把“默认选谁”提升成一份可配置、可约束、可持久化、可回读的 Session decision,并且保留 Codex/GPT 的 shipped default、v0 compatibility 和 explicit user intent。代码量主要来自跨入口完整性、tests/fixtures、docs 和 packaged assets;核心 authority 仍集中在现有 owner 中。

Future-facing pass 已检查:把前端 allocation reason 的条件分支整理成 typed localization map 会稍微降低后续维护成本,但当前不影响语义,也不值得扩大本 PR。后续应在此 authority boundary 上补 semantic task-fit evidence 与 packaged first-use/correction qualification。

English verdict: APPROVE - exact head e9d0103; no blocking findings. The closed policy/pool, restart-stable Session allocation, backward-compatible defaults, CLI/Dashboard readback, and affected UI paths were validated locally.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-head review addendum

Review target: PR #4802 at 3c5860b7dceb2b2bb909b9840dedb18bfd7b75af.

The follow-up commit repairs the only branch-local CI regression found after the prior review. steward_executor.allocation no longer imports the control-plane execution-profile graph, machine_defaults no longer imports chat_manager at runtime, and execution-profile plus orchestration validation now reuse one provider-neutral REASONING_EFFORTS value. This removes the mypy import expansion and two duplicate vocabularies without changing allocation policy, persisted Session fields, defaults, or fallback authority.

Exact-head evidence:

  • strict mypy: 22 configured files, 0 errors;
  • Ruff: passed for all five files in the repair;
  • focused pytest: 85 passed across steward allocation/configuration, Chat API, manager context, and channel binding;
  • dashboard acceptance, DCO, dependency review, both optional-Ark contracts, PostgreSQL integration, desktop builds, Node compatibility, Stage 2C, and completed Python shards: passed;
  • semantic vocabulary smoke: passed under the source-checkout Python environment with repository Node dependencies;
  • change-quality receipt cqr_0353f91fa205361083d3: valid for the exact current base and diff.

I found no new blocking correctness, authority, configuration, compatibility, privacy, or presentation issue in the final diff. The PR is still not merge-ready because current origin/main has two independent CI regressions: the module-budget debt is repaired by #4793, and the date-expired Lark fixture is repaired by #4798. Those dependencies remain review-required and should land before this branch is refreshed and its final CI/readback is judged.

English verdict: APPROVE THE DIFF - exact head 3c5860b7dceb2b2bb909b9840dedb18bfd7b75af; no blocking finding in this PR, with merge readiness held on #4793, #4798, refreshed-base CI, and maintainer review.

@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Integration qualification update

Reviewed PR #4802 head 3c5860b7dceb2b2bb909b9840dedb18bfd7b75af together with approved dependency PR #4793 head b28af169f271eb9997b07730c1f034d58cccb827 in an isolated detached integration checkout.

  • Git merged the two exact heads cleanly with no conflicts.
  • The combined focused suite passed 153 tests: the maintainability ratchet, the full Lark goal-topic runtime file (including both dated context cases), and all five steward-allocation test files from feat(steward): persist guided executor allocation #4802.
  • Configured strict mypy passed: 22 source files, 0 issues.
  • Ruff on the combined changed Python surfaces and git diff --check passed.

This proves that #4793 contains both integration repairs needed by #4802: the module-budget cleanup and a single fixed-clock repair for the dated Lark fixtures. PR #4798 is therefore not an additional integration dependency for #4802.

The remaining merge path is explicit: a maintainer must update and land #4793 (its exact-head approval is valid, while merge readiness currently reports only merge_state_requires_update), then refresh #4802 onto that main revision and rerun exact-head CI/review. No merge was performed and no branch head was changed by this qualification.

@huangruiteng
huangruiteng merged commit 84fb052 into main Sep 20, 2026
29 of 33 checks passed
@huangruiteng
huangruiteng deleted the codex/local-agent-allocation branch September 20, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant