Skip to content

fix(graph-ui): honest Project-ID label; RED repro for TS inherited-method gap#847

Merged
DeusData merged 2 commits into
mainfrom
distill/ui-label-and-ts-repro
Jul 4, 2026
Merged

fix(graph-ui): honest Project-ID label; RED repro for TS inherited-method gap#847
DeusData merged 2 commits into
mainfrom
distill/ui-label-and-ts-repro

Conversation

@DeusData

@DeusData DeusData commented Jul 4, 2026

Copy link
Copy Markdown
Owner

distill: honest Project-ID label + RED repro for the TS inherited-method gap

Two small, independent deliverables distilled from recent review decisions.

1. fix(graph-ui): label Project name honestly as permanent ID

The New Index modal presented "Project name" as an optional display name, but the
value becomes permanent identity: the database filename, the projects primary key,
and the QN prefix of every node. It can never be renamed afterwards.

This implements the decision from the #805 review (credit: @rarepops, whose PR
identified the dishonest label): keep the field, make it honest.

  • Label is now "Project ID (optional — permanent, cannot be renamed)" (zh:
    项目 ID(可选,永久且不可重命名)).
  • New help line under the input: "Becomes the database name and query prefix.
    Leave blank to derive it from the path."
    (zh: 将作为数据库名称与查询前缀;留空则从路径派生。)
  • Placeholder: "Derived from folder name if blank" (zh: 留空则从路径派生).
  • Both locales updated in graph-ui/src/lib/i18n.ts; the test asserting the old
    label (StatsTab.test.tsx) updated.

Verification: npx vitest run → 13/13 green (under an en_US locale; one
pre-existing, unrelated locale-dependent failure exists on main in
GraphTab.test.ts — bare toLocaleString() formats 2,000 as 2.000 on a
German-locale machine; untouched by this PR). npx tsc -b clean.

2. test(repro): RED — TS cross-file inherited method call unresolved

PR #840 flips the probe lrp_ts_s6_inherited_method from a fragile false-green
(a unique_name short-name registry guess that happened to bind the right node in
a 2-file fixture) to asserting the weak edge is suppressed (calls == 0).
That flip is correct — but it leaves the underlying gap (ts_lsp cross-file
inherited method call resolution) with no red reproduction anywhere.

Per repo discipline (reproduce discovered gaps immediately; RED entries live in the
non-gating repro suite), this adds tests/repro/repro_ts_inherited_method.c:

  • Fixture: base.ts (export class Base { greet() ... }) + derived.ts
    (Derived extends Base + a typed const d: Derived = new Derived(); d.greet()
    call site).
  • GREEN precondition test: both files extract cleanly (no has_error), Base.greet
    is extracted as a Method, the greet call site is extracted — so the red below is
    attributable to resolution only.
  • RED pipeline test: after full production indexing, asserts store-level
    preconditions (a Method node with QN suffix .Base.greet exists; INHERITS >= 1)
    and then the CORRECT outcome: a CALLS edge from callSite to *.Base.greet
    carrying an lsp_ts_* strategy on that same edge. A strategy-less short-name
    fallback edge (pre-fix(resolver): suppress weak short-name strategies for TS/JS (recovers #836) #840 lucky green) does not satisfy it; post-fix(resolver): suppress weak short-name strategies for TS/JS (recovers #836) #840 suppression
    (no edge) doesn't either. Green ⟺ genuine ts_lsp cross-file inheritance
    resolution.
  • Registered in Makefile.cbm TEST_REPRO_SRCS and tests/repro/repro_main.c
    (suite repro_ts_inherited_method; deliberately non-gating, make test-repro).

RED evidence (verbatim)

From CBM_INDEX_SUPERVISOR=0 CBM_REPRO_ONLY=repro_ts_inherited_method ./build/c/test-repro-runner:

    [ts-inherited] CALLS private-tmp-cbm_repro_RCQJ67.derived.callSite (Function) -> private-tmp-cbm_repro_RCQJ67.derived.Derived props={"callee":"Derived","confidence":0.90,"strategy":"same_module","candidates":1,"line":8}
    [ts-inherited] CALLS private-tmp-cbm_repro_RCQJ67.derived.callSite (Function) -> private-tmp-cbm_repro_RCQJ67.base.Base.greet props={"callee":"d.greet","confidence":0.75,"strategy":"unique_name","candidates":1,"line":9}
  FAIL tests/repro/repro_ts_inherited_method.c:246: no lsp_ts-resolved CALLS edge callSite -> *.Base.greet — TS cross-file INHERITED method call is UNRESOLVED (ts_lsp inheritance gap, see #836/#840)
[SUITE] repro_ts_inherited_method              1 passed, 1 failed

Red-for-the-right-reason proof: the GREEN row is the extraction-precondition test
(both files parse cleanly, Base.greet Method def + greet call site extracted);
the store-level preconditions inside the failing test (callee node present,
INHERITS >= 1) printed no failure; and the edge dump shows the graph holds exactly
the weak "strategy":"unique_name" fallback edge (confidence 0.75) that #840's
analysis predicted — the lucky wrong-mechanism edge, not an lsp_ts_* resolution.
The FAIL fires on the primary missing-LSP-resolution assertion only.

Root-cause pointer (documented in the test header): ts_lsp cross-file inheritance
resolution — internal/cbm/lsp/ts_lsp.c method lookup does not follow the
(correctly extracted) INHERITS edge from Derived to an imported Base. See
#836/#840 and the S6 probe.

Refs #805-review, refs #835.

DeusData and others added 2 commits July 4, 2026 11:35
The New Index modal presented the project name as an optional display
name, but the value becomes permanent identity: the database filename,
the projects primary key, and the QN prefix of every node. It can never
be renamed afterwards.

Implements the decision from the #805 review: keep the field, make it
honest. The label now reads "Project ID (optional — permanent, cannot
be renamed)", the placeholder and a new help line explain that the ID
becomes the database name and query prefix and that leaving it blank
derives it from the path. Both EN and zh locales updated, test asserting
the old label adjusted.

Co-authored-by: rarepops <rarepops@protonmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
PR #840 flips the lrp_ts_s6_inherited_method probe from a fragile
false-green (a unique_name short-name registry guess that happened to
bind the right node in a 2-file fixture) to asserting the weak edge is
suppressed. That flip is correct, but it leaves the underlying gap —
ts_lsp cross-file INHERITED method call resolution — with no red
reproduction anywhere.

Add tests/repro/repro_ts_inherited_method.c to the non-gating repro
suite: base.ts defines Base.greet, derived.ts has Derived extends Base
and a typed call site d.greet(). A GREEN precondition test proves both
files extract cleanly, the Base.greet Method def exists and the call
site is extracted; the RED pipeline test additionally verifies the
callee node and the INHERITS edge are in the graph, then asserts the
correct outcome: a CALLS edge callSite -> *.Base.greet carrying an
lsp_ts_* strategy on that same edge. The pre-#840 lucky unique_name
fallback edge does not satisfy it (verified: the run dumps that exact
edge, strategy unique_name, confidence 0.75), and post-#840 suppression
yields no edge at all — so the test stays RED until ts_lsp genuinely
resolves cross-file inheritance. Guards the gap left visible after

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
#840's probe flip; see the test header for the root-cause pointer.
@DeusData DeusData enabled auto-merge July 4, 2026 11:44
@DeusData DeusData merged commit c737413 into main Jul 4, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant