Skip to content

fix(pipeline): preserve dotted TypeScript import basenames - #1811

Merged
DeusData merged 18 commits into
DeusData:mainfrom
pcristin:fix/issue-1682-dotted-ts-imports
Sep 4, 2026
Merged

fix(pipeline): preserve dotted TypeScript import basenames#1811
DeusData merged 18 commits into
DeusData:mainfrom
pcristin:fix/issue-1682-dotted-ts-imports

Conversation

@pcristin

Copy link
Copy Markdown
Contributor

What does this PR do?

Preserve extensionless dotted JavaScript/TypeScript module basenames such as
featureX.engine during relative-import resolution.

Refs #1682.

Verification

  • make -f Makefile.cbm test-focused TEST_SUITES='fqn edge_imports' — 143 passed
  • make -f Makefile.cbm test-par — 7,577 passed, 0 failed, 8 skipped across 139 suites
  • git diff --check
  • Changed files pass clang-format --dry-run --Werror
  • Diff-scoped clang-tidy passes

The repository-wide lint-ci baseline is not clean in untouched files: cppcheck
reports existing style findings in src/store/store.c and src/cypher/cypher.c,
and the formatter reports existing findings in src/mcp/mcp.c and
src/pipeline/pipeline_incremental.c. No unrelated lint cleanup is included here.

Checklist

  • Every commit is signed off (git commit -s) — required, CI rejects
    unsigned commits (DCO, see CONTRIBUTING.md)
  • Tests pass locally (make -f Makefile.cbm test)
  • Lint passes (make -f Makefile.cbm lint-ci)
  • New behavior is covered by a test (reproduce-first for bug fixes)

Signed-off-by: Pcristin <xxxokzxxx@protonmail.com>
@pcristin
pcristin requested a review from DeusData as a code owner August 23, 2026 22:15
@github-actions

Copy link
Copy Markdown

Thanks for opening this — it has been seen, and it is queued.

This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence.

Current review status: working through a backlog. 0.9.1-rc.1 is out, so the release freeze that held reviews is over — but it left a large queue of open pull requests behind it, and we are reading through them oldest-first. The background is in discussion #1144.

What that means for this PR, concretely:

  • It will not be closed for inactivity. No stale bot touches pull requests here.
  • It may still sit a while before a human reads it. That is on us, not on you.
  • Older PRs are read first, so a recent one is not being skipped — it is behind a queue.

Things that will genuinely speed it up whenever review does happen:

  • Keep it rebased on main — the tree is moving quickly right now, and a conflicting branch cannot be reviewed as the diff you intended.
  • Get CI green, or say which failures you believe are pre-existing.
  • Keep the change to one claim. Bundled features and refactors get split before they get merged, which costs you a round trip.
  • Every commit needs a sign-off (git commit -s) — CI enforces DCO.

If this fixes a bug, a reproduction we can run is worth more than a description of the symptom.

Thanks for contributing, and sorry in advance for the wait.

@pcristin

pcristin commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

CI triage: the only substantive red job is test / test-windows-guards, where section_cold_storm lost one of six concurrent clients while they raced to spawn the ephemeral daemon. All dedicated Windows test shards, sanitizers, lint, security, and DCO jobs passed.

This PR changes only FQN/import resolution and its regression tests; it does not touch daemon or Windows-guard code. The same cold-storm timeout occurred on the unrelated PR #1245 workflow run, while surrounding runs of this guard passed, so this matches an
existing intermittent guard failure rather than this patch.

I tried to rerun only the failed jobs, but GitHub rejected it because contributors do not have repository Actions rerun permission. Could you @DeusData rerun the failed jobs? I have deliberately not added an unrelated code change or empty commit just to retrigger CI.

@DeusData DeusData added bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges priority/high Needs near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker. labels Aug 24, 2026
@DeusData

Copy link
Copy Markdown
Owner

Thank you for the careful CI attribution. I checked the diff and current main: this PR is limited to FQN and import resolution plus its regression tests, while the red job is the Windows daemon guard. That failure is outside this change path and matches the existing startup-flake family you linked.

You are also correct that contributors cannot rerun repository jobs. This should be rerun from the maintainer side, and there is no need to create an unrelated commit. Thank you for documenting the evidence instead of treating the red aggregate as proof against the patch.

@DeusData

DeusData commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Approved on merit. The one red is not yours, and I can be specific about that.

The failure

test / test-unix (macos-15-intel) fails at:

lock_registry_absolute_deadline_survives_repeated_wakes
  FAIL tests/test_lock_registry.c:1153: ASSERT(tail_queued)

with run totals 7617 passed, 1 failed. Your change touches src/pipeline/fqn.c and src/pipeline/pass_pkgmap.c — the import-path resolver. It cannot reach the lock registry.

This is a known flake we have already diagnosed: the assertion's verdict is fed by a 100 ms wall-clock window, so a loaded runner decides the result rather than the code. We saw the identical signature — same test, same line, same platform — on 28 August on an unrelated NetBSD-only #ifdef change. Your PR is the second unrelated diff to be reddened by it, which I have recorded; it makes fixing it properly a priority rather than a curiosity. Nothing for you to do.

On the change

The bug is a good one to have found, because the old code encoded a false rule: the text after the final dot is an extension. For featureX.engine that silently rewrites the module identity, and the resulting IMPORTS edges point at a module that does not exist. Stripping only recognised JS/TS module extensions replaces a guess with a fact, which is the right direction.

Two things I want to credit:

Removing the second, generic strip after the relative resolver has normalised the path. Double-stripping is the kind of bug that hides behind a passing test suite for years, because it only bites inputs that survive the first pass with a dot still in them. Noticing that the two stages overlapped is more valuable than the extension list itself.

Asserting both edges in the regressionhelperB and SomeType both targeting featureX.engine.ts. A value import and a type import take different paths through the resolver, so pinning only one would have left half the fix unguarded.

On your lint note

the formatter reports existing findings in src/mcp/mcp.c and src/pipeline/pipeline_incremental.c

That is a false positive on your side, not drift on ours, and you are the third contributor to hit it this week. Our gate requires the Homebrew LLVM clang-format; a distro or standalone clang-format-20 reports whole-file differences on exactly those large files. I ran make -f Makefile.cbm lint-ci against current main today with Homebrew clang-format 22.1.8 and it exits clean. So your instinct to include no unrelated lint cleanup was exactly right — there was nothing to clean.

I will raise making that explicit in CONTRIBUTING, since three people have now spent time on it.

Before merge

Four checks are still queued. Our Actions pool is servicing roughly one job at a time against 21 queued PR runs, so this is slow for reasons unrelated to your PR. I will merge once it settles, and the lock_registry red is not a blocker.

@DeusData

DeusData commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Maintainer notice: please disregard comments from @adfjadfj16-a11y on this thread

@adfjadfj16-a11y is not a maintainer of this project and does not speak for it. That account has posted replies on 17 threads here written in the project's voice — promising merges, announcing that a case has been "escalated to the development team", asking to close issues, and in some threads replying as though it were the author of someone else's pull request. None of those were maintainer decisions, and none of them carried any weight.

@DeusData is the only account that gives a maintainer response on this repository. If a comment about the fate of your issue or pull request did not come from @DeusData, it is not a decision, however official it reads.

If you were waiting on something because of one of those comments — a promised merge, a review "immediately", a request to close your ticket — I am sorry. That was noise you had no way to identify as noise, and it should not have been on your thread. Your issue or PR is judged on its own merits, and I will answer it here myself.

Nothing in this notice reflects on your contribution. Thank you for your patience, and thank you for the work.

@pcristin

pcristin commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

The latest red check appears unrelated to this PR's #1682 changes and is caused by an upstream toolchain change.

The failing job is test / test-lsan-macos: https://github.com/DeusData/codebase-memory-mcp/actions/runs/33745916176/job/100622049644

It fails during compilation with:

src/cli/cli.c:1768:21: error: variable 'g_mcp_command_path_probe_counter' set but not used [-Werror,-Wunused-but-set-global]

The previous LSan run on this PR installed Homebrew LLVM 22.1.8 and passed. This run installed the newly available LLVM 23.1.0 through the workflow's unpinned brew install llvm ccache, which exposes the existing POSIX test-build diagnostic.

The PR branch's src/cli/cli.c is identical to current upstream main; the PR diff remains limited to the intended FQN/import files. The latest merge from main also changed only src/mcp/mcp.c and tests/test_mcp.c.

This likely needs an upstream fix to make the test-only probe counter platform-correct, or a temporary LLVM pin. Another branch update or unrelated change in this PR should not be necessary.

@DeusData
DeusData dismissed stale reviews from adfjadfj16-a11y and adfjadfj16-a11y September 3, 2026 11:50

Dismissed by the maintainer: this account is not a member of the maintainer team and its reviews carry no weight here. Only reviews from DeusData are maintainer decisions.

@DeusData

DeusData commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Thank you — that diagnosis is exactly right, and it was the first sighting of a real problem.

Run 33745916176 poured Homebrew LLVM 23.1.0 and died at src/cli/cli.c:1768 under -Wunused-but-set-global; the run on your current head drew the 22.1.8 bottle and got past the compile, which is why the two runs look different. The compile red is main's, not yours: the counter's only read is Windows-only, so the POSIX store is genuinely dead and Clang 23 is correct to say so. The fix is #2027.

The remaining red on your current head (subprocess_run_spawn_failure, test_subprocess.c:272) is the sanitizer-lane spawn-starvation family I described above — also not yours. I have re-queued the full run; once #2027 is on main I will make sure this gets a run against it, and it merges on green. Nothing needed from you.

@DeusData
DeusData merged commit 3bbabf1 into DeusData:main Sep 4, 2026
34 checks passed
@DeusData

DeusData commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Merged as 3bbabf1 — thank you, and thanks for the patience across the reruns and the LLVM 23 compile detour (that one was ours, fixed in #2027). Dotted TypeScript import basenames now keep their full name through fqn.c and the package map, so foo.service no longer collapses to foo and the IMPORTS edges land on the right module. Really appreciate you seeing #1682 through.

@pcristin
pcristin deleted the fix/issue-1682-dotted-ts-imports branch September 4, 2026 08:33
birhantprkc pushed a commit to birhantprkc/codebase-memory-mcp that referenced this pull request Sep 4, 2026
The test-lsan-macos leg installs the unversioned `llvm` formula, which
tracks Homebrew's current stable. That moved from 22.1.8 to 23.1.0 today,
so the leg's compiler now depends on which bottle the runner image draws:
run 33745916176 (PR DeusData#1811) poured 23.1.0 and died at compile on a new
Clang 23 diagnostic (-Wunused-but-set-global under -Werror); the run an
hour earlier poured 22.1.8 and built fine. Same code, two verdicts.

Pin the formula (and the `brew --prefix` lookup) to llvm@22 — the version
every green run of this leg has used so far. Moving to a newer major
becomes a deliberate edit of these two lines instead of an accident of
the runner image.

The diagnostic itself is fixed independently in DeusData#2027 so main compiles
under both majors; this change is about determinism of the leg, not the
warning.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
DeusData added a commit that referenced this pull request Sep 4, 2026
…istic

lock_registry_absolute_deadline_survives_repeated_wakes has failed on the
test-unix (macos-15-intel) leg of three unrelated pull requests in one
week -- #1342 (08-28), #1811 (09-02) and #1819 (09-03, run 33799475629,
job 100823626965) -- always with the same signature:

  FAIL tests/test_lock_registry.c:1153: ASSERT(tail_queued)
  7648 passed / 1 failed

The registry is not racy. cbm_lock_registry_acquire enqueues the waiter
synchronously under the registry mutex before any wait, so waiter_count
and the attempting count are exact. The defect is in the fixture: it
raced two wall-clock windows against each other, both anchored to a
timestamp the observer thread took before the tail thread had even been
scheduled.

  deadline_start = cbm_now_ms();
  tail.deadline_ms = deadline_start + 200;  /* the tail's acquire deadline */
  queue_deadline   = deadline_start + 100;  /* the observer's budget */

Because both windows start before the tail runs, a loaded runner breaks
the fixture two different ways:

  * the tail is scheduled inside its deadline but after the observer's
    100 ms budget has expired -- the queued state existed and was simply
    no longer being looked at; or
  * the tail is scheduled more than 200 ms late, in which case its
    deadline has already passed when it finally calls acquire, the
    pre-registration deadline check in lock_registry_acquire_internal
    returns BUSY immediately, and the tail never enqueues at all -- the
    asserted state can then never occur, however long the observer waits.

lock_registry is in the parallel wave of run-tests-parallel.sh, not the
serial tail, so on a small CI runner it competes with a full wave of
sanitized suites -- exactly the scheduling delay both paths need.

Widening the observer's budget would only paper over the first path, and
the state it waits for is transient by construction: it exists only
between the tail's enqueue and the tail's own deadline. So the fixture is
rebuilt to observe states that cannot evaporate.

  * The tail anchors its absolute deadline itself, in its own thread,
    immediately before the acquire it bounds. Scheduling delay can no
    longer consume the deadline before the call starts, so the enqueue is
    unconditional, and elapsed is measured from the tail's own anchor --
    it now times the registry instead of timing the scheduler.

  * Enqueue is exposed as a monotonic counter,
    cbm_lock_registry_waiter_enqueue_count_for_test, next to the existing
    test_condition_wait_calls counter it is modelled on. Because the
    count only ever grows, the observer reads it once after the tail has
    returned rather than trying to catch a live queue depth: the polling
    loop, and with it the window, is gone.

  * The fixture's remaining 500 ms and 600 ms budgets become the file's
    LOCK_REGISTRY_TEST_TIMEOUT_MS backstop, and each loop exits on the
    state it waits for instead of on the clock, so the backstop only
    fires when the product is actually broken.

The contract is unchanged: the tail must still return at its absolute
deadline (150 <= elapsed < 350 ms for a 200 ms deadline) despite ~40
unrelated cancel broadcasts, still with BUSY and no lease, with the head
still holding the attempt. The broadcast loop now starts immediately
after the tail is released, so it overlaps the tail's wait at least as
much as it did before.

Verification, all on macOS arm64 with the sanitized runner:

  * The mechanism was reproduced locally by delaying only the tail thread
    after its start gate, with production untouched. A 120 ms delay (the
    state exists, outside the observer's budget) and a 250 ms delay (the
    tail never enqueues) each produced exactly one failure,
    ASSERT(tail_queued) -- the CI signature.
  * After the rebuild the same injections are green at 120, 250, 400 and
    900 ms: an arbitrary scheduling delay no longer decides the verdict.
  * lock_registry 30/30 green plain and 30/30 green under four CPU hogs;
    16/16 inside the saturated 18-job parallel wave.
  * private_file_lock, lock_registry, daemon, project_lock and the
    daemon_* suites: 222 passed, 1 skipped.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges priority/high Needs near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants