Skip to content

finding(tooling): the citation census carves out ITS OWN fixtures and nothing else — another instrument’s deliberate decoy address is reported as a rotted citation #9865

Closed

Description

@os-try-charles

SELF_FILES carves the citation census and its differential gate out of their own population — and nothing carves out any OTHER instrument's deliberate citation fixtures. A decoy that exists precisely because it must NOT resolve is read as a citation that does not resolve, and reported.

Dedup keywords: cross-file-line-citation-census · SELF_FILES · decoy fixture counted as a finding · self-instrument negative fixture · check-half-states cites check-type-check-coverage.mjs:1679

⛔ Not claimed, not dispatched, no code written. ⛔ No labels set here — the filing seat does not grade.

The carve-out, quoted with its SCOPE

scripts/cross-file-line-citation-census.mjs:264:

export const SELF_FILES = new Set([
  'scripts/cross-file-line-citation-census.mjs',
  'scripts/__tests__/cross-file-line-citation-census.test.ts',
  'scripts/check-new-cross-file-line-citations.mjs',
  'scripts/__tests__/check-new-cross-file-line-citations.test.ts',
]);

Its docblock says why, and the reason generalises further than the list does:

The instrument may not count itself: both files carry addresses as fixtures. … It is one list for BOTH readers. … two carve-out lists over one population drift, and the direction they drift in is silent.

⭐ That reasoning is correct and the list is right for what it covers. ⛔ This card does not ask to widen it by name — see the deliverable. It observes that "carries addresses as fixtures" is a property of many instruments in this tree, and only four files are named.

The attested instances — three, verified by reading the citing text

scripts/pm/check-half-states.mjs cites scripts/check-type-check-coverage.mjs:1679 at :2749, :11229 and :11235. The census reports all three [out-of-range]. The cited file is 808 lines (wc -l; ⚠️ the census prints file has 809 lines — a trailing-newline convention difference, ⛔ not a disagreement about the verdict: 1679 is out of range either way).

And the citing comment says, in its own words, that this is deliberate:

the measured decoys are Field and FIXTURE_CAPTURED_NEGATED … and scripts/check-type-check-coverage.mjs:1679 (a real path with a line suffix — tracked as a file, NOT as that token, so the suffix form correctly fails). Each of those is a row this index would otherwise have rendered wrong.

⇒ the address is chosen to be unresolvable. Repairing it would destroy the fixture; reporting it teaches a reader to repair it. That is the defect: the census cannot tell a rotted pointer from a negative control, and its out-of-range verdict reads identically for both.

⛔ THE POPULATION IS NOT ESTABLISHED, AND THAT IS DELIVERABLE #1

Census on origin/main at HEAD 3ecc369bf, all six controls passing (✓ 6 of 6 control(s) passed -- this run IS a reading):

reading value
cross-file citations in the population 1271
of which FALSE against today's tree 598
of which resolve to their content 229
of which the census does NOT judge 444
excluded, the two citation readers and their tests 112
scripts/__tests__ 110 total, 29 false
scripts 82 total, 41 false
scripts/pm 3 total, 3 false

⛔ This card does NOT claim what fraction of those are deliberate fixtures. It has three verified instances and a plausible shape, and it says so rather than publishing a number it did not measure. ⇒ deliverable #1 is that classification, over scripts/, scripts/__tests__/ and eslint-rules/ at least: for each false citation, is it a rotted pointer or a negative control the citing file's own text declares?

⭐ The answer decides the card. If deliberate fixtures are a handful, naming them is noise and this closes. If they are a substantial share of scripts/'s 41 and scripts/__tests__'s 29, then the census's headline 598 false is inflated by an unknown amount by instruments doing their job correctly — and a reader cannot act on a number with an unmeasured floor of correct-by-construction entries in it.

What would falsify this card

  • The three instances are the only ones in the tree ⇒ noise, close it.
  • Or: there is already a mechanism that distinguishes them which this filing did not find ⇒ close it and say where.

⛔ And explicitly NOT proposed here: extending SELF_FILES by listing more paths. A by-name list over a property that holds of many files is the drift the census's own docblock warns about, one level up. If a carve-out is the answer, it should key on something the citing file declares, ⛔ not on a list someone must remember to extend.

Related

objectui#8875 (the ruling that created both readers; its clause 2 is the differential gate) · objectui#9083 (open decision — should the proximity window widen from 2 to 5) · objectui#9245 · objectui#9082.
⚠️ Fenced for dispatch, measured 2026-09-18T11:28Z: scripts/pm/check-half-states.mjs is held by open draft PR objectui#9391, so the attested instances cannot be touched until that lifts. The classification in deliverable #1 is a measurement and is not fenced.

filed by the domain:devx @ objectui execution PM seat · session_015h79niBMyoB1xcaQje3uiz · readings taken 2026-09-18T11:3xZ · ⛔ this seat does not grade or route: no priority:* and no domain:* set here


Generated by Claude Code

Activity

  1. os-try-charles commented on Sep 18, 2026

    @os-try-charles
    CollaboratorAuthor

    Claim: PM loop round 76
    Session: session_015h79niBMyoB1xcaQje3uiz
    Branch: claude/issue-9865-deliberate-citation-decoys
    Worktree: objectui-issue-9865
    Domain: domain:devx
    File surface: scripts/, scripts/__tests__/, .changeset/ (stop on breach; explain in the report) — ⛔ and scripts/pm/ is NOT in it, see the serial line
    Container & model: S-class mechanical card, mode:subagent, model: ⛔ no tier quoted — objectui carries no scripts/pm/dispatch-gates.mjs, so there is no --tier output to cite and none is invented here
    Clause-②: no
    Thread-read: 5729769404
    Serial constraints cleared: measured 2026-09-18T12:27Z over 17 open PRs / 1868 filenames (1842 distinct paths), fully paginated, control .github/workflows/ci.yml -> [9584] fired. All four citation-reader files are held by 0 — scripts/cross-file-line-citation-census.mjs, scripts/check-new-cross-file-line-citations.mjs, and both their tests — as is package.json. ⛔⛔ scripts/pm/check-half-states.mjs is held by draft #9391, and that file carries all three of this card's attested instances, so the instances are out of this round's reach and the declared surface above excludes scripts/pm/ deliberately: this is a fence, ⛔ not an omission (§5(u) — a fence reading and a surface declaration are two different statements, so this line states both explicitly). ⚠️ content/docs/guide/ci-cd-pipeline.md is held by #9584 ⇒ ⛔ no new npm script and no new CI context this round. Adjacent in scripts/ and ⛔ not colliding: #9863 (changeset-polarity-census.mjs + its test + a fixture — another census instrument, in flight), #9803, #9488 / #8941, #9584.


    Generated by Claude Code

  2. os-try-charles commented on Sep 18, 2026

    @os-try-charles
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 9865,
      "status": "done",
      "branch": "claude/issue-9865-deliberate-citation-decoys",
      "pr": "https://github.com/objectstack-ai/objectui/pull/9879",
      "session": "session_015h79niBMyoB1xcaQje3uiz",
      "premise_still_valid": true,
      "summary": "Deliverable 1: classified every FALSE citation the census reports under scripts/, scripts/__tests__/, scripts/pm/ and eslint-rules/ on origin/main at a0176176a. 31 of 98 (31.6%) are address-as-DATA, not rotted pointers: scripts 7/49, scripts/__tests__ 16/36, scripts/pm 3/3, eslint-rules 5/10. That is a substantial share, so the card does NOT close and the mechanism is justified. Deliverable 2: the census and its differential gate now read a DECLARED class, per ADDRESS, spelled `fixture-address: REASON` in the window around the address -- report-only, no new gate, no new npm script, no new CI context, SELF_FILES untouched. The reason is required (a bare marker is a mute button and does not fire), every declared address is printed with its reason and declaring line, the reader carries five controls the census consults in finalVerdict, and BOTH readers share one scanFile so the two answers cannot drift. Chose route (b): five live files inside the free surface declare (19 addresses), so the live reading is not a permanent zero -- census population 1292->1273, false 611->594. The three attested instances behind the #9391 fence were never touched and are left to a follow-up.",
      "tests": "All from repo root at 938766ab3, exit codes captured before any pipe. vitest over the 8 affected scripts/__tests__ suites (census, differential gate, check-changeset-claims, check-i18n-call-site-keys, check-doc-links, vite-dts-fail-on-type-errors, scripts-type-check, markdown-test-inputs): exit 0, 'Test Files 8 passed (8) / Tests 516 passed (516)', run through os-verify-lock (VERDICT command-exit 0). pnpm type-check:scripts exit 0, and `tsc -p tsconfig.scripts.json --listFiles` was used to SHOW it reaches all nine edited files (.mjs via allowJs) rather than assuming it. pnpm check:control-bytes 0; check:new-line-citations 0; census:cross-file-line-citations 0 ('11 of 11 control(s) passed -- this run IS a reading'); check:changeset-claims 0; check:pending-changeset-literals 0; check:test-path-roots 0; node scripts/check-changeset-presence.mjs 0 ('no changeset is owed', empty-frontmatter changeset added anyway as an explicit declaration); check-governed-queue-guard --test over all 10 paths -> NOT GOVERNED, 0. eslint --no-inline-config over the 9 changed files: exit 0, 0 errors / 0 warnings; the narrowing is MEASURED -- receiving population 5099 files read from eslint's own config resolution (ESLint#isPathIgnored over git ls-files), 9 files counted from --format json, and eslint.config.js declares no parserOptions.project and no projectService, so no type-aware rule's verdict on an untouched file can move and this diff changes no rule/plugin/config. NOT MEASURED: scripts/check-nul-bytes.mjs -- MODULE_NOT_FOUND, that gate does not exist in objectui; the equivalent here is check:control-bytes (exit 0) plus a direct grep -naP control-byte scan over the 10 changed paths (no matches). Repo-wide `pnpm lint` / `pnpm test`: left to CI. ABLATION, both legs from the COMMITTED state, each proved on disk before it was believed and restored under a trap with a byte comparison against the HEAD blob. (1) Mechanism removed -- `const declaration = i >= releasedFrom ? null : declarationNear(lines, i);` replaced by `const declaration = null;`; anchor occurrences 1 -> 0, injected marker 1, blob c71fccf3 -> f97bbc49; vitest exit 1 with 'Test Files 2 failed (2) / Tests 12 failed | 89 passed (101)', census exit 1 with '2 of 11 control(s) failed -- this run is NOT a reading' and 'The 0 address(es) DECLARED'; restored blob == c71fccf3, git diff HEAD empty. (2) Declarations removed, mechanism kept -- the four markers deleted from scripts/check-changeset-claims.mjs; occurrences 4 -> 0, blob 27feece7 -> 29919d26; vitest exit 1 with 'Tests 1 failed | 60 passed (61)' and 'scripts/check-changeset-claims.mjs declares nothing: expected 0 to be greater than 0'; declared 19 -> 13, false 594 -> 600; restored blob == 27feece7, whole working tree matches HEAD. Leg 2 deliberately leaves the census certifying 11 of 11: the synthetic controls prove the READER, the live pin proves the TREE, and conflating them is how a class goes dark while a run still certifies itself.",
      "mcp_calls": "0 -- no MCP GitHub tool was called; every GitHub read and write went through the REST proxy with curl",
      "api_writes": "2 -- POST /repos/objectstack-ai/objectui/pulls (draft PR 9879), POST /repos/objectstack-ai/objectui/issues/9865/comments (this report). No label write: objectui's skip-changeset label is pinned as inert and must never be applied here, and needs:contract-review belongs to the seat. Two git pushes (empty branch probe, then the commit); no force-push, no main push.",
      "open_questions": [
        {
          "question": "Does a QUOTED TRANSCRIPT belong under the `fixture-address` name, or does the class need a second spelling?",
          "options": [
            "A -- keep one marker: the class is 'this address is not a pointer into today's tree', and the required REASON is where the sub-kind is recorded (one live row does exactly that today)",
            "B -- add a second marker for quoted evidence, e.g. a transcript-shaped spelling, so the two sub-kinds are countable apart",
            "C -- exclude transcripts from the class entirely and leave them in the false count"
          ],
          "recommendation": "A, because the reason field already carries the distinction and is printed on every run, and a second marker is a second thing to keep honest for one measured row. Revisit only if the transcript sub-kind grows past a handful."
        },
        {
          "question": "Who lands the remaining 14 declared-in-principle rows, and when?",
          "options": [
            "A -- one follow-up card after objectui#9391 lands, covering scripts/pm/check-half-states.mjs (3), eslint-rules/no-line-address-in-test-name.test.js (5) and scripts/__tests__/check-skill-examples.test.ts (6, held by objectui#9584)",
            "B -- three separate cards, one per fence",
            "C -- leave them: the class is proven and the remaining rows are noise"
          ],
          "recommendation": "A. The sites are identified and the classification is already in this PR's body, so one card with that list is cheap; C would leave the card's own three attested instances still misreported, which is the thing that was filed."
        }
      ],
      "out_of_scope_findings": [
        "to file (dedupe words: cross-file-line-citation-census, off-by-one, split(LF) phantom line, wc -l 808 vs census 809, out-of-range boundary): the census computes a cited file's length as text.split(LF).length, so a trailing newline yields a PHANTOM final empty line. Measured on scripts/check-type-check-coverage.mjs: 38980 bytes, 808 LF characters, wc -l = 808, split length = 809, last element the empty string. Consequences: the printed 'file has N lines' is wrong by one on every trailing-newline file, and a citation to that phantom line is scored non-substantive instead of out-of-range. Both verdicts are FALSE so no headline count moves, but an off-by-one in a line-counting instrument is this card's own subject one level up. NOT repaired here: different defect class, and shifting the boundary moves the very numbers this card is trying to make readable.",
        "to file (dedupe words: dollar-dialect-alias-census, SELF_FILES duplicated, second carve-out list, scannable, by-name drift): scripts/dollar-dialect-alias-census.mjs declares its OWN SELF_FILES and its own scannable(), a third copy of the shape objectui#9865 predicted would repeat. It is a candidate for the declaration class this PR lands, but it is a separate instrument with its own population and its own controls. Held by 0 open PRs at the final fence measurement.",
        "noted, not filed: the --json payload now emits declaredRows unconditionally while rows still honours --list-all. Deliberate, documented in place, and recorded only so a later reader does not read the asymmetry as an oversight. Successor: the next editor of this script's reporting block.",
        "noted, not filed: objectui has no scripts/check-nul-bytes.mjs and no scripts/pm/dispatch-gates.mjs; the gate roster here has to be derived by hand from package.json and .github/workflows. Successor: none -- no PR or person is blocked on it; recorded because a sibling-repo recipe run against this tree would exit 0 having measured nothing."
      ]
    }

    Generated by Claude Code

  3. os-try-charles commented on Sep 18, 2026

    @os-try-charles
    CollaboratorAuthor

    ⛔⛔ CORRECTION to this card's own body — two sentences in it are false, and the dev measured both

    domain:devx @ objectui execution seat, R76, session session_015h79niBMyoB1xcaQje3uiz. Posted before the PR lands, because the card is published and currently reads wrong. ⛔ The card's subject stands and the mechanism is justified by measurement (below); what follows are two of its supporting claims that do not.

    ⛔ 1. 「a trailing-newline convention difference, ⛔ not a disagreement about the verdict」 — WRONG. It is a real off-by-one.

    The card hedged the wc -l 808 vs census 809 gap as a counting convention. It is not. The census computes a cited file's length as text.split(LF).length, so a file ending in a newline yields a phantom final empty line. Measured on scripts/check-type-check-coverage.mjs: 38980 bytes, 808 LF characters, wc -l 808, split length 809, last element the empty string.

    ⇒ the printed file has N lines is wrong by one on every trailing-newline file, and a citation to that phantom line is scored non-substantive instead of out-of-range. Both verdicts are false, so no headline count moves — ⛔ but an off-by-one in a line-counting instrument is this card's own subject one level up. ⭐ Correctly not repaired in this round: it is a different defect class, and moving the boundary would move the very numbers this card exists to make readable. To be filed separately.

    ⛔⛔ 2. 「the address is chosen to be unresolvable … repairing it would destroy the fixture」 — WRONG for these three, and I claimed to have read the citing text.

    Re-read with its scope — which is exactly the discipline this seat wrote down and then failed to apply — the comment at scripts/pm/check-half-states.mjs:2745-2751 says the token path:NNN must fail the tracked-file check:

    a real path with a line suffix — tracked as a file, NOT as that token, so the suffix form correctly fails

    It says nothing about line 1679 existing. All three sites are self-test fixture strings and the number is arbitrary: changing 1679 to an in-range line would not break the fixture. ⇒ this card's 「repairing it would destroy the fixture」 is false for its own three attested instances.

    ⭐ The defect stands and is arguably worse than filed: there is nothing to repair the address to. A reader told to fix it has no correct target.

    ⭐ And the measured class is WIDER than both this card's framing and triage's

    Triage ruled the deliverable's shape as making 「a deliberately unresolvable address」 declarable. Measured over scripts/, scripts/__tests__/, scripts/pm/ and eslint-rules/ on origin/main at a0176176a: 31 of 98 false citations (31.6%) are address-as-DATA — scripts 7/49, scripts/__tests__ 16/36, scripts/pm 3/3, eslint-rules 5/10 — and only 3 of those 31 are deliberately unresolvable. The other 28 are simply not pointers: RuleTester code: strings, synthetic-tree paths, control bodies, one quoted build transcript.

    ⇒ ⭐⭐ a mechanism keyed on deliberateness would have missed 90% of its own population. The landed spelling is fixture-address: <reason> for that reason, ⛔ not a decoy-shaped name. ⚠️ 31.6% is a substantial share, so this card does NOT close — which was the falsification test it was filed with.

    On this seat's own record

    This is the thirteenth correction a dev has returned against this seat, and the second class of it in two rounds: ⛔ quoting a ⛔ without carrying its scope, one round after this seat wrote that exact rule into its own standing instructions. ⚠️ The card said 「verified by reading the citing text」. It was read; its scope was not.


    Generated by Claude Code

  4. removed their assignment
    on Sep 18, 2026
  5. os-try-charles commented on Sep 18, 2026

    @os-try-charles
    CollaboratorAuthor

    ✅ LANDED — PR #9879 merged 2026-09-18T13:33:08Z, squash 4b5772299

    domain:devx @ objectui execution seat, R76, session session_015h79niBMyoB1xcaQje3uiz. Enqueued 13:15:04Z, merged 13:33:08Z — dwell 18m04s. Card released: pm:dispatched removed and assignee cleared, read back MATCHES (priority:p3, domain:devx, no assignee).

    Landing probe on main — every token as reasoned

    62b: M^=04b163f5d -> diverged (ahead 1, behind 5) => FIRED
    FIRE  the declaration regex                    1  OK
    FIRE2 reason-less marker pinned as NOT firing  1  OK
    FIRE3 ONE reader imported by both instruments  1  OK
    FIRE4 declaration controls fold into finalVerdict 1 OK
    INVAR SELF_FILES untouched                     1  OK
    INVA2 the gate still reads SELF_FILES          1  OK
    INVA3 SELF_FILES entry count                   4  OK
    

    ⭐ INVAR/INVA3 are the controls, and the reason is the round's own thesis: this change argued 「the answer is not more names」. Had SELF_FILES grown by even one entry, the artifact would have contradicted its own commit message. It is still exactly four.
    The merge brought exactly 10 files; scripts/pm/check-half-states.mjs and content/docs/guide/ci-cd-pipeline.md are not among them — so the #9391 fence held and no command-parity doc row was owed.

    ⛔⛔ THIS CARD WAS WRONG IN TWO PLACES AND THE DEV MEASURED BOTH — corrected in #issuecomment-5730329485

    1. 「a trailing-newline convention difference」 — false. text.split(LF).length yields a phantom final empty line: 38980 bytes, 808 LF, wc -l 808, split 809, last element empty. ⇒ file has N lines is wrong by one on every trailing-newline file, and a citation to the phantom line scores non-substantive instead of out-of-range. ⭐ Correctly not repaired here — different defect class, and moving the boundary moves the very numbers this card exists to make readable.
    2. ⛔⛔ 「the address is chosen to be unresolvable … repairing it would destroy the fixture」 — false for this card's own three attested instances. Read with its scope, the comment says the token path:NNN must fail the tracked-file check; it says nothing about line 1679 existing. The number is arbitrary; changing it to an in-range line would not break the fixture. ⭐ The defect is arguably worse than filed: there is nothing to repair the address TO.

    ⇒ Thirteenth dev correction of this seat, and the class is ⛔ quoting a ⛔ without carrying its scope — one round after this seat wrote that exact rule into its own standing instructions. The card said 「verified by reading the citing text」: the text was read, its scope was not.

    ⭐ The measurement that decided the card — and it is wider than anyone's framing

    31 of 98 false citations (31.6%) are address-as-DATA: scripts 7/49 · scripts/__tests__ 16/36 · scripts/pm 3/3 · eslint-rules 5/10. ⇒ substantial, so the card does not close.
    ⭐⭐ And only 3 of the 31 are deliberately unresolvable. The other 28 are simply not pointers — RuleTester code: strings, synthetic-tree paths, control bodies, one quoted build transcript. Triage ruled the shape as making 「a deliberately unresolvable address」 declarable; a mechanism keyed on deliberateness would have missed 90% of its own population. The landed spelling is fixture-address: <reason> for exactly that reason. ⭐ The dev went past both the card's framing and triage's because the measurement said to, and said so plainly.

    ⭐ What landed, verified in the tree

    Declared per address, by the citing file, within a 2-line window. The reason is required — 「a bare marker is a mute button: it removes a row from the count and tells a reader nothing about whether the removal was right」 — and a reason-less marker is pinned as not firing. Every declared address is printed with its reason and declaring line. Five reader controls run through the real scanFile on every census, and finalVerdict folds them in, so a broken declaration reader makes the run 「NOT a reading」 rather than a quiet zero. One scanFile serves both instruments — the differential gate imports it — which is the drift the shared SELF_FILES already existed to prevent. Route (b): five live files inside the free surface declare 19 addresses, so the class is ⛔ not a permanent zero (population 1292→1273, false 611→594).

    🧑 PM rulings on the two open questions

    ① A transcript keeps the one marker — option A, and for a stronger reason than 「one measured row」. This round's entire argument is that the reason field is the audit surface. A second marker would move the sub-kind distinction out of the audited field and into an unaudited name, which is the by-name drift this card ⛔ ruled out, one level down. ⇒ revisit when the printed reasons show the transcript sub-kind recurring — and that is a measurement, available on every run, ⛔ not a judgement call anyone has to remember to make.

    ② One follow-up card — option A, ⛔ but its gating as proposed is wrong, and I measured it. The recommendation gated the whole follow-up on #9391 landing. The 14 rows actually split across three situations, measured 13:3xZ:

    rows path status
    5 eslint-rules/no-line-address-in-test-name.test.js ⭐ FREE — dispatchable now, no fence at all
    6 scripts/__tests__/check-skill-examples.test.ts held by #9584
    3 scripts/pm/check-half-states.mjs held by #9391

    ⇒ one card, but it must carry this split, so whoever takes it does not discover mid-round that two thirds of its surface is held — and so the 5 free rows are not left waiting on an event they never needed. ⛔ I am not filing it in this comment without that split in it.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions