Skip to content

fix(quota): fail closed when the Goal's active state is missing - #6802

Merged
huangruiteng merged 4 commits into
loopx-project:mainfrom
JasonBuildAI:codex/agent-k7v2
Oct 18, 2026
Merged

huangruiteng merged 4 commits into
loopx-project:mainfrom
JasonBuildAI:codex/agent-k7v2

Conversation

@JasonBuildAI

@JasonBuildAI JasonBuildAI commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

A Goal whose declared active state file is gone no longer receives a normal delivery authorization, and its skip packet now points at the documented repair instead of the work it cannot do. Before this change loopx quota should-run --goal-id returned status_health_ok=true, decision=run, should_run=true, normal_delivery_allowed=true and a required read of the missing ACTIVE_GOAL_STATE.md, even though the same status payload reported the per-goal state_file_missing finding with a reconnect/retire repair. Host automations that follow the gate therefore spent a turn every cadence on a Goal with no state to advance; at the documented initial 30-minute App cadence (app_automation_initial_rrule in docs/quota-allocation.md) that is up to 48 authorized turns per day for one stale entry. After the change the same command returns status_health_ok=false, decision=skip, should_run=false, state=blocked_health, and reason/recommended_action carry the finding's retire-global-goal preview, while a healthy Goal still returns run.

  • Outcome basis / optional anchor: reproduced control-plane defect, issue [Bug]: quota gate authorizes automatic turns for a Goal whose declared active state file is missing #6799; the status contract already defines this finding in docs/status-data-contract.md.
  • Goal/source and gap: loopx/control_plane/quota/decision_summary.py::goal_status_health_ok guarded automatic compute on contract diagnostics and global_registry.ok, but never on the per-goal state_file_missing finding, so the quota gate kept authorizing a normal delivery turn with a required read that cannot succeed. The skip packet also carried the live lane's generic "run the first adapter tick" action instead of the status finding's repair action.
  • Observable before → after, with the validation row that proves it: real_entrypoint and regression_parity rows below.
  • Issue/task and intended base: Fixes #6799; base main at a54c030ee79ea9270fed4ca94f9592f32a19232a.

Author Declaration

  • Written by: model_agent (DeepSeek Harness, deepseek-flash) at the requesting operator's direction and review.

Implemented against

Criterion (spec clause) Disposition Symbol / path Test or command
A per-goal state_file_missing action finding must prevent normal delivery authorization implemented goal_status_health_ok tests/control_plane/test_contract_health.py::test_quota_does_not_authorize_a_goal_whose_declared_state_is_missing
The guard must affect only the Goal named by the finding implemented goal_missing_state_blocker tests/control_plane/test_contract_health.py::test_missing_active_state_finding_blocks_only_its_goal
A blocked skip must name the finding's repair action, not the live lane's run action implemented _apply_missing_state_health_guidance the end-to-end test asserts state=blocked_health, status=state_file_missing, source=global_registry, the retire-global-goal reason/action and must_attempt=false
Source-registry provenance findings stay non-blocking (shadowed by the status projection) deferred (no change) _GOAL_MISSING_STATE_FINDING the scoping test keeps a stale_source_registry finding for another Goal non-blocking
The guidance rewrite must not relabel operator-gate, terminal-closure, monitor-quiet or safe-bypass skips implemented _apply_missing_state_health_guidance tests/control_plane/test_contract_health.py::test_missing_state_guidance_keeps_other_skip_routes_unchanged
  • Self-check before submission: read the status contract and the quota decision path; ran the failing-before/passing-after regression, the focused quota suite, the canary premerge gate and the public boundary scan. An independent review of the first commit found that the skip packet still carried the generic run guidance and that the guard trusts the global-registry route; the guidance part is fixed in the second commit. A second review found that the first guidance rewrite was too broad for operator-gate and terminal-closure skips; the third commit narrows it to the eligible health skip and adds cross-state regressions. The route limitation is disclosed below.

Scope And Continuation

  • Completed scope and remaining work: the quota health guard now treats a per-goal state_file_missing global-registry finding as a status-health failure, and the eligible health skip packet's state, status, source, reason and recommended_action follow the finding's repair action. Other skip routes (operator_gate_notify, terminal_no_followup, monitor_quiet_skip, automation_prompt_upgrade_required, safe bypass, real runs) keep their own state, effective action and user/agent channel. No schema or field additions. Deliberately untouched: the status projection still lists the live run lane beside the registry finding, and quota status/quota plan still count the Goal as eligible while health_blockers reports the finding; those are separate read-only projections. Their hosts are expected to use quota should-run as the automatic-turn gate, but aligning the plan projection is a reasonable follow-up.
  • Slice boundary / successor: complete within this scope. A typed control_plane_health_repair turn for this finding (instead of a skip) can be added later by projecting the finding into the item's health blockers; the default policy has control_plane.self_repair disabled, so today the skip is the fail-closed outcome.

Validation

  • Tested revision: 97e9f2caf5194af603fe2e0d9a46b9c70603b479 (commits 30cffa2de gate, 3b6a3d735 guidance, 18222bf40 scope, 97e9f2caf real operator-gate test variant)
  • Run state: finished
  • Input classes: synthetic
Check kind Result Public-safe evidence / limitation
static passed python -m ruff check tests loopx/canary loopx/control_plane loopx/domain_packs loopx/presentation: All checks passed!. git diff --check clean. scripts/generate_semantic_inventory.py --changed-from HEAD: no supported new vocabulary carriers.
unit passed pytest -q tests/control_plane/test_contract_health.py: 12 passed; focused quota suites plus quota markdown renderers: 156 passed.
regression_parity passed At parent a54c030ee the end-to-end regression fails on status_health_ok (assert True is False); at the gate-only commit it fails on the guidance (assert 'eligible' == 'blocked_health'); at this head both pass. The cross-state regression asserts operator-gate, terminal-closure, monitor-quiet, safe-bypass and should-run packets are unchanged; the live target packet still carries the repair guidance. The helper scoping test fails at parent as well.
real_entrypoint passed Native Windows source checkout: a Goal with its state file deleted returned status_health_ok=true, decision=run, should_run=true before this diff; at this head it returns false, skip, false, state=blocked_health, status=state_file_missing, source=global_registry, the retire-global-goal preview in reason/recommended_action, must_attempt=false, primary_action="do not run delivery work for this goal in this turn" and no required reads. A healthy Goal remains true, run, true.
integration passed with one pre-existing host failure loopx canary premerge --from-git-diff --git-diff-base upstream/main at the final head 97e9f2caf: 16 selected checks, 15 passed; risk-profile smokes 8/8. examples/control_plane/quota-plan-smoke.py fails on this cp936 host with UnicodeDecodeError: 'gbk' codec ... in the smoke's own subprocess reader and TypeError: ... not NoneType; the identical failure occurs with the parent decision_summary.py at a54c030ee, and the smoke passes unchanged with PYTHONUTF8=1. Not caused by this diff.
static (mypy) blocked (host) python -m mypy on native Windows reports 6 pre-existing POSIX-attribute errors in loopx/extensions/process_runtime.py and loopx/control_plane/effect_runtime.py; none in the changed files. CI runs mypy on Linux.
hosted (windows-powershell) not_run Hosted CI only; this change touches no host-specific code and the lane runs on this head.
  • Coverage and gaps: the changed gate is covered by a unit test and an end-to-end quota decision test, and the guidance by the same end-to-end test; the real CLI before/after is recorded above. Not covered by tests: a stale global-registry entry whose local Goal is actually runnable (the guard would block it until the global entry is repaired; the status finding already recommends reconnect/retire), the adjacent state_file_not_declared finding, and malformed global_registry.findings shapes (the guard fails open on missing/malformed containers). The status and quota-plan projections still list the Goal as eligible; the automatic-turn gate is quota should-run and is now fail-closed. The cp936 smoke-harness failure is pre-existing host behavior, not a changed path.

Frontend / Visual Evidence

  • UI impact: none
  • Before: N/A
  • After: N/A
  • States and viewports shown: N/A
  • Source data: none
  • Attention review: N/A (no visual surface)
  • Craft review: N/A (no visual surface)

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring (no functional changes)
  • Documentation update
  • Test update

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)
  • Benchmark boundary (adapters, runners, verifiers, scoring, evidence)
  • Capability or extension (providers, adapters, skills)
  • Public docs or presentation surface (README, protocols, dashboard)
  • Build, packaging, installer, or CI
  • Host or runtime integration

Technical Direction

  • Core control-plane hardening.

Shared-authority RFC fixture impact

  • N/A: no shared-authority RFC fixture, provider conformance arm, or runtime-routing change.

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths (including .loopx/, .codex/goals/, and live ACTIVE_GOAL_STATE.md).
  • I did not duplicate maintainer-owned benchmark work unless a maintainer split out a public issue for it.
  • I kept the change scoped to the linked issue/task.
  • I completed the visual evidence section for UI changes, or marked UI impact none.
  • Every commit includes a DCO Signed-off-by trailer (git commit -s).

AI disclosure: this change was drafted with AI assistance at my request, under my direction and review.

`loopx status` reports a per-goal `state_file_missing` finding with the
reconnect/retire repair, but `loopx quota should-run --goal-id` still
returned should_run=true with normal delivery allowed and a required read of
the missing ACTIVE_GOAL_STATE.md. `goal_status_health_ok` only consulted the
status contract diagnostics and `global_registry.ok`, so an automatic host
turn kept being authorized for a Goal that has no state to advance.

Treat the per-goal `state_file_missing` finding as a status health failure.
Source-registry provenance findings are deliberately shadowed by the status
projection and stay non-blocking.

Before/after on a native Windows source checkout at a54c030: a Goal whose
state file was deleted returned status_health_ok=true, decision=run,
should_run=true, normal_delivery_allowed=true; the same command now returns
status_health_ok=false, decision=skip, should_run=false, and a healthy Goal
still returns run. The two new regressions fail without the fix and pass
with it.

Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
JasonBuildAI added a commit to JasonBuildAI/loopx that referenced this pull request Oct 18, 2026
The first commit fails the automatic turn closed, but the skip packet still
carried the live lane's generic "run the first read-only adapter tick" action
and reason. A host that displays the packet's guidance would still be pointed
at work it cannot do. Reuse the status finding's reconnect/retire
recommended_action for the packet's reason, recommended_action, state, status
and source when the gate blocks for a missing active state file.

The end-to-end regression now asserts the repair guidance, the blocked_health
state, the state_file_missing status, the global_registry source and
must_attempt=false; it fails with only the first commit and passes here.

Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
JasonBuildAI added a commit to JasonBuildAI/loopx that referenced this pull request Oct 18, 2026
The previous commit rewrote the top-level state, status, reason and
recommended action of any skip packet that coexisted with a
state_file_missing finding. That relabeled operator-gate and
terminal-closure skips as blocked_health, which can hide a legitimate user
prompt or block terminal completion of a canonically closed Goal.

Restrict the rewrite to the eligible quota skip that the health gate itself
blocked: status health false, effective_action=quota_skip, state=eligible and
no safe bypass. Other skip routes keep their own state, effective action and
interaction/user channel.

Add helper-level regressions for operator-gate, terminal-closure,
monitor-quiet, safe-bypass and should-run packets, and keep the target health
skip assertions.

Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
The cross-state regression used status_health_ok=true for the operator-gate
packet, so it did not mirror the real coexistence shape: an operator gate plus
a missing-state finding makes status health false. Use the real false variant;
the effective_action check still keeps the gate state and user channel
unchanged.

Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
JasonBuildAI added a commit to JasonBuildAI/loopx that referenced this pull request Oct 18, 2026

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · reasoning_effort=max

Exact head: 97e9f2caf5194af603fe2e0d9a46b9c70603b479

动机

项目仍登记在本机、但 Goal 的状态文件已经缺失时,自动调度调用者需要知道该 Goal 暂时不能交付,以及应修复哪个入口。

在同一个双 Goal 环境中删除其中一个状态文件,旧 status 已报告 state_file_missing,quota should-run 仍允许运行;本修改使该 Goal 返回 blocked_health,并保留另一个健康 Goal 的运行路径。

源码与普通安装包的真实 CLI 都会在目标 Goal 有精确缺状态 finding 时拒绝正常交付,并给出该 finding 原有的修复建议;其他健康 Goal 继续,原文件按原字节恢复后目标 Goal 也恢复运行。

范围是消费 status 已产生的、精确匹配 Goal 的 state_file_missing finding;不声称缺失/畸形诊断容器、state_file_not_declared、stale global entry、主机唤醒前拦截或用户通知策略都已修复。

改动思路

复用 status 现有 finding 作为事实,在现有 health 投影和 should-run 的拒绝提示边界补齐消费即可;没有新增持久 health 状态、通用 Python 调度决策源或要求所有 Goal 重配。

当前 PR 交付精确 Goal 缺状态诊断到 quota health/修复建议的可用闭环;生产者未报告 finding 的其他健康诊断与主机通知属于既有 status 和 host owner 的独立边界。

先从 status 的现有 global_registry_health.findings 中按 kind 和 goal_id 精确找事实,传入已有 health 决策。只有普通 eligible quota_skip 且无 safe bypass 时补上缺状态的拒绝原因;终态、operator、monitor quiet 等分支不被这层投影接管。没有新增存储或用户设置。

具体改动

完整 a54c030ee79ea9270fed4ca94f9592f32a19232a → 97e9f2caf5194af603fe2e0d9a46b9c70603b479 差异:2 existing quota Python production files (82 added lines) and 1 focused existing test module (216 added lines); three paths total,+298/-0。

  • goal_missing_state_blocker:new exact lookup of existing diagnostic;输入 status global_registry_health findings,关键条件 only exact state_file_missing + exact goal_id。结果由 goal_status_health_ok and guidance 消费,失败仍由 missing/malformed containers return None; not a new generic fail-closed promise 处理。
  • goal_status_health_ok:matching missing state now returns false;输入 current status plus current goal,关键条件 unrelated Goal/source provenance remains separate。结果由 typed quota decision input 消费,失败仍由 existing other health logic retained 处理。
  • _apply_missing_state_health_guidance:missing state reason/action replace generic quota text;输入 not running, unhealthy, eligible quota_skip, no safe bypass,关键条件 terminal/operator/monitor-quiet/bypass routes retain their owner。结果由 CLI interaction contract and operator 消费,失败仍由 repair source/reconnect then rerun 处理。
  • build_quota_should_run:applies bounded guidance after normal payload decision;输入 status capture and goal_id,关键条件 does not create a second store or bypass existing decision。结果由 native quota should-run 消费,失败仍由 existing health repair 处理。

规范来源 #6799,spec_revision=2026-10-18T08:24:16Z。state_file_missing:status 的目标 Goal 缺状态 finding 应使自动 quota 不再正常交付。(implemented,goal_missing_state_blocker / goal_status_health_ok;paired source/global native CLI + installed wheel);goal_scope:其他 Goal 与来源注册表诊断不能误挡当前健康 Goal。(implemented,exact kind + goal_id matching;health-beta and new health-gamma public CLI);repair_guidance:拒绝时复用真实 finding 的 reason/recommended_action。(implemented,_apply_missing_state_health_guidance;independent status finding vs quota output readback)。基线规范在完整 diff 前读取;本 PR 对文档的修改也作为被审内容,并未当作独立授权。

测试继续放在原 quota health 模块,覆盖精确 kind/Goal、其他来源 finding、正常运行及终态/operator/bypass/quiet 分支。后几类是源码 builder 的路由保留检查,不是新增的真实主机 operator-gate 实验。健康事实生产者与既有 TypeScript admission owner 保留,没有按文案前缀分类。

对主干的风险

Common synthetic two-Goal fixture through bootstrap/status/quota should-run: baseline missing-file refusals/guidance fail the independent oracle; exact source head and noneditable wheel each pass 7 cases. Additional new-Goal-after-finding, reordered global registry and byte-identical restoration counterfactuals pass.

70 focused Python tests passed (49.10s), including health matching, decision summary/capture and live decisions. 6 direct + 16 selected checks passed; zero failing commands/manual holds. Managed qualification is held only by stale_receipt.

真实 CLI 对照包含原始健康、source/global 缺状态、健康 sibling、新建健康 Goal、global 顺序变化和按原字节恢复。缺状态 guard 退出 1 是预期拒绝,不是执行器故障;修复动作与独立 status finding 对比,未硬编码某个 retire 命令。返回仍为 DONT_NOTIFY,本 PR 未改变 host 通知或消除模型唤醒。

正常 dashboard Chat build 与普通非 editable wheel 构建通过,改变的生产文件与 wheel 逐字节一致,隔离安装后重跑实际入口。初次从仓库根误调用不存在的 npm build:chat 脚本,改到真实 dashboard 目录后才完成构建;没有把该调用错误归因于产品。补充探针中的回执路径/旧 Turn 前置条件也按真实契约修正,原失败保留,未移除独立 oracle。

No remote CI consulted or Windows execution. Author historical cp936/mypy failures remain unverified historical claims; current Mac selected checks pass without claiming the old cause was repaired. Stale exact-scope quality receipt remains a separate merge hold. Notification/host wake suppression, malformed/missing diagnostic containers and other status findings are not qualified.

本轮没有查询、轮询、等待或触发 CI。最新 main 与相关工作核对后,没有发现生产 owner 已完成的同义修复;共享文档的其他行或无关 successor passthrough 不构成本 PR 的重复。

我的整体评价

复用 status 现有 finding 作为事实,在现有 health 投影和 should-run 的拒绝提示边界补齐消费即可;没有新增持久 health 状态、通用 Python 调度决策源或要求所有 Goal 重配。

当前 PR 交付精确 Goal 缺状态诊断到 quota health/修复建议的可用闭环;生产者未报告 finding 的其他健康诊断与主机通知属于既有 status 和 host owner 的独立边界。

有界目标判定 goal_achieved:交付了可读回的拒绝和继续路径,不以文件数、测试数或回执存在代替结果。long_horizon=improved,重放/恢复/独立新 subject 的实际验证支持后续继续;user_experience=improved,沿既有 CLI 读回真实状态和恢复建议,无新增配置、复制信息或确认步骤。

有界未来重构检查:共享精确 finding helper 已足够,维持事实生产、health 输入和提示投影的现有分工;为此进行完整语言迁移或扩大诊断分类没有必要。代码层面 APPROVE 仅对本 exact head;托管质量凭据、原生 merge readiness 与维护者显式合并授权仍是独立条件。

English verdict: APPROVE at 97e9f2caf5194af603fe2e0d9a46b9c70603b479. Common synthetic two-Goal fixture through bootstrap/status/quota should-run: baseline missing-file refusals/guidance fail the independent oracle; exact source head and noneditable wheel each pass 7 cases. Additional new-Goal-after-finding, reordered global registry and byte-identical restoration counterfactuals pass. 70 focused Python tests passed (49.10s), including health matching, decision summary/capture and live decisions. 6 direct + 16 selected checks passed; zero failing commands/manual holds. Managed qualification is held only by stale_receipt. No remote CI consulted or Windows execution. Author historical cp936/mypy failures remain unverified historical claims; current Mac selected checks pass without claiming the old cause was repaired. Stale exact-scope quality receipt remains a separate merge hold. Notification/host wake suppression, malformed/missing diagnostic containers and other status findings are not qualified.

@huangruiteng
huangruiteng merged commit 55d6337 into loopx-project:main Oct 18, 2026
30 of 36 checks passed
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.

3 participants