Repository navigation
fix(turn): preserve quota capability refusal facts - #5815
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; declaration_source=runtime_reported; reasoning_effort=xhigh. Host-recorded observation does not authenticate backend weights or active-Turn liveness.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机
采用短执行包的 CLI/Turn 宿主在任务缺少能力时会遇到这个问题。完整 quota 已说明任务需要 network 且当前缺失;旧短包却丢掉 required/missing,即使签名匹配也无法保留该拒绝事实。本批在既有 TypeScript 投影中原样保留这两组数组,真实 File/SQLite 的拒绝和合法准入均已验证。不重新计算就绪,不授予能力,不修改 SQLite 默认或强制迁移既有 Goal。共享完整要求读取、安装态 App 收敛、实际等待/backoff、模型成本与质量、剩余 Python 最后调用方仍待各自验收。
改动思路
能力门禁已有 typed owner;短包只投影其事实,在既有 boundary 中修复即可,不需要新的状态、策略、版本分支或 Python 决策源。本 PR 交付能力拒绝事实的源码、签名、真实入口回归和双语路线核对;完整 host 收敛与形态默认继续按既有三批验收推进。先由原生 quota 和能力门禁决定是否可运行,再由既有 TS read model 把同一捕获决策投影给宿主;Python 只保留当前 effect-runtime 的传输桥。正向路径保留 required 和合法空 missing,拒绝路径保留真实缺失项及原拒绝动作。完整候选诊断仍在有权限的详情中。没有新增 writer、执行器、手工同步状态或权限;这一入口修复不需要等待整个 RFC 或 PR 队列。
具体改动
六个文件,+159/-1。产品修改只有 boundary 的已有字段选择;一组72行真实 File/SQLite 矩阵、23行 TS 签名/历史输入负例,以及协议披露和双语 RFC 执行事实核对。完整要求读取的相邻工作是 #5794 的提案,本批未重复实现,也未把提案当已安装行为。
关键代码讲解
loopx/control_plane/quota/turn_envelope.ts:322的 boundary 在375–382行取 payload.capability_gate,380行加入 required/missing,仅拷贝非 null/undefined 的既有字段。空数组不被删掉,历史 required_capabilities/missing_capabilities 仅在源中存在时保留;不重算就绪,不复制私有候选集合。loopx/control_plane/quota/turn_envelope.ts:869的 buildTurnEnvelope 仍先取同一 turnActionProjection,再对源投影和 envelope 生成签名。当前数组进入既有 boundary 签名;同一捕获源的身份、动作、结算和 scheduler 不变。匹配只证明所覆盖投影相同,不能证明所有原生事实都保留,因此真实测试独立读取完整 decision 的 required/missing 作为 oracle。
依据是改动前 docs/architecture/rfcs/agent-loop-effect-interpreter-v0.md,revision 93599b3a401314e21167da257a003418413016b1。逐项映射:Reconcile execution/context requirements across heartbeat and TurnEnvelope 的事实清点与本能力遗漏修复 implemented,其完整 host 要求仍保留;Adopt one typed projection in real host renderers deferred,实际 App/read/detail/backoff/迟到和一次结算仍待原验收;Qualify the context shape and migration default deferred,只测了 bytes,没有模型或持续运行收益。协议历史签名保留和有权详情要求保持;本 PR 新写的核对不替代旧规范。
对主干的风险
最强反例是源和短包用同一漏字段函数,签名仍匹配。不可变基线的真实 CLI 已在拒绝 network 的 File 案例复现 KeyError required;head 的真实16案例通过,独立 wheel 的16案例也通过,覆盖两 provider、拒绝/准入、off/recall-only/ingest-only/失效绑定。TS22例保留历史字段、空数组和私有诊断排除;修改 missing 后签名文档不同。重建纯投影前后 store 字节一致,未再执行准入。相关 Python162例与类型检查通过,既有 host provider 失败和结算隔离仍有覆盖。
17个相同源观察的基线/head 对照中,身份、action、writeback 和 scheduler 一致;新增36–46个 UTF8 bytes。包已有约9–14.5KiB,8KiB performance target 未放宽,也未把超目标变成准入限制。新构建的边界哈希会改变;存储签名和原回执不重写,不声称跨版本哈希等价,也不声称形态默认已合格。代码回滚无需数据转换。前端/Lark 没有新操作或配置,未把 wheel CLI 通过当作 App 采用。
语义与 CI 对齐
本批复用既有 capability_gate_v0 vocabulary 和 TS 投影,语义 advisory 没有新注册词表。原生风险检查的13/14项及4项直接检查通过;完整 semantic smoke 仍失败。失败是 project_lifecycle_refresh_state.py 的两个 load_registry codec_read site 与现存 I/O manifest 不一致,最新不可变基线 93599b3a401314e21167da257a003418413016b1 和 head f23d379024f38eb595e5484525628681b8f32c6f 的原始 stderr 完全一致,源及 manifest 字节均未改动。独立归因是 pre_existing_unrelated,原始失败仍 unresolved;质量 receipt 的 pass 没有把它变绿。应由该 manifest/入口 owner 修复并重跑原检查,合并就绪另行判断。评审 packet 的 wait_for_ci=false,依照本地原生证据判断,未为评审轮询或等待远端 CI。初期 fixture 对宿主本地 capability 推断和显式拒绝退出码的错误假设已改正;那些不是产品失效证据。
我的整体评价
交付为 justified_increment。long_horizon=preserved:动作/绑定/原生结算和 scheduler 不改变,现有恢复负例未被削弱;user_experience=improved:真实短包保留原拒绝原因而不增加 setup、确认或权限。没有发现本 exact head 的阻断缺陷;独立归因的主干红项和未知外部严格 digest consumer 风险保留。范围 proportionate,最高价值的未来向处理已是复用同一 TS owner,避免新 Python 策略和额外 executor。其余 renderer/Host IO 的退出必须等待真实最后调用方;共享完整 reads、安装态 host 与成本/质量仍保持未完成。APPROVE 是此边界的代码判断,不是整体 Goal/SQLite 发布默认验收,也不是 maintainer merge 权限。
English verdict: APPROVE - 5815@f23d379024f38eb595e5484525628681b8f32c6f. Real native and installed File/SQLite facts, signature negatives and same-source parity pass. The independently reproduced unchanged manifest failure remains red and a separate merge-readiness risk. Runtime/control-plane merge is left to the maintainer.
Goal And Delivered Outcome
A refused quota decision names its required and missing capabilities with
required/missing. TurnEnvelope selected only historical field names, so a compact host lost those facts even though its projection signature matched. Retain the current arrays intact in the existing TypeScript boundary projection, including an empty missing list after admission; preserve historical names when supplied.Basis: heartbeat/Turn execution-fact convergence under effect-interpreter M7.4 and roadmap S2/S3/S6/S8. This is one omission repair, with the existing RFC updated to distinguish remaining full reads, identity, lease, closure, scheduler and optional-memory requirements. Base:
mainat93599b3a401314e21167da257a003418413016b1.Author Declaration
docs/architecture/rfcs/agent-loop-effect-interpreter-v0.md“Heartbeat and Turn Envelope convergence” anddocs/reference/protocols/turn-envelope-v0.mdat the stated base.Self-check inspected the native gate, compact owner, signatures, current related PR and real CLI/installed-package paths. The future-facing pass reuses the existing field projection directly; no builder, vocabulary, provider, schema version or Python decision owner is added.
Scope And Continuation
This changes newly generated compact boundary facts and therefore their hashes. Saved signatures are not rewritten; no cross-version hash-equivalence is promised. Full quota output, admission, capability activation, claims/leases, settlement and scheduler ownership remain unchanged. Reading these facts grants no capability. Current provider/policy defaults and existing Goal migration/recovery are unaffected.
The bounded omission is repaired; whole heartbeat/Turn convergence and SQLite release qualification remain open under the existing RFC. This does not qualify installed App adoption, model value, sustained operation or removal of Python IO adapters.
Validation
f23d379024f38eb595e5484525628681b8f32c6f.-I: the same 16 cases; installed package and TS owner provenance verifiedrequired; head preserves required/missing and detects signature mutation. Same-source comparison over 17 captures retains identities, actions, writeback and scheduler; adds 36–46 bytes without changing budgetsInitial fixture assumptions about ambient local capabilities and refused-selection exit status were corrected before the demonstrated omission; the actual production counterexample remains recorded. Initial wheel build rejected a stale frontend bundle; a real rebuild and new wheel validation passed. Baseline census setup required a tracked fixture and installed TypeScript dependencies before the matching raw failure was proven. No gate or budget was relaxed.
Frontend / Visual Evidence
UI impact: none. This is an existing host read-model correction, with no new operation, capability or settings. CLI compact JSON changes; full JSON remains the source decision. No first viewport changes.
Control-plane change: maintainer merge required. The unresolved baseline manifest failure is disclosed and must not be treated as a green merge gate.