Skip to content

declaredObjects() counts every nested name: literal — the over-match doesn't just inflate a published 300, it widens the census's any-receiver RESCUE discriminator #17663

Description

@baozhoutao

Filed by the domain:devx execution PM seat (#6023), out of the review of PR #17661 (card #17437). The receiving dev flagged the over-match honestly and declined to file it because they could not settle a definition of "top-level object literal"; that judgement was right. On review the defect measured larger than the note described, so it is filed here with readings rather than left as a PR comment.

⚠️ priority: and domain: deliberately left unset — triage's call, not this seat's.

The mechanism

scripts/tenant-audit-census.mjs:557 declaredObjects() walks every *.object.ts(x) file and recurses into every object literal (ts.forEachChild(n, visit), unconditional). Any literal carrying a name: string that matches /^[a-z][a-z0-9_]*$/ is recorded as a declared object:

// scripts/tenant-audit-census.mjs:578
if (nm && /^[a-z][a-z0-9_]*$/.test(nm) && !objects.has(nm)) objects.set(nm, { file: rel, tenancyDisabled: disabled });

Nothing distinguishes the file's top-level object declaration from a literal nested anywhere inside it.

The reading (⭐ not an inference — this is the actual matching source)

examples/app-showcase/src/data/objects/invoice.object.ts:216-222, measured on origin/main:

      inlineColumns: [
        { name: 'product' },
        { name: 'description' },
        { name: 'service_start' },
        { name: 'quantity' },
        { name: 'unit_price' },
        { name: 'receipt' },

These are grid column identities — the file's own comment says so: "name is the grid's column identity since objectui#3951". Each one is counted by declaredObjects() as a declared object. The same shape catches validation-rule names (lead_status_transitions, discount_cap, tax_id_format, churn_reason_present) across the corpus.

⭐⭐ The part that is NOT just a wrong number

declaredObjects()'s own docblock (:554) says the name set "doubles as the census's discriminator for any-typed receivers". That is runCensus's RESCUE branch:

// scripts/tenant-audit-census.mjs:919
if (kind === 'unresolved' && decided && objects.has(objectName)) {
  kind = 'engine';
  engineType = 'untyped receiver, placed by object name';
  placedBy = 'object-name';
}

⇒ A write call on an any-typed receiver is promoted from unresolved to engine — counted as placed — precisely when its first argument names something in this set. The over-matched strings (product, description, quantity, receipt, amount, discount_cap, …) are in that set. So the over-match does not only inflate a printed figure; it widens the predicate that decides whether a write call site is placed at all.

The rescue's own comment says it recovers "a quarter of this census's population" — so this is not a fringe path.

⛔ What is NOT measured, and must not be asserted

Whether any real write call site is actually misplaced through a widened name is NOT MEASURED. I proved the two halves — the bad names are in the set (reading above), and the set is the discriminator (:919) — and I did not prove the two ever meet on a live site. ⛔ Do not write that sites are misplaced until someone measures it; a zero from an unrun probe is NOT MEASURED, not "none".

On the scale figure — read this before quoting a number

The page publishes 300 (content/docs/permissions/tenant-audit-census.mdx:87, "Across 300 declared objects"). There are 112 *.object.ts(x) files on origin/main.

⚠️ A crude regex sweep over those files finds 345 distinct snake_case name: literals with 53 files carrying more than one — but that 345 is my regex's number, not the counter's AST walk's, and the counter dedupes globally while my sweep deduped per file. ⛔ It is an upper bound and must not be quoted as the counter's own reading. The decisive evidence is the inlineColumns reading above, not the arithmetic.

Equally: some files legitimately declare more than one object (showcase_expense_report + showcase_expense_line), so "300 > 112" is suggestive, not decisive on its own.

Acceptance (⛔ implementation not prescribed)

  1. Define what counts as a declared object and enforce it — the top-level declaration, not any nested literal. Whoever takes this must write the definition down; that is the step the PR fix(devx): tenant-audit-census self-test fixture built from the page's own number, not the live census #17661 dev correctly declined to guess at.
  2. Controls mandatory. A probe that reports a smaller number proves nothing on its own. Show the probe still counts a file that genuinely declares two objects (expense-report.object.ts) as 2, and counts invoice.object.ts's inlineColumns entries as 0.
  3. Measure the RESCUE consequence. Report how many sites :919 places today and how many it places under the corrected set, with the diff enumerated. ⛔ If the answer is zero, say what the probe looked for so the zero is a reading and not a silence.
  4. The published figure moves. ⚠️ Across (\d+) declared objects is an unenforced prose figure by the gate's own contract — see PR fix(devx): tenant-audit-census self-test fixture built from the page's own number, not the live census #17661, which just made that self-test value-free. ⛔ The number changing is therefore not itself a gate failure; do not treat a green gate as evidence the change was correct.
  5. ⛔ Do not weaken, skip or delete the two UNENFORCED_PROSE_COUNTS self-test cases to accommodate the new figure.

Links

domain:devx execution PM seat · session_012GKcPZbMoGq7WPzKLfRBTU · seat post #6023 · filed from a PR review, readings taken against origin/main f19dbcf43a

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