fix(workspace): settle registered originless local goals - #5614
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
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
审查 head:397e5eb3e8c70b0d7cfc9126a3380001a0b69189;基线:bd607db9c563b263111abdbc37167620e919feb7。未发现阻塞问题。
动机
使用已注册本地 Goal 的操作者,在没有 origin 的 Git 目录中完成研究或资料任务时,会遇到保存进展和结算之间的不一致。
此前 guard 允许开始,refresh-state 却无法识别工作区,导致已完成的工作不能结算,下一轮仍要处理相同拒绝。
本次预期改进是:只有注册根目录中的独立本地仓库才能使用已有 local_goal 身份;实测已完成保存、单次扣费、重复请求无新增扣费以及下一轮继续原 Todo。
本次不验收持续运行、全部宿主或 PostgreSQL,也不授予修改仓库、claim/lease 或完成 Goal 的权限。
先读了基线版本的 docs/quota-allocation.md,spec_revision 为 bd607db9c563b263111abdbc37167620e919feb7。按其中 Post-turn accounting protocol 核验:交付身份与 Git 并非同义;显式仓库及隔离要求仍由原 owner 判断;验证及持久写回之后只能结算一次。这里对 originless Git 的范围扩展是明确的修复,不是把所有 Git peer 工作当成本地非交付。
改动思路
复用现有 local_goal 快照与 TypeScript evaluateDeliveryWorkspace 隔离 owner。Python 只观察 Git 和真实路径;没有新增决策源、schema、配置或手工维护字段。做法比要求用户编造 origin 或创建一套新结算协议更小,也避免错误拒绝不断消耗长程工作时间。
普通 Git 原有分支和非 Git 分支保留。新 fallback 同时要求 checkout 根等于注册根、git-dir 等于 common-dir,并且 Git 读取 origin 返回真正的 missing-key 状态。空值、非法 URL、读取失败、外部/嵌套仓库和 linked worktree 都不进入它。
具体改动
workspace_guard.py::_capture_local_goal_workspace抽出旧的非 Git 快照构造,保持 path-free 身份;_git_origin_is_absent区分没有 key 与读取失败;capture_delivery_workspace只增加上述受限分支。state_refresh.refresh_goal_state的既有调用继续把注册项目根和选中 Todo 交给原隔离 owner;显式task_repository或 peer worktree 要求仍拒绝不合格快照。新函数不是新的权限入口。docs/quota-allocation.md披露本地 originless 的新行为及排除项,没有改变一次结算规则。- 两个现有测试文件补注册根/子目录、无注册根、非法/空 origin、外部/嵌套/linked checkout、Git config 失败,以及 legacy/File/SQLite 的真实 CLI refresh → spend → replay。未添加平行 runner。
全 diff 为四文件 +156/-25:生产 +60/-23、文档 +4/-2、验证 +92/-0。未来改动容易局限在已有快照构造与 Git 观察边界;本次已抽出重复构造,没有理由另建框架。
对主干的风险
主要风险是把应隔离的 Git 任务误识别为 local_goal,或拒绝真实独立工作区。已执行六组相关测试,62 passed,覆盖完整 Todo 来源、workspace attribution、当前 claim/lease、跨目录拒绝、恢复和结算因果关系。
独立的不可变 base/head 对照通过实际 Git、typed owner 和生产 CLI 执行:非 Git、正常 origin、非法和空 origin 的快照完全一致;只有 originless 注册根有预期差异。旧版三个 provider 均 guard 成功、refresh 拒绝且零扣费;新版三个 provider 均 refresh 成功、首次 spend 一笔、replay 零新增,下一轮仍选中原 open Todo。无需增加无意义 origin 或重复人工干预。显式 repository 和显式隔离要求的负例仍拒绝;nested/foreign/linked repository 不获得 fallback。
语义 advisory 没有发现 supported 新词汇载体;人工核验是复用既有 local_goal/workspace 枚举,正式 vocabulary drift smoke 和 git diff --check 通过。未读取 CI,遵从此 Goal 的配置。首次测试命令用了不存在的测试文件,未执行任何测试;改为仓库实际文件后上述 62 项通过。独立 probe 首次误要求 replay 必须再次返回 settlement_progress;修正为契约要求的成功且 appended=false,保留原失败记录,没有修改产品或放松扣费断言。
我的整体评价
APPROVE。这是有真实触发条件和恢复证据的完整小修复:减少错误拒绝和重复恢复成本,保留选中 Todo、显式隔离、仓库身份和单次记账边界。长程连续性的这条局部路径正向;没有用一次成功冒充整体可靠性或可量化效率提升。CLI 的错误恢复路径得到修复,前端/Lark 不增加新操作;本机安装采用和全宿主持续运行不在本次验收内。评审结论不提供合并授权。
English verdict: APPROVE - head 397e5eb. The registered originless checkout can settle and continue without fabricating a repository; explicit Git/worktree isolation remains enforced. 62 focused tests, immutable base/head production CLI journeys across legacy/File/SQLite, unaffected-branch snapshot parity, semantic drift and whitespace checks passed. Sustained operation, other hosts and PostgreSQL remain unqualified; CI was not consulted.
A registered local Goal can run in a Git checkout with no origin, but its validated progress previously failed
refresh-stateworkspace attribution. Accept that canonical checkout through the existing path-free local Goal identity when its root equals the registered project root.The Python Git adapter supplies the observation; the existing TypeScript isolation owner still rejects explicit repository or independent-worktree requirements. Invalid/empty origins, failed origin reads, foreign/nested repositories and linked worktrees do not gain this fallback. Normal Git snapshots and non-Git behavior remain unchanged. The shared local snapshot helper removes duplicated construction; no new schema or configuration switch is introduced.
Validation: regression fails on the base; workspace/local settlement suite passes (32 tests), expanded workspace/completion boundary suite passes (53 tests, overlapping coverage). Real CLI journeys cover legacy, File and SQLite refresh → spend → replay with exactly one debit, plus explicit repository rejection. Semantic inventory advisory and full vocabulary drift smoke passed after installing required root npm dev dependencies. Python adapter and existing CLI settlement behavior change; no frontend/Lark interaction or PostgreSQL implementation changes. This bounded S2/S4 continuity repair does not qualify sustained operation or all host surfaces.