Skip to content

tenant-audit census collapses declared type text before re-parsing it (route ①), and conflates same-named locals across scopes #19300

Description

@os-litant

Path: P1 | 那条路第 1 步「写元数据」 | 普查把声明类型文本折成一行再重解析,合法的换行内联对象类型读不出来
分诊重测与定级:2026-09-20T15:29Z

Origin

Triage on #19077 named three routes for the census's unreadable-type-text class. PR #19290 implemented route ③ — localise the failure into a per-site refusal instead of a process-wide takedown — and an at-tier review confirmed it holds. Route ① — stop collapsing the declared type text — was named there as the real repair and is not in the tree. #19077 will close on #19290's merge, so it is carried here.

Defect 1 — the census collapses declared type text before re-parsing it

Measured at PR #19290 head ce1b530410150de7f229a6ffb9dab0dd1608baf6, re-read first-hand by this seat in a detached worktree. scripts/tenant-audit-census.mjs stores declared type text through getText(sf).replace(/\s+/g, ' '):

:508   type: typeNode ? typeNode.getText(sf).replace(/\s+/g, ' ') : null,
:527   if (t) m.set(mem.name.text, t.getText(sf).replace(/\s+/g, ' '));
:590   return node.getText(sf).replace(/\s+/g, ' ');

A newline-separated inline object type is legal TypeScript, but once its newlines become single spaces the text no longer re-parses: the members run together and census-receiver-type.ts dies at 1:78 ';' expected. After #19290 the site is no longer a process-wide takedown — it is refused by name as type-text-not-round-trippable — but the author is still told to restyle legal TypeScript (add ; separators, or name the type) to work around the tool's own reading.

The reviewer's judgement, verbatim:

the arm is a refusal that tells the author to restyle legal TypeScript (; separators or a named type) to work around the tool's own collapse at :480/:499/:562. That is what the sequenced hunk asked for and it is strictly better than the takedown it replaces, but the underlying limitation is still in the tree; the PR's "Not a defect in the tree" under-states it. Triage's route ① (stop collapsing) is the real repair.

(The reviewer's :480/:499/:562 are that file's line numbers at an earlier base; at the PR head they are :508/:527/:590 as quoted above.)

Defect 2 — declaredTypesIn keys its locals map by bare identifier name, with no scope

Same file, same head. declaredTypesIn(sf) (:496) builds const locals = new Map() (:498) and fills it by bare name (note(locals, n.name.text, …) at :534 and :543, locals.set(el.name.text, …) at :555); every consumer reads it back by bare name (:648, :655, :677, :1156, :1329). Two parameters that share a name in different scopes therefore conflate.

Measured instance, from the same review: a fixture whose two receiver sites both named their parameter engine had both sites refused. Renaming one made the control clean. This is pre-existing, not introduced by #19290, and it produces false refusals in the census.

Note for triage

Two distinct defects in one file's TypeScript reading, with two distinct fixes. They are filed together because they were measured in one act; splitting them into two cards is a reasonable triage call.

Dedup words

type-text-not-round-trippable, declaredTypesIn, tenant-audit-census, census-receiver-type, getText collapse

Origin: at-tier contract review of PR #19290, comment 5749193385 (2026-09-20T10:19Z) — "Residual" under ① and the out-of-scope observation under the lit control. Line readings re-taken by this seat at 2026-09-20T10:28Z.
Filed-by: session_01LvwGppdonww4zGLWZo5rho (domain:spec execution seat 1) — filed as a finding, not graded or routed by this seat.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions