fix(repo): point live surfaces at the canonical repository - #4776
Conversation
b0d0a5e to
fffa423
Compare
|
Rebased-free rewrite pushed as fffa423: the |
The one red test is reproduced on clean
|
|
Correcting the scope of my previous comment, because I have now read every shard's JUnit artifact for this run rather than one:
|
|
Closing the loop on my two comments here, because the answer turned out to be neither "pre-existing on macOS only" nor "shard ordering": it is a calendar.
Filed with the full bracketing as #4797 and fixed test-only in #4798 ( |
The organization migration moved the project to loopx-project/loopx, and GitHub's redirect meant nothing failed loudly while shipped defaults, projected documentation links, monitored connector targets and copied command examples kept handing out the pre-transfer address. Dated citations (pull/issue numbers in prose) are left alone: they record the address the event happened under. Signed-off-by: DJC1412 <108855841+DJC1412@users.noreply.github.com>
STRONG_TERMS named only the pre-transfer owner and repo URL, so a mention of the canonical loopx-project/loopx address was graded weak: the provider downgraded this project's own current pages. Both addresses are strong now, and the smoke pins the current form, the archived form and a noise term in one pass. Signed-off-by: DJC1412 <108855841+DJC1412@users.noreply.github.com>
Code, scripts, workflows and package surfaces must carry the canonical repository address; prose may still cite the historical one, the provider disambiguation list must match both, and the packaged chat bundle is excluded because it is a build product fixed by rebuilding. Signed-off-by: DJC1412 <108855841+DJC1412@users.noreply.github.com>
fffa423 to
805dab5
Compare
|
Status of the red here, with the numbers, so nobody has to re-derive it. The head is now rebased onto current
|
huangruiteng
left a comment
There was a problem hiding this comment.
评审结论:REQUEST_CHANGES
评审 head:805dab5e22b0eb5148e4408a93f58836eb230c20
阻塞项
-
[P1] 新增的 repository-hygiene guard 没有覆盖它自己刚修正的两个 package README,而且 live/history 判断依赖文件内容而不是文件路径。
LIVE_PACKAGE_MARKERS不包含 README,因此_is_checked_surface("packages/dsh-loopx-plugin/README.md")和_is_checked_surface("packages/loopx-community-discussion/README.md")都返回False。也就是说,把本 PR 修正过的 DSH release-download 安装命令或 community-discussion 扫描命令重新改回旧 owner,新增 guard 仍然不会报错。同时,
_stale_live_pointer()只接收 contents,却用text.endswith((".md", ...)) or "/README" in text猜测它是不是 prose。精确复现中,同一个https://github.com/huangruiteng/loopx/releases/download/...字符串,仅仅因为前面多了无关的/README文本,就从“offender”变成“允许的历史引用”。而/releases/download又被整个放进HISTORICAL_CITATION_RE,会把这个 PR 明确认定为 live install command 的链接也当历史材料放行。这不满足 #4753 maintainer intake 要求的“显式 live surfaces / reviewed allowlist”,并且让“防止 residue 再长回来”的交付结果仍然不成立。最小修复:把
name与 contents 一起交给 classifier;显式纳入这两个 README/安装命令;按 path + use 建立小型 reviewed exception table;用 mutation case 证明旧 DSH release URL 会被点名、合法历史 PR citation 不受文件内其它文字影响。 -
[P2] relevance smoke 缺少 maintainer 明确要求的 generic weak 行。
_pre_and_post_transfer_addresses_are_both_strong()当前只钉住 canonical strong、archived strong 和 loopear noise。由于本 PR 新增了较宽的loopx-projectsubstring,应该同时钉住“title/url/text 均不含 identity 或 noise”的普通事实仍返回非空weak。我在 base/head 对比里验证当前实现确实保留了 weak,但这个约束还没有进入 durable smoke;请补上第四行,避免未来扩展 strong terms 时把无关事实静默抬成 strong。
动机
这个 PR 解决的是一次被 GitHub redirect 掩盖的真实迁移残留:first-run、agent onboarding、machine configuration、value connector、package examples/metadata 继续对外发旧地址;更重要的是,community-discussion 只认识旧 owner,导致项目自己的 canonical URL 被判为 weak。这个问题及边界由 #4753 和 maintainer intake 明确确认,历史 PR/issue/commit 引用、DSH 已安装 identity filename、generated chat bundle不应被 blanket rewrite。
从结果看,运行时字符串与 relevance 行为的主体修复是成立的;当前缺口集中在“以后不能再退化”的 guard 本身,而不是 URL 替换方向。
改动思路
实现复用了正确的现有 owner:
- 各现有 runtime/configuration/package surface 只改自己的输出字面量;
normalize.py仍是 discussion relevance 的唯一决策点,同时保留旧地址作为历史 alias;community_discussion_smoke.py扩展现有 offline contract smoke;examples/repository-hygiene-smoke.py扩展现有仓库卫生检查,没有再建第二套检查器。
正向路径是:现有 caller 发出 canonical URL → classify_relevance 在 noise precedence 后匹配 canonical term → make_fact 保存 strong → scan/render consumer 得到正确输出。负向/维护路径应是:tracked path + URL use 被显式分类 → live old address 报出具体文件 → reviewed historical citation 保留。当前负向路径把 path 信息丢掉了,所以 classification 既漏了 live README,也会随无关 contents 改变。
具体改动
- 15 个文件,
+155/-29。 - production/runtime:first-run issue URL、onboarding source repository、两类 machine configuration documentation URL、十个 configuration catalog URL、两个 value connector targets。
- provider behavior:
STRONG_TERMS增加 canonical organization/repository,保留huangruiteng和旧 URL alias。 - public package/docs:DSH package metadata/release command、community-discussion commands/request、repo-health request、benchmark toolkit links。
- validation:新增 transfer-address smoke,以及 81 行 repository hygiene selector/classifier。
关键代码讲解
normalize.py::classify_relevance(约 35 行)保持 noise-first 顺序;相同四行 fixture 的 base/head 对比为:canonicalweak -> strong,archivedstrong -> strong,genericweak -> weak,noisenoise -> noise。这是预期且有价值的唯一行为变化。repository-hygiene-smoke.py::_is_checked_surface(约 52 行)决定 guard 的覆盖全集。它包含所有loopx/**,但 package 侧只选/src/、package.json、request 和 smoke,遗漏本 PR 自己改变的 live README。repository-hygiene-smoke.py::_stale_live_pointer(约 64 行)本应决定 live pointer 与 historical citation,实际却没有 path 入参,prose由 contents 偶然决定;这正是 P1 的错误 owner/boundary。community_discussion_smoke.py::_pre_and_post_transfer_addresses_are_both_strong(约 83 行)覆盖两个 alias 与 noise,但遗漏 intake 指定的 generic weak regression。
对主干的风险
主体 URL 替换风险较低:未新增 API、状态、CLI 或 authority,都是既有 caller 的 string/default 修正;静态 JSON 可解析,changed Python 可编译,配置/onboarding/value-connector focused tests 全绿。旧 URL 继续作为 discussion 历史 alias,兼容性方向正确。
最大风险来自错误的“已守住”信号:当前树通过新增 canonical validator 并不能证明未来 mutation 会失败。exact-head probe 已证明两个 changed README 根本不在 scan set 内,而且同一 release URL 可因 contents 里出现 /README 被豁免。blast radius 是未来用户继续复制旧安装/scan 命令,同时维护者以为 CI 已覆盖;另一侧则可能把合法历史 citation 当 stale live pointer,形成噪声红灯。
语义与 CI 对齐
现行 acceptance 来自 #4753 maintainer intake:显式 live surfaces 或 canonical owner、reviewed historical exceptions,以及 canonical strong / archived strong / generic weak / noise 四行矩阵。当前 exact head 在 guard 覆盖与四行 durable regression 上未完全对齐。
本地验证(按 packet,未读取/等待远端 CI):
community_discussion_smoke.py:通过;- 组织 identity、machine configuration、capability UI/defaults、manager/steward、value connector、agent onboarding:61 passed;
- identical base/head relevance matrix:预期的
weak,strong,weak,noise -> strong,strong,weak,noise; - changed Python
py_compile、3 个 JSON parse、git diff --check:通过; - full
repository-hygiene-smoke.py:先通过本 PR 新增 canonical validator,随后仍在主干既有v1.1.0release-timeline 缺口失败;这个 baseline failure 已由 issue/PR 正确披露,我没有把它归因于本 diff,也没有把它隐藏或降级。
我的整体评价
这是一个目标明确、范围基本合适的迁移修复:现有 owner 复用合理,runtime/package 输出和 relevance 行为确实改善,历史 alias 也被保留。没有必要另造 repository-identity 框架;未来向的最有价值小重构,就是让现有 hygiene guard 直接持有 path-aware 的 live/history 语义,而不是继续扩大 substring/content heuristic。
因此我暂不批准。修复 P1、补齐 generic weak regression,并在同一 exact head 重新跑 provider smoke、focused tests、README mutation + historical citation 两个 guard counterfactual 后,可以做完整复审。
English verdict: REQUEST_CHANGES - head 805dab5; the canonical URL and relevance fixes are valid, but the new hygiene guard excludes both changed package READMEs and derives live-vs-history from incidental file contents, so the exact stale install pointer can regress undetected. Add path-aware coverage and the missing generic-weak regression; focused local validation otherwise passed (61 tests plus the offline provider smoke).
The first cut guessed whether a file was prose from its own contents, so an install command could be excused by unrelated text sharing the file, and the package READMEs whose install commands this branch fixed were not covered by the guard at all. Liveness now comes from where a file is, and each occurrence is classified by the path segment that follows the address: repository, issue_form, discussion, release_asset and main_pointer are live, a numbered issue or pull citation is historical only where that path and use are in the reviewed table. Five cases inside the smoke pin the classifier itself, including that a pull citation stays tolerated beside a line mentioning a README, and that the same shape is still a live address in a product module. Also pins a fact with no project identity as weak, so widening the disambiguation terms cannot silently promote unrelated discussion. Signed-off-by: DJC1412 <108855841+DJC1412@users.noreply.github.com>
|
两处都按建议改了,head P1:guard 不再从文件内容猜"这是不是 prose",也不再漏掉它自己修过的 README。
P2:补了第四行。 复验:provider smoke 离线通过; |
|
@huangruiteng both review points are addressed on Current CI here is 10 passed / 11 pending / 0 failed — the four
Everything in this PR's own scope is green: the canonical-pointer guard with its five classifier assertions, the package smokes, and the 573 tests across the 31 modules this diff touches. |
huangruiteng
left a comment
There was a problem hiding this comment.
复审结论:APPROVE
评审 head:38cf0b9afb9d83ee920764db365fb0ab1118d290
上一轮在 805dab5e22b0eb5148e4408a93f58836eb230c20 提出的两个阻塞项已经按其语义边界修复,而不是只让当前 fixture 变绿:
- 原 P1 的 hygiene guard 现在以 path + 单个 URL occurrence 的 use 为决策输入。
_is_live_surface()会覆盖整个packages/,仅排除明确声明的 generated bundle;_address_use()把每个旧地址分别分类为 repository / issue / issue_form / release_asset / discussion / main_pointer / branch / pull / commit 等 use;只有REVIEWED_ADDRESS_EXCEPTIONS[exact_path]中明确允许的 use 才能保留。无关 prose 不再影响结论。 - 原 P2 的 relevance smoke 已补上 generic row,并明确要求它返回非空
weak。当前矩阵完整覆盖 canonical strong、archived strong、generic weak、loopear noise dropped。
动机
这个 PR 修的是 repository transfer 后被 redirect 掩盖的两类真实问题:一类是 first-run、onboarding、machine configuration、value connector 和 package command/metadata 仍向用户或工具发出旧 owner 地址;另一类是 community-discussion 能识别旧地址,却把项目自己的 canonical URL 判成 weak。
目标不只是做一次字符串替换,还要避免同一类 residue 再长回来,同时不能因为全仓 substring denylist 把历史 PR/issue/commit citation、provider 的 archived alias 或 generated bundle 一并破坏。当前 head 已经把这三个边界——live、reviewed history、generated output——落成可观察规则。
改动思路
实现继续复用现有 owner:
- 各 runtime/configuration/package surface 只改自己发出的 public literal;
packages/loopx-community-discussion/.../normalize.py仍是 strong/weak/noise 的唯一决策点,并保留 pre-transfer identity 作为历史 alias;community_discussion_smoke.py固化四行 relevance matrix;examples/repository-hygiene-smoke.py作为已有 repository maintenance gate,按 tracked path 与 URL use 检查旧地址。
正向路径是:caller 发出 loopx-project/loopx → provider 在 noise precedence 后匹配 canonical term → make_fact 保存 strong → scan/render consumer 得到正确输出。
负向路径是:tracked live path 包含旧地址 → OLD_ADDRESS_RE 枚举每次 occurrence → _address_use() 只根据该 URL 的 suffix 分类 → exact path/use exception 未命中 → validator 点名文件和 use 并失败。这里已经没有“同一文件里恰好出现 /README 就把 release asset 当历史材料”的内容耦合。
具体改动
- 全 PR:15 files,
+248/-29。 - production/runtime:first-run issue URL、agent onboarding repository、machine configuration documentation URLs、configuration catalog URLs、value connector targets。
- provider behavior:canonical organization/repository identity 变成 strong;旧 owner/address 继续作为 archived alias;noise-first 与 unmatched-weak 默认不变。
- public package/docs:DSH metadata/release command、community-discussion commands/request、repo-health request、benchmark toolkit links。
- maintenance coverage:全 live-prefix inventory、generated prefix exclusion、occurrence-level URL use classifier、exact path/use exception table、counterfactual assertions和四行 provider matrix。
- 相对上一轮评审 head,新增修改只在两个 smoke 文件,
+139/-46,直接关闭 P1/P2,没有扩张到新的 runtime framework。
关键代码讲解
repository-hygiene-smoke.py::_is_live_surface(line 58)只读 path;packages/的 README 因此和 source/request 一样进入 scan,generated chat bundle 则由单独 prefix 排除。_address_use/stale_address_uses(line 64/96)把 occurrence 的 suffix 转成窄 use token,并以 exact path exception fail closed。未知新 use 默认不会被放行。normalize.py::classify_relevance(line 35)保持 noise → strong → weak 的顺序;唯一有意行为差异是 canonical identity 从 weak 变 strong。community_discussion_smoke.py::_pre_and_post_transfer_addresses_are_both_strong(line 83)现在同时钉住 canonical strong、archived strong、generic weak 和 noise dropped,补上上一轮漏掉的 false-positive boundary。
对主干的风险
生产风险较低:没有新 API、持久状态、CLI option、scheduler、quota、permission 或 authority contract;大多数生产 diff 是现有 consumer 的 literal 修正。兼容性方面旧 repository identity 仍是 provider strong alias,reviewed historical pull citations 仍可保留。
主要维护风险是显式 exception inventory 需要随新的 intentional history 更新;但这会 fail closed 并在 CI 中暴露为可评审噪声,优于 silent drift。LIVE_ADDRESS_USES 当前未被消费,是一个可删的小 cleanup,但不形成第二套 authority,也不改变行为,我不建议为它再次扩大本 PR。
远端 CI 目前还不是 merge-ready:test shard 2 的 maintainability ratchet 已在当前 main 失败;shard 3/4 是 7 天后过期的 Lark absolute-date fixture,#4798 在 clean origin/main 复现 2 failed, 49 passed 并提供修复。pytest 和 merge-gate 是这些 shard failure 的传递结果。它们不由本 diff 引入,因此不构成本次 code-review blocker,但本次批准不豁免这些门禁,也不授权合并。
语义与 CI 对齐
当前 head 与 #4753 maintainer intake 及上一轮 P1/P2 repair contract 对齐:live surface 由 path 决定;旧地址是否允许由 occurrence use + exact path exception 决定;relevance 必须保持 canonical strong / archived strong / generic weak / noise dropped。没有用 author prose 替代机器证据。
本地 exact-head 验证:
community_discussion_smoke.py:通过;- 直接调用
validate_canonical_repository_pointer():通过,并执行 old release asset / reviewed pull citation / product-code pull / blob-main / generated asset / DSH README 六类 counterfactual; - organization identity、capability configuration UI/defaults、machine configuration、change quality、value connector、agent onboarding、chat machine/goal configuration:95 passed in 22.02s;
git diff --check origin/main...HEAD:通过;git merge-tree --write-tree origin/main HEAD:通过;- review result 按 policy revision 7 校验:
approval_consistent=true,无 blocker。
我的整体评价
这是一个范围完整且可回滚的 repository-transfer 修复。上一轮最关键的问题不是“README 又漏了两个”,而是 guard 把 path 语义丢掉后,用 contents 猜 live/history;当前修复已经把 decision owner 放回 path/use boundary,并用反例固定。generic weak 也进入 durable smoke,避免 canonical strong term 未来继续扩张时静默抬高无关事实。
Future-facing pass 的结论是无需再建 repository identity abstraction:现有 caller owner、provider owner 和 hygiene owner 已足够清晰。当前 PR 可以批准;合并仍应等待或重新评估远端基线门禁,不在本次 review 中绕过。
English verdict: APPROVE - head 38cf0b9; both prior blockers are resolved at their semantic boundary: the hygiene guard is path/use-aware with exact reviewed exceptions and mutation-sensitive counterfactuals, and the provider smoke now pins canonical strong, archived strong, generic weak, and noise dropped. Exact-head local validation passed (95 focused tests, both smokes/validators, diff check, and clean merge-tree); current remote shard failures reproduce on main or are covered by #4798, so they remain a merge-readiness hold rather than a finding in this diff.
Goal And Delivered Outcome
loopx-project/loopx, and most surfaces followed (README, workflows, the Tauri config, the hosted site,scripts/install-from-github.sh,self_update.DEFAULT_UPDATE_REPO) — but the addresses a shipped build hands out did not: the first-run report link, the onboarding projection, thedocumentation.urltwo machine-configuration namespaces project into CLI and Dashboard, two monitored connector targets,configuration_catalog.py's ten doc pointers, and copied command/package metadata. GitHub's redirect is why none of it failed loudly. One of them was a behavior bug rather than a stale link:loopx-community-discussion'sSTRONG_TERMSmatched only the pre-transfer owner and repo URL, so a mention of the project's own current address was gradedweak.make_fact(source_url="https://github.com/loopx-project/loopx/issues/7", …)returnedrelevance: "weak", relevance_reason: "no explicit project disambiguation term"— the exact string the mutation run below reproduces; after, both the current and the archived address classifystrong, and aloopeartitle is still dropped. Proven by theunitandregression_parityrows.main.Scope And Continuation
blob/main/tree/maindocument links and 30 bare identity mentions still sit underdocs/**,docs/book/**and the hosted blog HTML; 431/pull/N,/issues/N,/commit/shaand/releases/download/tagcitations were measured and deliberately left as historical record. Also untouched with a reason:packages/dsh-loopx-plugin'sdata/plugins/huangruiteng__loopx--packages-dsh-loopx-plugin.ymlfilename is derived identity in already-installed state, so it needs a migration decision, not a rename; andloopx/web/chat/assets/index-*.jscarries a baked-inblob/mainlink, which a rebuild fixes — hand-editing minified output does not.docs-governancelink check is the shape I would take). No new follow-up issue is filed; [Task]: Live surfaces and one relevance oracle still carry the pre-transfer repository address #4753 carries the counts.Validation
805dab5e2(rebased on currentmain; the focused rows were re-run on this head and the earlier revision note below stays as the record of where each was first measured)unitpython3 packages/loopx-community-discussion/smoke/community_discussion_smoke.py→ok: offline contract smoke passed, including the new case that pins current-addressstrong, archived-addressstrongandloopearnoise dropped.unitpython3 -m pytest -q <31 test files matching the touched modules>→ 573 passed, covering first-run report, onboarding,configuration_catalog, machine-configuration contract/UI/goal-defaults, change-quality and connector consumers.staticpython3 examples/repository-hygiene-smoke.pyreaches and passesvalidate_canonical_repository_pointer(see the coverage row for the one check that fails independently of this diff).staticpython3 -m py_compileover every changed Python file; the three changed JSON files re-parse.regression_parityloopx/agent_onboarding.pymakes the new check fail with the offending path listed. (2) Removing the two addedSTRONG_TERMSentries makes the provider smoke fail withrelevance: "weak", and the hygiene check then fails on the dropped disambiguation address — so both halves of the fix are load-bearing rather than cosmetic.manualloopx check --scan-path examples/repository-hygiene-smoke.py --scan-path loopx --scan-path packages→ public boundary scan clean (1294 files), 7 non-literal credential-reference hits downgraded as expected by the scan's own classifier.staticexamples/repository-hygiene-smoke.pyalso failsvalidate_release_timelinewithrelease timeline is missing version entries: v1.1.0. Reproduced independently of this PR:git show origin/main:docs/product/release-readiness.mdcontains 0v1.1.0entries, i.e.mainis red on that check since the 1.1.0 release commit. Out of scope here (it needs release evidence only the owner has); reporting it rather than folding a release-docs change into an identity PR.npm run test:control-plane(no TypeScript state rule or effect touched), the hosted-site and desktop build pipelines (only a checked-in built bundle and a package manifest string changed, no source of either), and no live GitHub API call was made to prove the connector targets resolve; issue and discussion numbers are preserved by the transfer redirect.Frontend / Visual Evidence
manager_runtimeandsteward_executorrendered adocumentation.urlundergithub.com/huangruiteng/loopx/blob/main/….github.com/loopx-project/loopx/blob/main/…; no layout, control or state changed, so no screenshot is added — the projection reads the string this PR changes, andtests/capabilities/test_machine_configuration_contract.py/test_capability_configuration_ui.pycover it.Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).