Skip to content

fix(coordination): resume interrupted canonical Goal creation - #7381

Merged
huangruiteng merged 1 commit into
loopx-project:mainfrom
JasonBuildAI:codex/agent-x7r2
Oct 26, 2026
Merged

huangruiteng merged 1 commit into
loopx-project:mainfrom
JasonBuildAI:codex/agent-x7r2

Conversation

@JasonBuildAI

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

An interrupted loopx bootstrap currently bricks the Goal id and leaves the entire project's status failing; this change lets the next bootstrap resume the registered creation instead of rejecting it as a changed registration.

  • Outcome basis / optional anchor: fixes [Bug]: an interrupted canonical Goal creation cannot be retried and leaves the project status failing #7379 (reproduced on main f794ee464; original baseline 93bb1ed27)
  • Goal/source and gap: loopx bootstrap publishes the Goal to .loopx/registry.json and writes its projection before the canonical authority exists. Any interruption after that point (Ctrl-C during the cold TypeScript authority start, a host failure, or a concurrent creator) leaves a registered Goal with no authority. Every retry then exits 1 with source_registry_changed_retry, --force refuses with "Canonical creation cannot rebuild existing state", and loopx status exits 1 with "canonical Todo contract unavailable: Canonical authority is required". The documented recovery ("retry its original operation") never runs.
  • Observable before → after, proved by the validation rows: retry exit 1 / source_registry_changed_retry / status ok=false → retry exit 0 / state_action=kept-existing / authority_initialized=true / status exit 0 ok=true. The focused regression fails on the parent owner with ShadowManagementError: source_registry_changed_retry and passes at this head.
  • Issue/task and intended base: Closes #7379; base loopx-project/loopx:main.

Author Declaration

  • Written by: model_agent (DeepSeek V4.1 via DeepSeek Harness), at the requesting operator's direction and under their review.

Implemented against

Criterion (spec clause) Disposition Symbol / path Test or command
An interrupted canonical creation resumes through the registered operation and target implemented _same_registry_observation in loopx/control_plane/coordination/authority_source_capture.py test_interrupted_cli_creation_resumes_the_registered_operation
A real route or registration change still fails closed implemented same test_cli_creation_recovery_cannot_recreate_or_adopt_authority[changed_source-file|sqlite] (unchanged, passes)
The real CLI recovers an interrupted create end to end implemented bootstrap_project retry path native Windows E2E in the validation table

Scope And Continuation

  • Completed scope and remaining work: complete within this scope. The fix restores resume for an interrupted creation; it does not change the refusal for a completed authority whose store was lost, for a changed creation_operation_id, or for an explicit route change.
  • Slice boundary / successor: N/A.

Validation

  • Tested revision: 5018930b23cacad722639b90a5beccc43fe92cdb
  • Run state: finished
  • Input classes: synthetic
Check kind Result Public-safe evidence / limitation
unit passed pytest -q tests/control_plane/test_new_goal_storage_defaults.py -k "interrupted_cli_creation or cli_creation_recovery": 7 passed, 61 deselected at the tested revision. The new case fails at the parent owner with ShadowManagementError: source_registry_changed_retry.
real_entrypoint passed Native Windows 11: interrupted bootstrap (Goal observed in the project registry, process killed) → retry exit 0 with state_action=kept-existing and storage_selection.authority_initialized=true; status exit 0 ok=true; todo add exit 0.
static passed ruff check loopx/control_plane/coordination/authority_source_capture.py tests/control_plane/test_new_goal_storage_defaults.py; git diff --check.
  • Coverage and gaps: The failure window was reproduced by killing the real CLI after registry publication; the regression test deterministically simulates the same post-publication failure. The full test file on native Windows also carries unrelated App preview-gate and Windows-symlink failures outside the changed path; they were not re-baselined here, and the focused recovery selection is green. Hosted Linux CI remains the authoritative full-suite check.

Type of Change

  • Bug fix

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)

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.
  • I did not duplicate maintainer-owned benchmark work.
  • I kept the change scoped to the linked issue/task.
  • I completed the visual evidence section for UI changes, or marked UI impact none (none).
  • Every commit includes a DCO Signed-off-by trailer.

AI Disclosure

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

The canonical creation retry passes the registered Goal with its state_file rewritten as an absolute path, while the typed source owner required the exact registry observation. An interrupted bootstrap therefore failed every retry with source_registry_changed_retry and left the project registered with a half-created Goal whose status reported canonical authority required.

Compare the resolved state route, as the typed owner already does, so the same route resumes the original creation operation while a real route change still fails closed.

Fixes loopx-project#7379

Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
@JasonBuildAI

Copy link
Copy Markdown
Contributor Author

Validation note at 5018930b2 (public-safe):

  • loopx canary premerge --from-git-diff --git-diff-base upstream/main: direct checks 6/6 passed, risk-profile smokes 8/8 passed. The one catalog failure is examples/semantic-vocabulary-drift-smoke.py, which exits 1 with repository npm dev dependencies are not installed (the typescript package is missing); run pm ci --ignore-scripts in this checkout. The same command exits 1 with the same message at the parent f794ee464, so this is a local environment gap, not a regression from this diff.
  • Hosted build fails in "Exercise the installed page in a real browser" with AssertionError [ERR_ASSERTION]: The source badge does not repeat the visible Goal title. The failing dashboard chat smoke and component are untouched by this PR, which changes only loopx/control_plane/coordination/authority_source_capture.py and its focused test; the changed coordination path is not exercised by that browser step.

@JasonBuildAI

Copy link
Copy Markdown
Contributor Author

Hosted CI note at 5018930b2: Sign-off, dependency-review, postgresql-authority, stage2c (mutants, installed, e2e 1), kernel-contracts, kernel-static-checks, typescript-core (3/3), chat-bundle and changes passed. The remaining failures are build and the browser shards (chat-bundle-browser 2/3, dashboard-browser 2), which fail in the dashboard/chat workspace smoke area (The source badge does not repeat the visible Goal title) that this Python-only diff does not execute. The Python test-shard, windows-powershell and remaining browser jobs were still running at this note. The changed path is covered by the focused suites above.

@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; model=gpt-6.1-sol; provider=OpenAI; runtime_reported; reasoning_effort=max.

动机

APPROVE,限 5018930b23cacad722639b90a5beccc43fe92cdb;未发现阻断问题。 本次独立核验的是中断创建后的恢复和有用后续工作,保留合并授权与安装资格的独立边界。

新建 Goal 时遭遇中断、随后重试 bootstrap 的用户或 Agent。

在注册发布后、权威初始化前中断:基线重试报 source_registry_changed_retry;当前头沿原操作和存储目标恢复,并能新增任务、再次重试且保留该任务。

同一次创建恢复后可继续做原任务,设备默认值变化不改写已冻结的目标,错误路由和强制重建仍被拒绝。

本次不重建丢失的已完成权威存储,不改变权限、默认 provider、Todo 生命周期、安装状态或首 Host 的执行资格。

注册条目存在并不表示 Goal 已经可用。原失败会让每次重试在到达原生恢复 owner 之前退出,用户只能反复收到同一诊断。当前修复消除的是同一来源路径的表示差异,没有把真正的操作或存储变化当作可恢复输入。

改动思路

路径解析属于既有 Python 来源观察适配层;复用 resolve_state_file 后只归并同一路由,冻结目标、空来源、writer fence、CAS 和回执仍由原 TypeScript 创建 owner 判断。

当前边界:恢复既有 bootstrap 的同操作重试;一个本地比较函数加现有回归即可,不增加配置、状态副本、恢复协议或新的用户确认。

先比较除 state_file 之外的完整注册,再用已有 resolver 解析两份状态路径;只有指向同一路由才继续从当前注册内容构造来源快照。后续仍带注册字节 witness,并由 TypeScript 检查 operation、target、state route、空来源与原始 fence/receipt。这样修改的是表示归一化,不把 Python helper 变成第二个创建决策者。

输入 基线 本 head
原创建、相对/绝对同一路径 source_registry_changed_retry 沿原 operation 恢复
恢复前修改设备默认 provider 仍不能恢复 冻结的原 provider 不变
已新增 Todo 后再次 bootstrap 原 completed-receipt 路径 原回执恢复,Todo 完整保留
改路由、改 operation 或强制重建 拒绝 继续拒绝

最强反对理由是放松注册比较会掩盖真实变更;检查完整其它字段、来源 witness、下游冻结目标及真实拒绝测试,比另建重试状态或人工修注册更直接,也不会多加一次确认。

具体改动

评审前读取的接受依据是 https://github.com/loopx-project/loopx/blob/f794ee4642353b70cde185e2774fa0059c467d6a/docs/reference/local-authority-provider-selection.md,不可变版本 f794ee4642353b70cde185e2774fa0059c467d6a,尤其 New Goal authority 与原操作恢复/备份边界,并读取 issue #7379 和全部当前讨论。下列 id 是原条款的审计映射标签:

  • frozen-operation-and-target — implemented:After interruption rerun the same bootstrap; changed defaults cannot retarget its original operation and workspace.
  • replay-preserves-later-work — implemented:The original receipt survives later native writes; replay cannot erase or repeat Todos.
  • source-and-backup-boundary — implemented:Incomplete creation validates original source; lost completed authority requires backup recovery and forced bootstrap cannot rebuild it.

关键代码讲解

  • _same_registry_observation 只将 state_file 放入单独比较,其余完整字段仍需一致;两份路径复用 resolve_state_file 并解析为实际路由。缺失值不会制造一个新的来源。
  • build_runtime_shadow_source_snapshot 在既有 registry source witness 下读取当前记录。比较失败仍返回原 source_registry_changed_retry;成功后传入 current,保持快照来自当前权威观察。
  • initialize_goal_storage_target 是原有调用方:先向 typed owner 请求原回执,只有尚未完成创建才捕获来源。修复使 CLI 预先解析过的 state_file 能进入这条已有路径;已完成回执仍不要求重读缺失的 Markdown 展示。

差异为2文件、+79/-1;生产部分 +22/-1,其余是现有配置测试文件里的确定性中断回归。没有新模块、配置、持久化词汇、请求版本、provider 选择或安装步骤。调用搜索覆盖 bootstrap、App storage API、migration/inspection 和 unchanged typed source owner,没有重复业务决策或闲置抽象。

对主干的风险

独立完整 test_new_goal_storage_defaults.py 68项通过,test_shadow_registry_source.py 26项通过,原生 TypeScript 创建 suite 7项通过;同一普通创建/显式关闭/既有拒绝选择在不可变基线和 head 各9项通过。它们覆盖 File/SQLite、changed operation/source、缺失已完成 store、来源竞争、App HTTP 路径、禁用配置及正常目标冻结;不是只看新测试自己通过。

额外用同一独立 harness 在基线 f794ee4642353b70cde185e2774fa0059c467d6a 与当前头制造注册发布后的中断。只有中断点注入异常,后续均为真实 CLI:两种 provider 的基线重试都以 source_registry_changed_retry 退出1;head 都退出0,state_action 为 kept-existing、authority_initialized 为 true,并沿原 operation/provider 恢复。改变设备默认值不改写目标;恢复后实际新增 Todo、重试、再独立读取该 Todo,完整记录相同。错误路由与 force 分别退出1,未产生替代状态文件。

scoped Ruff、Python 语法和差异/双语检查通过。标准 premerge 的6项直接检查、13项选中检查通过,无人工留置;精确范围质量收据 cqr_d0a2bf8963d0ce479efb 为 PASS / valid,safe-fix 未使用。所有这些信息在首次完整评审前取得。原生 CI 未查询、轮询或等待;作者在讨论中的其它 CI 陈述没有被当作本次独立通过证据。

语义与 CI 对齐

该变更复用既有 original-operation/source-identity 契约,没有新共享词汇。原来把同一路由误拒绝的行为有意改变,其它字段比较、typed witness 和原创建目标保持;原始 force、缺失 store、changed operation/source 的拒绝不变。错误文本或 Agent 指导没有被压缩、替换或改成新的结算义务。回滚仅需撤回本地比较,不迁移权威数据、不清理 writer fence 或原回执。

我的整体评价

APPROVE,限 5018930b23cacad722639b90a5beccc43fe92cdb。 当前头完成了中断后重试并继续原任务这一有用修复。长期工作与使用体验维度为 improved,证据限于已验证的恢复、少一次手工修注册、以及后续 Todo 的持续读回;没有据此声称整体 Goal 完成或长期因果净收益。

检查的是现有 CLI 和规范来源捕获路径,没有页面、布局、组件或图片变更;视觉构图检查不适用。

未独立复验原生 Windows 的杀进程窗口、已安装 App 或首 Host 启动;中断发生点由受控故障注入,后续恢复与有用任务读回使用真实 CLI 和 File/SQLite。

这个局部边界适当:来源适配层归一化已知路径,现有 typed owner 保留执行决定,原注册和回执不会因设备默认值改变而漂移。有界简化是复用 resolver 与完整字段比较;无需新的状态机、版本或人工步骤。发布审批不清除其它人的未解决意见,也不授予合并、安装或生产操作权限。

English verdict: APPROVE at 5018930. The existing source adapter now recognizes equivalent state routes while the typed creation owner retains operation, target, witness and replay authority. Independent real File/SQLite CLI recovery preserves later work;94 Python tests,7 native TS tests,9 normal/refusal controls per arm and standard premerge passed. Exact-scope quality is PASS; native Windows kill timing and installed Host execution remain unqualified here.

@huangruiteng
huangruiteng merged commit c6462f9 into loopx-project:main Oct 26, 2026
25 of 38 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.

[Bug]: an interrupted canonical Goal creation cannot be retried and leaves the project status failing

3 participants