Repository navigation
[finding][lint] After #6381 converged the view ladder, two SMALLER helpers are still triplicated across the same view-walking rules — collectionEntries and the objectName -> object -> data.object binding ladder #6662
Description
Activity
Findings-round routing repair:
domain:devxappended —findinggrade untouched, no ownership taken.- Landing: both triplicated helpers live in
packages/lint(collectionEntriesverified atvalidate-form-layout.ts:79/validate-translatable-sections.ts:139onorigin/main@04476e7) ⇒domain:devx, same lane as lint: 视图容器阶梯遍历在 packages/lint 内已有三份实现,彼此按不同判据取舍 #6381/PR refactor(lint): converge the three view-container ladder traversals onto one shared walker (#6381) #6657 which spawned this. - The card's own window stands: natural convergence point is after lint:
collectViewRecord的 listViews/formViews 分支收「map key + 内层 name」两种拼写,而组装器只认 map key —— 冲突改名时两者恰好相反 #6422 is decided (one of the three binding copies lives in that card's held file) — grading should wait for that, which is exactly why this staysfinding.
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- Landing: both triplicated helpers live in
Findings triage round: PROMOTED —
finding→pm:queue(labels changed with this comment, read back clean).The 08-08 hold's restart condition has fired: #6422 closed completed 2026-08-08T23:40Z, so the file any convergence must touch (
validate-translation-references.ts) is no longer held. Per the post-unlock discipline, the card's file face was re-verified on the post-merge ref (origin/main@3e8e669) — the unlocking work did not absorb this card:collectionEntriesstill at three copies:validate-form-layout.ts:81,validate-translatable-sections.ts:143,validate-visibility-predicates.ts:290;- the binding ladder still at three copies:
boundObject(validate-form-layout.ts:142),viewObjectName(validate-translatable-sections.ts:130,validate-translation-references.ts:407).
The card's own convergence window is now open: descent (already shared via
view-walk.ts), ladder, andcollectionEntriescan move together in one pass over the same file set. Dedup: repo-wide search forcollectionEntriesreturns only this card; no open PR touches the three files for this purpose. Notarget:label — internal lint refactor, not RC-blocking by the four-category test.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-project-manager commented
on Aug 10, 2026 CollaboratorAuthorMore actionsClaim — devx PM seat, session
session_01F8q5J1MQyocgtNspb15fSn, branchclaude/issue-6662-lint-helper-convergence.Dispatching to an
os-devagent. Two blockers checked before claiming, since this card spent two triage rounds on hold:- lint:
collectViewRecord的 listViews/formViews 分支收「map key + 内层 name」两种拼写,而组装器只认 map key —— 冲突改名时两者恰好相反 #6422 is closed completed (2026-08-08T23:40Z), sovalidate-translation-references.tsis no longer held. Triage's 23:24Z comment already re-verified on the post-merge ref that the unlocking work did not absorb this card. packages/lintis now free. [lint] validate-expressions 的 script 退役键提示仍说 "rewrite it" — #6856 house 句式的最后一个域外站点 #7030 / PR fix(lint): validate-expressions script tombstone 采用 house 版os migrate meta句式 (#7030) #7108 landed onmainas5087ac635a few minutes ago. This card and lint:validate-flow-trigger-readinesscites a live example-app instance that #6882 just removed — plus the deferred question of whether the wider absent-triggerTypecriterion should now ship #7041 were both held out of dispatch while that was in flight to avoid two agents in one package; that constraint is now lifted.
Landing sites re-verified on current
origin/mainbefore dispatch — both helpers still at three copies each, matching the card and triage:file collectionEntriesbinding ladder validate-form-layout.ts✅ ✅ ( boundObject)validate-translatable-sections.ts✅ ✅ ( viewObjectName)validate-visibility-predicates.ts✅ — validate-translation-references.ts— ✅ ( viewObjectName)⚠️ Line numbers in this card have now drifted twice (validate-translation-references.ts: 347 in the body → 407 in triage's re-verification), which is the third instance this round. The implementer is told to locate by content and never by line number.If an earlier claim comment with a different session ID exists above this one, that claim wins and this one should be treated as withdrawn.
Generated by Claude Code
- lint:
os-project-manager commented
on Aug 10, 2026 CollaboratorAuthorMore actionsLanded on
mainas58451f3b3via PR #7186. Card auto-closed on theFixesline; clearing the stalepm:dispatched.Artifacts verified in
origin/main:packages/lint/src/collection-entries.tsexists,view-walk.tsexportsviewObjectName, and the PM's pre-dispatch-style scan of the four consumer files shows zero local definitions remaining — all three copies of each helper folded, none left behind, which was this card's one hard constraint.Three things from the delivery worth the record:
- The semantic-equivalence proof did the hard case honestly. The real divergence was sharper than the card described — the visibility copy's map guard lacked the
!Array.isArray(v)clause entirely, not just theisRecspelling. Proven two ways: structurally (the array branch returns unconditionally, so the guard only ever sees non-arrays, making the clause trivially true at that point) and empirically (a 35-input differential probe over both bodies transcribed verbatim fromorigin/main, identical output). And the epistemics held: the probe's first run reported 5 false mismatches from a bug in the probe itself — the implementer fixed the probe, not the claim. - The refactor-grade differential was falsified before it was trusted. 10,080 runs / 11,624 findings byte-identical — but first, the harness was shown capable of going red: dropping the shared
data.objectrung reddened 3 of 4 differentials while visibility-predicates correctly stayed green (it consumes no binding), the exact asymmetry the design predicts. An honest negative was also recorded:validate-translatable-sections.test.tshad no map-shape pin of its own and did not go red under that break — the new cross-rule table test is what now covers that column. - Composition survived convergence. Only the base rung moved; each rule's own fallback chain (
?? containerObject,?? recordObject ?? listBinding) is untouched, which is what refactor(lint): converge the three view-container ladder traversals onto one shared walker (#6381) #6657 deliberately preserved and this card required.
Changeset:
skip-changesetaccepted over the dispatch brief's default — argued from AGENTS.md's own scope (feature/functional improvement), a measured zero-behaviour delta, zero new exports in the builtdist/*.d.ts, and PR #6657's precedent on the same package for the same class of change.This closes the two-helper residue #6381 left behind; the descent, the ladder, and
collectionEntriesnow live in one place each.
Generated by Claude Code
- The semantic-equivalence proof did the hard case honestly. The real divergence was sharper than the card described — the visibility copy's map guard lacked the
- added a commit that references this issue
on Aug 17, 2026
Filed unassigned from #6381 / PR #6657. Record only — no commitment to a fix.
Observation class: nothing a user hits today. All copies agree, and the PR that
found them deliberately did not fold them in, for reasons given below.
Facts, measured at
3e028ce37(the #6381 branch, post-convergence)#6381 converged the "views[] entry to its real form/view sites" descent onto
one shared walker (
packages/lint/src/view-walk.ts). Two smaller helpers used bythe very same rules were left at three copies each.
1.
collectionEntries— 3 copies. Coerces a collection authored either as anarray or as a name-keyed map into records carrying their config path.
validate-form-layout.tsvalidate-translatable-sections.tsvalidate-visibility-predicates.tsSemantically identical. Not byte-identical: the visibility copy open-codes
!!v && typeof v === 'object' && !Array.isArray(v)inline where the other twocall a local
isRec. Each carries its own docblock making the same argument(findings are edit targets, so a map-shaped collection must not report a
synthetic index) —
validate-form-layout.ts:76even says out loud "Same helper,same reasoning as
validate-visibility-predicates.tsandvalidate-translatable-sections.ts", i.e. the duplication is alreadyacknowledged in-tree.
2. The view binding ladder
objectName -> object -> data.object— 3 copies.Byte-identical bodies, two different names:
validate-form-layout.tsboundObjectvalidate-translatable-sections.tsviewObjectNamevalidate-translation-references.tsviewObjectNameThe card that spawned this (#6381) named the binding resolution as "three
spellings" and correctly excluded
lint-view-refs.ts's deeper ladder(
name -> id -> object -> list.data.object -> form.data.object) as reasoneddifference rather than drift. These three are the other kind: the same four
lines, three times.
Note what does NOT differ: only the base ladder is duplicated. How each rule
composes it differs on purpose (form-layout falls back to the container;
translatable-sections falls back to the container and then to the default
list's binding), and #6657 preserved that deliberately.Why #6657 did not fold them in
Two reasons, both worth keeping on the record:
the descent". A refactor whose entire evidentiary claim is "verdicts are
byte-identical" is worth more when its diff is exactly the thing it claims to
have merged.
validate-translation-references.tsholdscollectViewRecord, and lint:collectViewRecord的 listViews/formViews 分支收「map key + 内层 name」两种拼写,而组装器只认 map key —— 冲突改名时两者恰好相反 #6422 isheld in the maintainer decision box with that file as its subject. Any
convergence that reaches all three copies has to touch it. Folding two of
three would reproduce the exact shape lint: 视图容器阶梯遍历在 packages/lint 内已有三份实现,彼此按不同判据取舍 #6381 exists to prevent — the next
author fixes one copy and leaves another behind.
So the natural window for this is after #6422 is decided, at which point the
descent, the binding ladder and
collectionEntriescan move together, in onepass over the same set of files.
Why record it at all
#6381's own signal argument applies unchanged: the ladder there was found broken
in two different files in two consecutive issues, and the copy count was the
evidence a single source was owed. These two helpers have the same copy count
and the same consumer set. Recording them now means the next person to open one
of these files sees the other two, which is the cost this class of finding is
about.
Refs: #6381 / PR #6657 (the descent, converged), #6422 (held — blocks the
binding-ladder half), #6248 / #6251 / #6128 (the two-time hole that made the
case), #3583 (
page-walk.ts, the shared-walker precedent).