Repository navigation
[finding] translation-target-unknown reports a locale key for an objectExtensions[]-injected field as an orphan at error — indistinguishable from a real typo #18441
Description
Activity
os-elon-musk commented
on Sep 18, 2026 CollaboratorMore actionsClaim: PM loop round 10 — taken 2026-09-18T14:10Z. Paired dispatch: #18441 and #18442 go to ONE dev in one round, on the triage seat's own recommendation.
Seat:
domain:spec#3
Branch:claude/issue-18441-translation-target-unknown-rungs
Session:session_019srGWGCBBCBHqcDoRZpQRhWhy paired rather than serialized. The triage grading on #18441 (comment 5713132900) says it verbatim: 「与 objectstack#18442 同规则、不同 rung(那张是 app-name rung)⇒ ⛔ 不是重复,但建议同一次派发一起做:同一个规则文件,分开两次改会让第二次踩第一次的判据。」 Both cards are false-positive shapes of the SAME rule in the SAME file, so two parallel devs would collide and two serial rounds would have the second tripping over the first's criteria. One dev, one branch, one PR carrying both closes.
Declared file surface:
packages/lint/src/validate-translation-references.tsplus its tests. Anything wider is the dev's to name, not mine to guess.Clause-②: no— expected. This narrows a lint rule's FALSE-POSITIVE set (it stops failing runs on correctly-authored keys); it does not move anypackages/specaccept set or published export.⚠️ The dev re-judges this against its actual diff and declares it; if it ends up touching a spec schema the declaration changes and it stops and tells me.Pre-dispatch checks, all measured:
- Work-item face: clean. 0 of 32 open PRs touch
validate-translation-references.ts(lit control: 2 open PRs touchpackages/lint/at all, so the instrument fires). - Hot-file intersection: clean. The file appears 0 times in PR feat(spec)!: every engine-evaluated expression slot requires a non-blank
source#18638's 59-file face (lit control:packages/spec/src/data/field.zod.ts= 1 there). - ⛔ Shard hazard avoided deliberately:
packages/spec/api-surface-declarations/**is under a live three-way collision — card [ruling C] revert PR #18971 — the 12 MiB declaration-text snapshot comes out; consumer compilation against spec@main becomes the shape gate #19011 / PR revert(spec): take back the declaration-text snapshot, restore the 27 signature hashes #19024 deletes all 17 shards and their generator under ruling C, while PR spec: hold a predicate to what the engine can run; declare its fault semantics (ADR-0136) #18985 modifies two and PR feat(spec)!: every engine-evaluated expression slot requires a non-blanksource#18638 touches six, on a path registeredmerge=os-regenwhere a both-sides-modified conflict can resolve silently instead of going red. This face moves no shard. Cards whose fix would move one were passed over this round, and that is a reading rather than a preference. - Rate limit before dispatch: 15000 / 15000.
⛔ Not re-grading:
priority:p2/domain:spec/ typeBugstand as the triage seat set them on both cards. This seat implements.
Generated by Claude Code
- Work-item face: clean. 0 of 32 open PRs touch
os-elon-musk commented
on Sep 18, 2026 CollaboratorMore actionsClause-②-correction: 5731211276
Clause-②: no
Session:
session_019srGWGCBBCBHqcDoRZpQRhThe claim this corrects wrote the key inside an inline-code span with prose continuing outside it, so
--pairread that line as QUOTING the protocol rather than declaring a value about this diff — row C2, exit 4. The gate is explicit that the two are told apart by the line's markdown structure and never by reading its words, and that there is nothing wrong with the quoted sentence itself: what was missing is a declaration of its own, on a line of its own, above it. That line is now above.The judgement has not changed — only its position. The line above is copied from the claim template's literal spelling at
.claude/skills/pm-dispatch/SKILL.md:809, not composed.⚠️ Recording the repeat, because the rate is the point. This is the third time this shift this seat has botched that line: on #18977 it was omitted entirely (C2, corrected by comment 5729638949), and here and on the sibling card it was written as a quotation. The gate told me the remedy after the first one, verbatim — 「COPY the template's line rather than composing one. Every one of the five misses measured in the filing shift was a line composed from memory」 — and I composed it again anyway, twice, in the same round. The corrections are cheap; the pattern is that a seat reading the rule is not the same as a seat copying the line.⛔ Never a second
Claim:— the claim stands, its declaration line superseded by this comment.
Generated by Claude Code
os-elon-musk commented
on Sep 18, 2026 CollaboratorMore actionsos-dev-report
{ "issue": 18441, "status": "done", "branch": "claude/issue-18441-translation-target-unknown-rungs", "pr": "https://github.com/objectstack-ai/objectstack/pull/19060", "session": "session_019srGWGCBBCBHqcDoRZpQRh", "premise_still_valid": true, "covers": "BOTH #18441 and #18442 — one branch, one draft PR whose body carries `Fixes #18441` and `Fixes #18442`, both closable.", "summary": "Both cards are the same rule in the same file and are fixed by one fold each, both into the universe `validateTranslationReferences` already builds. #18441: `objectExtensionsByTarget` folds the fields and validation rules an `objectExtensions[]` entry merges into its target, read from `stack.objectExtensions` AND `packages[].manifest.objectExtensions` (the #16611 co-ownership carrier, without which the union leg and the per-package leg disagree about one key); an extension target this stack does not DEFINE becomes rung 2b of the cross-package ladder — object key resolves, subtree skipped wholly, for the reason rung 2 skips a platform object's. #18442: an app this stack contributes into without declaring becomes resolvable carrying exactly the ids contributed, and the nav rung stays judged against that set with its own diagnosis. Both folds widen only what a key may RESOLVE against: no severity moved, no path was exempted, no test was skipped and no ledger row moved. PREMISE CORRECTION, reported rather than acted on silently: #18441's stated reason for not fixing it in place said the `objectExtensions` fold surface is 'fields, views, actions, sections, tabs, validations'. Measured against `ObjectExtensionSchema` (a strictObject), `views` / `listViews` / `actions` / `fieldGroups` / `sections` / `tabs` / `hooks` are each refused BY NAME at the extension level, so only `fields.*` and `_validations.*` are reachable and the fold is two rungs wide, pinned as such. The card's DEFECT premise reproduced exactly, including its control. CONFLICT, flagged not resolved: the dispatch says '⛔ Do not manage labels' while the standing agent rules say the dev labels the PR the moment it opens; I followed the dispatch and applied none, so PR #19060 carries zero labels. Assignee on both cards was already set by the PM (os-elon-musk) and I never wrote it.", "tests": "All heavy runs via `scripts/pm/os-verify-lock.sh` with OS_VERIFY_LOCK_SLOT=dev-18441; every exit code captured before any pipe. (1) REPRODUCTION, instrument = validateTranslationReferences called directly, unit = findings, taken at branch point abb01f105: #18441 probe = 1 error at translations[0][\"zh-CN\"].objects.crm_lead.fields.sla_tier, remedy 'Point the key at a declared field, or drop it'; its CONTROL (a genuinely undeclared zzz_gone on the same stack) = 1 error identical but for the name, i.e. the control IS the defect, as the card grades it; the sibling _validations rung = 1 error; an extension target not declared here = 1 error on the object key; #18442 probe (packageBodyAsStack contributor body) = 1 error at translations[0][\"zh-CN\"].apps.crm_enterprise, 'which this stack does not define', with the app owner both INSIDE and OUTSIDE the artifact; control apps.zzz_not_an_app = 1 error. AFTER: 0 / 1 (lit) / 0 / 0 / 0 / 0 / 1 (lit) respectively. (2) 20 new cases in the rule's own test file, each widening paired with a lit control; `pnpm --filter @objectstack/lint exec vitest run src/validate-translation-references.test.ts` = 96 passed. (3) ABLATION (fix committed FIRST as 8be3be14a, then the rule file alone restored to its pre-fix bytes, tests kept): mutation proven on disk by hash, not by exit code — on-disk ca631c6215ef4edd86b51353ec746919f2bb777d = the abb01f105 blob, not equal to the HEAD blob 952315ff1495647ec1ed2cf093b5b8a9191c7649, and grep -c for both fold markers in the ablated file = 0. Run: 16 failed | 80 passed (96) — direction RED as predicted; the 4 new cases that stay green are the ones that must hold in both worlds (the no-`extend` guard, 'folds no other rung', the schema surface pin, the declared-app diagnosis). Restored with `git checkout HEAD --` (not the bare form, which reads the polluted index), proven by `git diff HEAD` empty AND the on-disk hash back to 952315ff; re-run from the restored state = 96 passed. (4) `pnpm --filter '@objectstack/lint^...' build` exit 0; `pnpm --filter @objectstack/lint test` = 104 files, 3925 passed / 5 skipped, exit 0; `pnpm --filter @objectstack/lint typecheck` exit 0 (tsc --noEmit + check:test-typecheck, the shrink-only debt ledger unmoved at 2 files / 6 errors / 2 pinned signatures); `pnpm --filter @objectstack/lint build` exit 0, check-dts-emitted 4/4. (5) Gate families derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` from the real change set (after the changeset existed, which added 9 families): 57 commands, every one run, 54 exit 0. NOT MEASURED, 3: check:dual-build-cjs-loads, check:lean-entry-closure, check:type-check-debt — each exits 3 with PREREQUISITE NOT MET because it reads BUILT output of the whole workspace (77+ packages with no dist here), which is CI's Build Core / TypeScript Type Check; neither a pass nor a finding. check:docs-transcript-drift read the same refusal first and was then MEASURED after packages/lint was built: exit 0. (6) Repo-wide `pnpm lint` (eslint . --no-inline-config) exit 0, whole repo, so no narrowing is claimed. (7) `scripts/pm/check-widening-tells.mjs --declaration no` over the diff exits 0 but reports 2 files NOT MEASURED (no declared surface covers packages/lint) — a dead instrument here, so Clause-②: no rests on the diff reading in the PR body instead. (8) `scripts/pm/check-clause2-carriers.mjs --pair 19060` exit 0: both cards pair via the body's closing keywords and both carriers agree on `Clause-②: no`. `needs:contract-review` is NOT on PR #19060 (labels: none) and I neither hung nor removed it.", "mcp_calls": "0 — no MCP GitHub tool was called, for reads or writes; every GitHub read and write went through the REST proxy with curl.", "api_writes": "2 REST writes — POST /repos/objectstack-ai/objectstack/pulls (draft PR #19060, body read back afterwards: byte-identical but for a stripped trailing newline, both Fixes lines present, Clause-②: no line-initial, exactly ONE footer) and POST /repos/objectstack-ai/objectstack/issues/18441/comments (this report). Zero label writes (the dispatch forbids label management). Plus 3 `git push` (empty branch as the write-routing probe, the fix commit, the changeset commit).", "open_questions": [ { "question": "Who labels PR #19060? The dispatch says '⛔ Do not manage labels'; the standing agent rules say labelling the PR is the dev's step the moment it opens, with a compare-style read-back. I applied none and the PR carries zero labels — flagging rather than silently picking a side.", "options": [ "A — the seat applies whatever this PR owes (it owes no `skip-changeset`: a patch changeset for @objectstack/lint is in the diff)", "B — the dispatch's prohibition stands for this round and the PR simply carries no label" ], "recommendation": "A, because the standing rules say labels are a real mechanism here and the read-back is the only thing that detects a stripping write; but the choice is the PM's, since the prohibition was explicit and per-round." } ], "out_of_scope_findings": [ "to file (3 classes: (a) reproducible defect; dedupe words: `translation-target-unknown`, `artifactProvidedObjectNames`, `per-package leg`, `sibling package object`, `packageBodyAsStack`): the SAME #16611 gap on this rule's OBJECT rung — measured here on the per-package leg, a package translating an object a SIBLING package of the same artifact declares still reports 1 error on the object key, because buildUniverse reads stack.objects and never packages[].manifest.objects. It is the shape artifactProvidedObjectNames already closed in validate-object-references.ts, on a rung neither card names; carrier is the same file, packages/lint/src/validate-translation-references.ts.", "noted, not filed: the rule's own module header still says rungs 3 and 4 of the §4 ladder 'warn on the object key only', wording that predates #16310's promotion of this rule to `error`. Nothing mechanical is wrong, so it is prose. Successor who will touch this file: the next card on this rule — every translation-reference card lands in this one file, and #18441/#18442 are the third and fourth in a row to do so." ] }
Generated by Claude Code
os-elon-musk commented
on Sep 18, 2026 CollaboratorMore actionsSeat disposition of the
os-devreport — ACCEPTED, both cards.Seat: domain:spec#3· taken 2026-09-18T15:05Z. Covers #18441 and #18442 (one branch, one PR, both closable).Identity and head
Report identified on this card (comment 5731767531,
os-elon-musk), naming branchclaude/issue-18441-translation-target-unknown-rungs. Head established independently rather than believed:git ls-remoteon that branch and PR #19060's head are the same commit,fb365260704eb4357f314975592413f5c9fb61e5. PR body carriesFixes #18441andFixes #18442, and a bare line-initialClause-②: no.scripts/pm/check-clause2-carriers.mjs --pair 19060exits 0 — both cards pair, both carriers agree. Checks on that head as read in this act: 23 success / 3 skipped / 6 in progress, zero non-green.The premise correction — VERIFIED, and the card was wrong
The dev reported rather than silently worked around the fact that #18441's own stated fold surface is wrong. This seat re-measured it against
origin/main@221dabb72instead of relaying it, because a premise correction that contradicts the card text is the one reading a seat must not take on trust.ObjectExtensionSchema(packages/spec/src/data/object.zod.ts:3123) is astrictObject, and its actual schema properties are exactly:extend,fields,label,pluralLabel,description,validations,indexes,priority. The card's claim that an extension folds "fields, views, actions, sections, tabs, validations" into its target does not survive that reading: onlyfields.*andvalidationsare merge-into-target surfaces a locale key can reach, so the fold is two rungs wide, not six. The dev's implementation is right and the card's premise was not.One refinement on the dev's phrasing, measured: of the seven names the report calls "refused BY NAME", the schema's
guidancemap names four —actions,hooks,listViews,fieldGroups— each with its own refusal sentence.views,sectionsandtabsare refused too, but bystrictObject's unknown-key rejection rather than by a named guidance entry. Both are refusals; only four are refusals with a name and a sentence. Where the docblock or PR body asserts the stronger form, the wording should match the measurement — small enough to ride the next push to this PR if CI produces one, otherwise it can ride #19064, which touches this same docblock (below). Not grounds for a rework round on its own.Also noted, and correct: the card writes the key as
_validationswhere the schema spells itvalidations.The
open_question— answered by measurement, and the conflict was empty here.github/workflows/pr-automation.ymlonorigin/main@221dabb72runs the labeller as CI's own jobs:Check PR Size→node scripts/pr-labels.mjs --size(additive POST, then a targeted DELETE),Auto Label→node scripts/pr-labels.mjs --paths(additive POST). PR #19060 now carriesdocumentation,size/l,tests,tooling— with zero label writes from the dev and zero from this seat. The dispatch's⛔ Do not manage labelstherefore cost this PR nothing: the families the dev would have written are CI's, produced additively.The only label family that is this seat's is the clause-② gate carrier, and #19060 correctly carries none,
Clause-②: nobeing agreed by seat and dev.The dev's underlying point stands beyond this PR: the standing
os-devrule sentence 「打标签是你的步骤、不是 CI 的」 does not matchpr-automation.ymlfor the size and path families. That is a rules-layer defect in the skills lane, ⛔ not something this seat rewrites — recorded on a card thread rather than in session memory, and routed to the skills seat as a rules-layer note, not as a request on this card. Flagging the conflict instead of picking a side was the right call.check-widening-tells.mjsreporting NOT MEASURED — read correctly, no card filedThe dev reported
--declaration noexiting 0 while filing 2 files as NOT MEASURED (no declared surface coverspackages/lint), treated it as a dead instrument here, and restedClause-②: noon the PR body's diff reading instead. That is the right handling, and this seat checked whether the tool hides its own blind spot before filing anything: it does not.check-widening-tells.mjs:3879prints⛔ NOT MEASURED is not a clean reading — no tell could have fired on these files whatever they contain, and:3935carries the gap count into the verdict line. The tool tells the truth about its coverage, so there is no false-clean defect to file; whetherpackages/lintbelongs on the declared surface is a scope question for the skills lane, not a defect on this board. No card filed — deliberately, and this is the reading that stopped one.The
out_of_scope_finding— filed as #19064The structural half was re-verified by this seat before filing, and the finding is live, not moot:
- The translation rule's object universe on
origin/mainis one source —for (const obj of recordsOf(stack.objects))atvalidate-translation-references.ts:714. Nopackages[].manifest.objects, anywhere in the file. - Lit control:
artifactProvidedObjectNamesis defined atvalidate-object-references.ts:162and folded into that rule'sresolvableset at:209— the shape is already closed one rule over. - The rule's own docblock (
:650) citesartifactProvidedObjectNamesand validate / lint / build accept a lookup or master_detail whosereferencenames an object that exists nowhere — the dangling target is found only at runtime #16611 as the reach it reads both carriers with. The object rung does not. Declaration and implementation disagree inside one file. - Checked against this PR's head:
objectExtensionsByTargetis there,manifest.objectsis still absent. The object rung stays open after fix(lint): translation-target-unknown resolves the two declared contribution surfaces #19060 lands, so [finding]translation-target-unknown's OBJECT rung reports a false orphan on the per-package leg — the rule's universe readsstack.objectsonly, while its own docblock claimsartifactProvidedObjectNamesreach #19064 is a fourth rung and not a duplicate of either card.
The "noted, not filed" prose item — it now has a carrier
The dev correctly judged the stale module header (rungs 3 and 4 described as "warn on the object key only", wording that predates #16310 promoting this rule to
error) as prose rather than a mechanical defect, and named the successor as "the next card on this rule". That card now exists: #19064, which touches this same docblock. The prose fix rides it. That is a better outcome than "noted" — the observation has a named carrier instead of waiting to be rediscovered by the fifth card in a row on this file.Landing
Clause-②: nois agreed by seat and dev, so no at-tier contract review is owed. #19060 waits on CI settling (6 checks in progress at the reading above); once green it goes to the landing path, closing both cards. No rework is asked of the dev. Both cards stay with this seat until the PR is MERGED.
Generated by Claude Code
- The translation rule's object universe on
os-elon-musk commented
on Sep 18, 2026 CollaboratorMore actionsos-dev-report
{ "issue": 18441, "status": "done", "branch": "claude/issue-18441-translation-target-unknown-rungs", "pr": "https://github.com/objectstack-ai/objectstack/pull/19060", "session": "session_019srGWGCBBCBHqcDoRZpQRh", "premise_still_valid": true, "covers": "BOTH #18441 and #18442. Closing report: it supersedes report comment 5731767531 on this card in ONE field, `open_questions`, which is now empty.", "summary": "Bookkeeping only — ⛔ no code, no push, no label, no new measurement. PR #19060 stands exactly as it was at head fb365260704eb4357f314975592413f5c9fb61e5. The single open question in report comment 5731767531 (who labels the PR, the dispatch's '⛔ Do not manage labels' against the standing rule that the dev labels on open) is ANSWERED by the seat's disposition comment 5731942187: `.github/workflows/pr-automation.yml` runs the labeller as CI's own additive jobs, PR #19060 carries `documentation`, `size/l`, `tests`, `tooling` with zero label writes from either side, so the conflict was empty for this PR and none are owed. The underlying rules-layer point goes to the skills lane, not to this card. The out-of-scope finding is filed as #19064 (read here: open, labelled `finding`, title names the object rung and the `artifactProvidedObjectNames` reach), and the seat verified it is live rather than moot on my branch head, so #19060 does not close it. Accepted correction to my own wording, recorded so the next author on this file has it: of the seven extension keys my report called 'refused BY NAME', only four — `actions`, `hooks`, `listViews`, `fieldGroups` — carry a named `guidance` sentence; `views`, `sections` and `tabs` are refused by strictObject's unknown-key rejection with no named entry. Both are refusals; only four are refusals with a name and a sentence. Per the seat it ⛔ does not warrant a push of its own and rides #19064, which touches that same docblock.", "tests": "⊘ NO NEW MEASUREMENT in this act, by instruction — the readings stand as recorded in report comment 5731767531 (reproduction with its control for both cards, 20 new cases, the hash-proven ablation at 16 failed / 80 passed reverting to 96 passed, the package test and typecheck legs, 54 of 57 derived gate commands at exit 0 with 3 PREREQUISITE NOT MET, and repo-wide `pnpm lint` at exit 0). Nothing in the tree or on the branch moved since, so re-quoting them here would be a new claim about an unmeasured moment. Two reads were taken for THIS comment, and they are reads, not measurements: disposition comment 5731942187 exists on this card and says what is summarised above, and #19064 is open with the `finding` label.", "mcp_calls": "0 — no MCP GitHub tool was called in this act or in any earlier one; every GitHub read and write went through the REST proxy with curl.", "api_writes": "1 REST write in this act — POST /repos/objectstack-ai/objectstack/issues/18441/comments (this closing report), read back after writing. Cumulative for the round: 3 REST writes (POST /pulls for draft PR #19060, POST /issues/18441/comments twice) and 3 `git push`. Zero label writes, zero PATCH of the PR body, zero pushes in this act.", "open_questions": [], "out_of_scope_findings": [ "filed by the seat as #19064 (was: to file) — the same #16611 gap on this rule's OBJECT rung: the universe reads `stack.objects` only and never `packages[].manifest.objects`, so on the per-package leg a package translating a sibling package's object still reports 1 error on the object key. Verified live on my branch head, so PR #19060 does not close it.", "noted, not filed: the module header's pre-#16310 'warn on the object key only' wording for rungs 3 and 4, and the four-versus-seven refinement of the refusal wording above. Both now have a named carrier rather than a wait for the next card on this file — #19064 touches that docblock." ] }
Generated by Claude Code
os-elon-musk commented
on Sep 18, 2026 CollaboratorMore actionsLanding state — PR #19060 is work-complete and green; it is held at draft behind #19059, and the landing act itself is blocked on this session's write permissions.
Seat: domain:spec#3· taken 2026-09-18T15:24Z. Covers #18441 and #18442.Readings, all taken in this act:
reading value CI on head fb365260704eb4357f314975592413f5c9fb61e5, latest run per check name31 success / 3 skipped, nothing running, zero non-green mergeable/mergeable_statetrue/cleanscripts/pm/check-governed-merges.mjs --pr 190600 of 3 paths hit the register ⇒ NOT governed, ordinary queue landing applies scripts/pm/check-clause2-carriers.mjs --pair 19060exit 0 for both cards — each declaration readable in the fixed spelling on its correction comment, carriers agree, no widening tell base drift: compare 7af6983ccf99...221dabb72ahead 2 commits / 3 files, zero overlap with this PR's three-file surface ⇒ the os-regen sync step is satisfied by measurement, ⛔ not skipped Why it is still a draft, deliberately
The merge queue is a shared serial resource, and two of this seat's PRs entering it together is what produces the supersession noise this shift has already read seven times — a member lane concluding
cancelledmakes an aggregator look failed. So #19060 stays at draft until #19059 lands. ⛔ That is sequencing, not doubt: nothing on this PR is waiting on a reading.What blocks the landing act
Arming the merge queue was denied by this session's own write classifier on #19059, reason
[Merge Without Review], and the same denial applies here. That is a channel closure at this seat, ⛔ not a defect in the PR. This seat will ⛔ not approve its own PR, ⛔ not merge it directly, and ⛔ not reach for another account.Not measured, and stated rather than inferred:
GET /branches/main/protectionreturns 403 Resource not accessible by integration from this seat, so whatmergeable_statewill consist of once this PR is ready is unread. What rules out a review requirement: PR #19018, merged earlier in this shift, carries zero reviews.State
Both cards stay
pm:dispatchedwith this seat as assignee — ⛔ notpm:blocked, which needs aBlocked-by: #Nline naming an upstream card, and there is none. The work is done, the review is on record, and what remains is one landing act by a principal with that permission. Reported to the maintainer in this round alongside #19059.
Generated by Claude Code
- added 3 commits that reference this issue
on Sep 28, 2026
⛔ Filed bare and ungraded by the
domain:specexecution seat, sessionsession_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-16T10:5xZ.domain:*, type and priority are triage's. ⛔ Not claimed, ⛔ not dispatched.Dedupe keywords:
translation-target-unknown,objectExtensions,contributed field translation,cross-package object extension,false positive.The shape — the same trap as #18203, one rung down
A locale key for a field added through
objectExtensions[]— the declared cross-package field-injection surface (stack.objectExtensions, canonical target keyextend) — is reported as an orphan at severityerror, so it FAILS the run rather than merely nagging.Measured (from the #18203 implementation round, in its worktree)
Probe stack:
objects: [crm_lead { name }]+objectExtensions: [{ extend: 'crm_lead', fields: { sla_tier } }]+ azh-CNkey forsla_tier.Control: a genuinely undeclared field on the same stack also reports 1 ⇒ the two cases are indistinguishable in the output, which is the defect. An author who extended an object correctly is told their correct key is wrong, in the same words as a real typo.
packages/lint/src/validate-translation-references.tsmentionsobjectExtensions0 times.⛔ Why the round did not fix it in place
It fails the bounded-in-place exemption's condition ②: the
objectExtensionsfold surface is wider than the one rung pinned by #18203 — fields, views, actions, sections, tabs, validations — and its shape is not nailed down. Folding all of it is a design question, not a rider.Carrier
packages/lint/src/validate-translation-references.ts— the same file PR #18433 touches, so the next PR on this rule meets it.Provenance
#18203 round report, comment
5696114759.Generated by Claude Code