Repository navigation
refactor(issue_fix): fold reviewer source trust/freshness vocabularies into one owner - #8826
Conversation
…s into one owner reviewer_recommendation.py restated the trust and freshness sets that repository_context.py already owns. Import both as aliases of the owner objects so the decision has a single source, and add an architecture guard that pins single ownership by value, by identity, and by wiring through both public builders. REVIEWER_SOURCE_KINDS stays local (deliberately narrower). Signed-off-by: psychologister <[email protected]>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent / gpt-6.1-sol / OpenAI / runtime_reported / reasoning effort max
动机 / Motivation
复审提交 682af24,目标主干 8ade78c。这次改动涉及调整 issue_fix 来源信任级别或时效性取值的维护者,以及走两个入口的调用方。此前改一个允许值要同步两份集合,漏改会让工作规划与评审人推荐对同一来源给出不同判定。现在两个入口读同一对象,基线中第二份声明可由新增测试检出。同一隔离 Git 夹具对照 24 个 CLI 输入。九组合法组合、无来源回退及四项非法取值检查的 JSON 与退出码逐项一致。验证仅涉及本地公开入口与合成仓库。真实外发评审请求及仓库全量测试未重跑。
改动思路 / Approach
工作规划既有 repository_context 定义取值,推荐入口只导入同一对象。两个入口继续验证各自的来源结构。本 PR 只收敛 issue_fix 的 trust 和 freshness 两个词表。工作规划通过既有入口验证 source,推荐侧沿同一集合校验后仍按本地证据生成候选。推荐入口自身只接收 maintainer_map,这个条件继续由原校验器负责。该维护改动以 PR 说明和现有 caller 为验收依据。工作规划的校验归属 · 评审推荐入口
具体改动 / Changes
关键代码讲解
- repository_context 持有 TRUST_LEVELS 与 FRESHNESS_STATES。reviewer_recommendation 将原模块名作为 import alias,原 _normalise_reviewer_sources 继续验证字段和值。CLI 传入原格式,成功响应、失败诊断及候选的外发权限字段都保持一致。允许值 · 导入 · 推荐来源验证
- 新测试从三个角度验证变更。扫描覆盖本包的普通 set 字面量,核对实际 import 对象,再用两个公开 builder 覆盖所有合法值和非法字段。把同一守卫放到基线,可检出原重复和对象分离。只在隔离进程内移除 advisory,真实推荐 builder 的全值用例随即失败。定向测试
对主干的风险 / Risks
本地实际运行 reviewer-plan --execute 和 workflow-plan,共比对 24 行成功、缺省及拒绝结果。核对完整 JSON、退出码和诊断。原计划与推荐的字段、排序和权限投影逐项相同。基线 42 项和提交 50 项定向回归全通过。词汇漂移检查输出相同,ruff、编译、diff 与两文件公开边界检查通过。REST 状态显示分支落后于 main,所触及的生产 owner 和消费者在分叉点与当前 main 对应文件相同。
语义与 CI 对齐
本 PR 复用 issue_fix 包内现有闭集。未定义新内核词汇。有效性证据来自上述本地检查。原词表
我的整体评价 / Verdict
通过当前提交的代码审查。两个入口复用同一校验词表,减少再改取值时需要同步的地方。真实入口的成功、失败与默认回退保持原行为。定向验证覆盖本次变更的输入和值域。验证仅涉及本地公开入口与合成仓库。真实外发评审请求及仓库全量测试未重跑。
English verdict: APPROVE. Both issue_fix callers now use the existing vocabulary owner. All 24 matched CLI outcomes preserve the current behavior.
Goal And Delivered Outcome
loopx/capabilities/issue_fix/repository_context.pyowns the closedtrust/freshnesssets every issue_fix source payload is validated against.reviewer_recommendation.pyrestated both under its own names (REVIEWER_SOURCE_TRUST_LEVELS,REVIEWER_SOURCE_FRESHNESS_STATES), so one vocabulary decision had two owners and a drift would let the two validators disagree about the same fields.reviewer_recommendation.pyimports both as aliases of the owner objects, and a new census guard fails if any second definition reappears (see theunitandregression_parityrows).main.Author Declaration
Implemented against
loopx/capabilities/issue_fix/repository_context.py(TRUST_LEVELS,FRESHNESS_STATES);reviewer_recommendation.pyaliasestests/architecture/test_issue_fix_source_vocabulary_owner.pytests/architecturesuite on both a pristine base worktree and the head worktree and compared failure sets; ran three mutations against the guard; ran ruff, the public-boundary scan, and the semantic-vocabulary drift smoke. Deliberately leftREVIEWER_SOURCE_KINDSlocal (narrower than the owner) and did not touch the same freshness triple inreward_memory/candidate_review.py(a different capability).Scope And Continuation
reward_memory/candidate_review.pyfreshness triple is a separate capability and a possible future convergence, not part of this slice.Validation
unitpassedpython -m pytest tests/architecture/test_issue_fix_source_vocabulary_owner.py— 8/8 passed; census-by-value, identity, and wiring through both public entry functions, with positive and negative controls.regression_paritypassedtests/architecturebase 2 failed / 1842 passed, head 2 failed / 1850 passed; issue_fix subset base 2 failed / 359 passed, head 2 failed / 367 passed. Failure sets byte-identical (pre-existingtest_content_digest_single_owner,test_posix_flag_portability, andtest_issue_fix_maintainer_correction_admission::test_t06_stopped_goal_refuses_at_effect_time[file/sqlite]); the +8 are the new guard. Three mutations each caught: restored literal copy → census + identity; renamed copy → census only; divergent reviewer set (dropsadvisory) → identity + wiring while census stays green.staticpassedpython -m ruff checkclean on both changed files; the new guard isruff format --checkclean. The production file was already format-dirty on base; this change is format-neutral and does not reformat it.real_entrypointpassedloopx check --scan-path <changed files>reportspublic boundary scan clean: 2 files; the unrelated registry-goal error reproduces identically on the pristine base.integrationpassedpython examples/semantic-vocabulary-drift-smoke.pyreportsokwith byte-identical output between base and head; the two sets are not registered kernel vocabularies, so no ratcheted budget moves.staticnot_runmypyis not installed in the local environment; neither changed file is in the pinned mypy scope, so the CI mypy gate is unaffected._normalise_reviewer_sources); the guard exercises both public builders across the full owner cross-product and rejects out-of-set values. The fulltests/tree was not run locally — scope wastests/architecture(complete) plus the issue_fix capability subset; the two pre-existing failures are unrelated and reproduce on the pristine base. No UI impact.Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
Boundary Checklist
none.Signed-off-bytrailer (git commit -s).