Skip to content

sync(13A): merge upstream checkpoint 5dc83ac9 into the CLI fork - #29

Closed
ngallodev wants to merge 89 commits into
sync/ci-guard-20261101from
sync/upstream-13a-20261101
Closed

ngallodev wants to merge 89 commits into
sync/ci-guard-20261101from
sync/upstream-13a-20261101

Conversation

@ngallodev

@ngallodev ngallodev commented Nov 1, 2026 •

Copy link
Copy Markdown
Owner

Merge upstream checkpoint 5dc83ac9fa363d51706a70977840b61ea59ce9db into the CLI-first fork with true ancestry: merge a03f1f8ab85e8861d8d6820061ccfd88797efae1 retains fork parent ff8b8906c6807953336609cc7f464e7e4ef3cf7b and that exact upstream parent. The checkpoint includes 79 commits; 854 pinned campaign commits remain. This stacked draft targets #28, which targets security PR #27. Do not merge independently or automatically.

Preserve native CLI operations, JSON output, daemon integration and Jenkins ownership. Adapt Python C3, Kotlin typed receivers, Rust generic scopes, registry/property handling, deterministic data flows, SQLite settings recovery and test-impact changes into the fork. Index format 3 stops inventing Docker registry hosts and forces old image identities through a full reindex. Keep MCP server/session/transport and automatic GitHub workflows excluded.

The 302,808,096-byte production binary exceeds the old archive member limit. Use a finite 512 MiB member ceiling consistently in npm/PyPI/Go while retaining compressed 256 MiB, 64-member and total expanded 512 MiB bounds. Real-binary extraction and execution passed through npm and PyPI. Preserve fork release metadata/checksum pins and omit the unsupported upstream MCP wrapper smoke driver.

Full-suite preparation exposed stale contracts after the Jenkins-only policy removed pr.yml. The Windows/smoke/venue/lane checks now validate retained manual workflows and Jenkins preparation; security permissions remain checked for every actual caller. The metadata contract checks six registry versions for agreement and preserves four artifact pins rather than treating mixed-origin Git tags as published fork releases. Its regression fixture accepts an unrelated v99.0.0 tag while rejecting registry-version and frozen-pin drift. Publication freshness remains a separate release qualification.

Validation: production build; 1,337 core/language tests; 190 storage tests; 139 parallel/determinism tests; npm 22 passed / 4 Windows skips; PyPI 44 passed; Go tests passed; 21 selector tests; 2/2 corrected image regressions under ASan/UBSan. The complete local preparation phase now passes all contracts. The initial combined extra-suite run failed on stale image expectations; those two cases were corrected and rerun, while the full union is being qualified in Jenkins.

Current candidate and release-tooling: 598d7c7145722e5f7c59819c1dcacd9f73c259ac. The existing release-tooling job is running the full gate with CBM_TEST_SUITES empty: http://192.168.88.146:8080/job/codebase-memory-cli-release-tooling/84/. Its SCM configuration was not changed. The earlier special job failed in the retired-workflow contract; source/test evidence is retained. Running is not passed.

Native Windows remains unverified. Diff-scoped clang-tidy previously failed with out-of-range diagnostics and its cause remains unisolated; CodeRabbit credentials were unavailable. Initial AW compatibility workers lacked bound acceptance commands and remain unaccepted; source verification and Jenkins gates are separate. No main push, PR merge, auto-merge, or hosted Actions job was performed. See docs/upstream-sync/13a.md, PLAN.md and ledger.json for source and adaptation receipts.

kaNEGY and others added 30 commits September 29, 2026 08:31
The v0.12.0 release smoke blocked every binary in its string audit:
"BLOCKED: Dangerous commands found in binary: wget". The line is the bare
string "wget" that src/pipeline/pass_shell.c compares a script's program
name with, and records as the `via` of a curl / wget HTTP_CALLS edge
(3b93db0). The binary never runs it.

Allow that whole line only, like the rst grammar's bare "telnet". A line
that carries a wget command (flags, a target, a URL) stays blocked; the
contract test now pins both cases.

Proof on the release run's own artifacts (run 38644765106, main 8df0639):
linux-amd64-portable and darwin-arm64 binaries BLOCKED before, all three
audits OK after. test_security_strings_allowlist.sh: 49 passed; with the
allowlist line reverted, the new bare-token case fails.

Signed-off-by: Martin Vogel <[email protected]>
Nondeterministic Windows reds came from races on _config.db:
test-windows-guards section_start_status_port / daemon_lifecycle ("the
daemon did not accept the UI configuration"), section_churn_stability
("could not load saved runtime settings"), the windows-2025 release
smoke whose `--ui=true --port` server exited about 5 s after start
(Phase 15, read as "no embedded UI assets"), and section_crash_recovery
("the stale daemon state never cleared").

- Every _config.db connection now waits out a committing writer
  (cbm_runtime_settings_wait_for_writers: one busy handler, logs
  config_db.busy_wait once per busy wait, a 3 s bound for a wedged
  holder). Startup's 50 ms window let a daemon's routine commit end
  unrelated CLI starts; cbm_config_open and the UI load had no wait at
  all, so a concurrent commit failed the daemon's UI save and made the
  load keep defaults.
- A process killed mid-write (crash, taskkill /F, power loss) left a hot
  rollback journal that the read-only settings reads cannot roll back
  (SQLITE_READONLY_ROLLBACK). Every later command then failed with
  "could not load saved runtime settings", permanently. Settings startup
  and the UI load now recover once through a read-write open that rolls
  the interrupted write back (config_db.hot_journal_recovered); a failed
  recovery is reported with the journal path and stays fatal.
- write_value no longer rewrites an unchanged value. The upsert fired the
  revision trigger, so every `daemon start` on a UI build committed and
  locked readers out although nothing changed.
- `daemon start` and the stdio server wait for the set_context and
  set_ui_config replies within their startup budget instead of the 1 s
  probe budget (MAIN_CONNECT_TIMEOUT_MS) that decided the command
  whenever the daemon's save ran long.

Tests, red on 8df0639 and green here:
- runtime_settings suite: three single-threaded lock tests (a log sink
  commits the held lock when the waiter logs config_db.busy_wait, so no
  test depends on a duration) and two hot-journal tests (a portable
  fixture snapshots the database and its journal mid-transaction and
  checks the journal is hot before the code under test runs).
- tests/windows/test_daemon_stability.py: new section
  start_port_waits_for_settings_writer holds the lock against a real
  `daemon start --port` and releases it on events; the crash section
  now prints the status output it saw.

Signed-off-by: Martin Vogel <[email protected]>
The license gate installed `scancode-toolkit` unpinned. pluggy 1.7.0
(uploaded to PyPI 2026-10-15 09:50 UTC) no longer finds the hookspecs that
plugincode 32.0.0 declares on a class (`@pre_scan_spec class
PreScanPlugin`), so scancode crashes at import with "ValueError: did not
find any 'pre_scan' hooks" and `security / license-gate` fails on every
run, whatever the tree. The last green gate started at 09:50:14 UTC;
every run since is red. `ci-ok` and the release `verify` job both need the
security workflow, so this blocks every PR and the release.

Install exactly scancode-toolkit 32.5.0 (the version every green run
used) with pluggy constrained to 1.6.0 through PIP_CONSTRAINT, which the
pip that pipx runs reads. The local hint in license-gate.sh names the
same command.

Signed-off-by: Martin Vogel <[email protected]>
fix(security): allow the bare wget token the shell pass compares
Every packaging surface states the newest v-prefixed tag, as the
version-metadata contract requires: the Chocolatey nuspec and installer
(checksum re-pinned to the released windows-amd64 archive), the Go
installer, the Nix flake, server.json, the npm and PyPI wrappers.

Signed-off-by: Martin Vogel <[email protected]>
The version-metadata contract tracks pkg/scoop as a release surface, and
the first sync commit missed it: version, both download URLs and both
Windows archive hashes, taken from the release's checksums.txt.

Signed-off-by: Martin Vogel <[email protected]>
The badge tracked dry-run.yml, which runs only when dispatched; its last
runs on main were cancelled or failed during the v0.12.0 preparation, so it
read "failing" although main passed the full matrix in the v0.12.0 release
run. release.yml runs the same full matrix on main for every release.

Signed-off-by: Martin Vogel <[email protected]>
An image reference that names no registry host was stored under an
invented one: `FROM nginx` became docker.io/library/nginx, `image:
acme/web` docker.io/acme/web, and a local `docker build -t myapp` or a
skaffold artifact `image: api` docker.io/library/myapp. docker.io is only
Docker's default. Podman and CRI-O resolve a short name through a search
list, mirrors rewrite it, and a local build tag may exist on no registry
at all. The graph stated a host the code never names.

An Image is now the repository as written, tag and digest dropped, with
a `registry` property: the host the reference names, else "unknown". A
stated host is kept as written; Docker Hub's spellings (docker.io,
index.docker.io, registry-1.docker.io) are docker.io, with library/ for
an official one-segment name. This holds for every source: FROM and
COPY --from, compose services, K8s containers, shell and skaffold build
tags, and the per-component Images of a repository built from several
Dockerfiles.

`FROM nginx` and `image: docker.io/library/nginx` are now two Image
nodes. Relating them would state the host again, so the graph does not.

The Image QN changes (__image__nginx instead of
__image__docker.io/library/nginx), so CBM_INDEX_FORMAT_VERSION moves to
3. Refreshed in place, an older index would give only touched files the
new identity and hold both forms of one image; every existing index is
rebuilt once on its first index after upgrading.

Signed-off-by: Martin Vogel <[email protected]>
chore(pkg): sync packaging metadata to v0.12.0
A Chart node had one kind of outgoing edge, DEPENDS_ON for a dependency
its Chart.yaml declares. A chart without dependencies, most of them, was
an isolated leaf: nothing linked it to the objects its templates render,
to its values files, or to the images it runs. On 20 pinned infra
corpora, 238 of 260 Charts had no outgoing edge, while 2,626 objects sat
in chart templates/ directories.

- Chart -DEPLOYS {via: chart}-> each Resource of <chart>/templates/, for
  its nearest enclosing chart: a subchart's objects are the subchart's.
  The same edge a Flux Kustomization draws to what it applies.
- values.yaml / values-<x>.yaml beside Chart.yaml -CONFIGURES {strategy:
  helm_values}-> the Chart.
- Chart -DEPLOYS {via: chart, ref: image}-> each Image its objects name
  literally, read after pass_docker.c moved references onto component
  Images. A templated image names no Image, and no values default is read.

An incremental closure repair re-runs the K8s pass over its plan only, so
a values file or a template edited alone would lose the chart's edge; such
an edit now declines to the full rebuild, like a Chart.yaml edit.

Signed-off-by: Martin Vogel <[email protected]>
…pers

v0.12.0 could not be installed through npm, pnpm, pip or the Go wrapper on
any platform (DeusData#2657): each wrapper refused an archive member above 256 MiB,
and every v0.12.0 binary is 331-335 MB. The v0.11.0 binaries were already
about 300 MB, so the Go wrapper, which has had the cap since v0.10.0, was
broken before; npm and PyPI gained it in v0.12.0. The archive is verified
against the release's checksums.txt before it is unpacked, so a byte cap
only ever refused what we ship.

- npm, PyPI, Go: delete every byte-size cap (compressed archive, per member,
  aggregate, checksum manifest, download size). The checksum, the exact
  member set, path and link refusal, the member count, HTTPS and the
  --version check stay.
- All three honour CBM_DOWNLOAD_URL like install.sh, for testing: https, or
  plain http to an exact loopback authority with no proxy and no redirect.
- Smoke: scripts/smoke-wrappers.sh installs the three wrappers from the
  checkout against the release fixture and runs the binary each one
  installed. smoke-test.sh Phase 13w runs it; SMOKE_REQUIRE_WRAPPERS=1 makes
  it required on the PR smoke lanes and in the release smoke, which gates
  publishing.

Other install paths found broken while checking every channel:
- Homebrew: the formula was still at 0.10.3 and installed the dynamic Linux
  build, which needs glibc 2.38 (Ubuntu 22.04, Debian 12 and RHEL 9 lack it).
  It now installs 0.12.0 with the static -portable Linux assets and tracks
  the newest release in the version contract like the other surfaces.
- Go: `go install .../pkg/go/cmd/[email protected]` never worked
  (no pkg/go/v* tags, so Go fetched the whole repository, over its 500 MB
  module limit), and @latest built main's wrapper, whose version constant
  lags each release. The release now also tags pkg/go/vX.Y.Z, and the
  wrapper installs its own module version (the constant only for local and
  untagged builds).
- npm: a stable release also moves the `next` dist-tag to itself; `next`
  still pointed to 0.9.1-rc.1.
- Docs: winget and Chocolatey were listed as install channels but are not
  published; they are removed until they are. Windows arm64 ships and is
  now listed.

Fixes DeusData#2657.

Signed-off-by: Martin Vogel <[email protected]>
…dge-release

docs(readme): point the main CI badge at the release workflow
…stry

fix(docker): never invent a registry host for an image
The v0.12.1 release smoke failed on every leg in Phase 13w, the
package-wrapper install gate added in DeusData#2664:

- macOS: the runner images have no Go on PATH, and
  SMOKE_REQUIRE_WRAPPERS=1 rightly fails without one. pr-smoke and the
  three release smoke jobs now set up Go from pkg/go/go.mod, with the
  same pinned step the wrapper test job uses.
- Windows: `mkdir -m 700` changes the mode in a second step, which MSYS2
  cannot do under the smoke profile's owner-only DACL. mktemp -d sets
  the mode at creation.
- Linux: the runner's older Go downloaded the 1.26.1 toolchain into the
  smoke profile's HOME. Go writes its module cache read-only, so the
  harness could not delete its profile afterwards. All Go state now stays
  in the wrapper's own work tree, and its cleanup restores write
  permission before removing it.

npm and PyPI passed on every leg that reached them; the gate itself is
unchanged.

Signed-off-by: Martin Vogel <[email protected]>
Every release surface of the version-metadata contract states the
newest tag: the Chocolatey nuspec and installer (checksum re-pinned to
the released windows-amd64 archive), the Scoop manifest (both Windows
archive hashes), the Homebrew formula (all four archive hashes; Linux
installs the static -portable builds), the Go installer, the Nix flake,
server.json, and the npm and PyPI wrappers. Every hash is taken from the
release's checksums.txt.

Signed-off-by: Martin Vogel <[email protected]>
…through macros

The first commit of this branch is the Smart CI change as of the rebase
onto 9f85f10. A review of it found places where the engine could run
fewer tests than a change needs; each now runs everything or selects the
right tests, with a test that fails when its fix is reverted.

Engine:
- A `#define NAME "literal"` line counted as naming a role but selected
  nobody, so the tests that start the blocking-git probe through their
  marker macros would not have run. The scan now follows NAME, as a whole
  word, to the code that uses it, through chains of up to 4 macros; a
  define it cannot follow runs everything.
- main dispatches through the role table, so no edge leads from main to a
  handler. A table entry the engine cannot read, or whose handler is not
  exactly one function, was skipped; it now runs everything.
- In a runner file, only a test case names a role's literal. The runner's
  own helper that reads the marker no longer counts as a spawner, so a
  role only the runner names runs everything again.
- A handler reached first by a parse gap or by the spawn lift was never
  lifted. Role lifts and parse gaps now run to a fixpoint, before the
  runner check and again after the spawn lift.
- A reached sink that main calls (the blocking-git probe) counted as a way
  into main and hid the real one: DeusData#2644 now names the start-up path main
  -> cbm_index_supervisor_capture_build_fingerprint.
- No pointer past the end of a role line; the RUNNER_REACHED note clamps
  its prefix.

CI:
- pkg/npm/README.md, which test_cli reads, runs the test legs instead of
  the docs tier.
- The build rule lists the harness scripts the test legs run:
  run-test-wave.py, path-safety.sh, clean.sh.
- The revert guard rejects the ancestor's coverage when a diff fails.
- The vetoed selection is uploaded (test-selection-vetoed).

Docs: SMART_CI.md states the new fail-safe cases, the version that lacks
the new config keys, the selection base, and that the narrowed leg builds
with gcc while the coverage comes from clang.

Signed-off-by: Martin Vogel <[email protected]>
… replay

README.md, the site files and pkg/npm/README.md are read by test_cli, so
a change to one now runs the test legs (T1-tests). The September replay
held 15 README pushes to the docs tier the analysis assigned and failed
every test leg's contract step. Those rows are now a documented
deviation, read-by-tests, which like makefile-by-name may only raise a
tier: 767 pushes as expected, 53 documented fail-safe deviations, all 22
real failures still caught.

Signed-off-by: Martin Vogel <[email protected]>
Why
The Python def walk stopped at every function_definition: it extracted
the def and never looked at its body. Every def or class declared inside
a function -- closures, decorator wrappers, the route handlers of a Flask
or FastAPI app factory (`@app.route` inside create_app), local classes and
their methods -- was absent from the graph. Blocks at module level (if /
try / for / with) were transparent, so only function bodies were blind.
The calls inside those defs were not re-attributed either: the call-scope
walk named a nested def by its class or module only (`pkg.mod.nested`, a
QN no node had), so the edges fell back to the file node, and inbound
traces of the called function silently lost the caller. A def nested in a
method got the method's own QN (`Tree.visit` for the `def visit` inside
method Tree.visit), so its calls, recursion included, landed on the
method. On an app-factory codebase this removes the whole HTTP layer.

Fix
- Extraction (extract_defs.c): after a Python def is extracted, its body
  is walked with the def's QN as the enclosing scope; methods' bodies are
  walked under the method QN. A nested def or class is qualified by the
  def it sits in -- pkg.mod.create_app.index, pkg.mod.Tree.visit.visit,
  pkg.mod.create_app.Settings.value -- the QN the Python LSP already gives
  the calls inside it (py_process_function). Decorated nested defs keep
  their decorators, so their route_path mints the Route and HANDLES.
  Lambdas and comprehensions hold no statements and stay as they are.
- Call scope (extract_unified.c): for Python the nearest named scope, a
  def or a class, prefixes a nested def or class, so every call, usage and
  env read inside a nested def carries the nested def's QN.
- A def nested in a function is a local of it (Python LEGB), so it must
  not become a global name: a Python symbol whose QN extends a
  Function/Method node is registered for exact lookups only, never in the
  short-name index (registry.c cbm_registry_add_for_language, used by the
  full, parallel and incremental registration sites alike). Without this,
  django's per-test `class MyModelAdmin` and every decorator's `def
  wrapper` became unique_name / suffix_match targets for unrelated calls.
  The incremental seed derives each stored file's language the way
  discovery does (name, then shebang), so it keeps the same symbols out.
  The import symbol-name fallback skips such locals too (pass_pkgmap.c),
  and the Python LSP no longer binds a def-local class module-wide by its
  short name (py_lsp.c).
- A bare call now resolves lexically first (registry.c
  cbm_registry_resolve_lexical, strategy lexical_scope): the def or class
  bound in the nearest enclosing function, skipping class bodies, stopping
  at the module. The sequential and parallel call passes use it
  identically, and so does the handler lookup of a call-registered route:
  `app.add_url_rule("/ping", "ping", ping)` in create_app reaches the
  local ping.

Proof (real code; every node and edge diffed, main 1f9b4db vs this)
- pallets/flask examples/tutorial (flaskr, create_app factory): the
  nested `hello` handler is now create_app.hello with HANDLES to
  /hello; 4 nested defs/classes added, 0 nodes and 0 edges removed.
- pallets/flask d73fa1c (tests declare handlers inside test functions):
  Function 532 -> 1068, Method 318 -> 381, Class 130 -> 209. The +678
  equals the 678 unique nested def/class QNs Python's own ast finds.
  Handler HANDLES (decorators and add_url_rule) 32 -> 296. 0 nodes
  removed, 0 duplicate QNs.
  The 94 removed CALLS: 90 moved from the file node onto the nested def
  that makes the call, 4 replaced by the lexically bound local.
- django fb11376 (local, 2,927 .py files): nodes 55,483 -> 60,052,
  Function 1,992 -> 3,027, Method 28,850 -> 29,491, Class 8,187 ->
  11,073. 0 nodes removed and 0 duplicate QNs. Every added
  Function/Method/Class sits under a Function/Method of the same file,
  and they match ast's 4,567 nested QNs except for 5 methods declared in
  an `if` inside a local class body (class-body `if` is not walked for
  any class). CALLS 62,430 -> 63,815. Every added CALLS edge has a nested
  def at one end: 1,015 from nested defs, 1,219 lexical_scope into a
  local, and none from outside the local's function. Of the 849 removed:
  507 moved from the file node onto the nested def, 334 replaced by the
  local the name binds, and 8 were false on main, all checked (e.g. the
  recursive `get_actions` nested in call_command had been suffix-matched
  to ModelAdmin.get_actions). HANDLES unchanged (135).
- Samples checked against the source:
  AbstractBaseUser.check_password.setter -> set_password / save;
  View.as_view.view -> setup / dispatch;
  Apps.lazy_model_operation -> lazy_model_operation.apply_next_model
  (line 426);
  InstrumentedASGIRequest.META -> the local InstrumentedDict (line 279);
  flask test_provide_automatic_options_arg_disable.index -> GET /.

Tests
- extraction: extract_python_nested_def_qualified_by_enclosing_def,
  _calls_attributed_to_it, _decorated_nested_route_handler,
  _nested_class, _nested_def_named_like_its_method,
  _lambda_and_comprehension_stay_in_enclosing_def (control),
  _nested_def_env_access_attributed_to_it (all _issue1548).
- pipeline: pipeline_python_app_factory_routes, _nested_def_is_function_
  local, _local_classes_stay_in_their_def, _import_never_binds_a_local_def,
  _nested_defs_parallel (>= 50 files, CBM_WORKERS=4),
  _nested_def_local_after_incremental (all _issue1548).
- registry: registry_python_function_local_is_exact_only,
  registry_resolve_lexical_walks_enclosing_defs (both _issue1548).
The extraction and pipeline tests were RED on main 3/3 for the asserted
reason and are green with the fix; the registry tests cover the new
registry API. Each production piece was reverted on its own, and each
revert turns at least one of these tests RED.

Fixes DeusData#1548
Signed-off-by: Martin Vogel <[email protected]>
(cherry picked from commit 62fda43fd66200879db62a58903a32dab0dd1a20)
…after it

Re-port onto current main (agreed with lane L7):
- The Python LSP binds every def/class a function body defines as a local
  before walking the body (LEGB): an undecorated def as an exact callable
  alias to its nested QN, anything else as a hard shadow, so no call falls
  through to a same-named module symbol. Defs inside the body's compound
  statements count too, and their bodies are now walked.
- Classes declared in a function are walked under the function's QN
  (py_process_class_in), so super()/self calls in their methods resolve.
- cbm_registry_resolve_lexical moves AFTER the LSP override: both resolvers
  call one entry point, cbm_registry_resolve_call_scoped, at the same place
  (before the language-aware chain). It never uses the per-file resolve cache.
- Main's cbm_registry_add_lang carries the def-local exclusion, so every
  registration site (full, parallel, incremental seed) applies it; the
  separate cbm_registry_add_for_language and the second incremental language
  derivation are dropped.
- The pass_pkgmap.c def-local import skip is its own continue.

Tests: local-vs-module shadowing in both orders, a decorated local, and a
function-local class's super()/self calls, sequential and parallel.

Signed-off-by: Martin Vogel <[email protected]>
`import pkg.mod.nodes` binds the ROOT name `pkg`, so `class X(pkg.mod.nodes.Context)`
names module pkg.mod.nodes's Context. The cross-LSP base resolution asked
the registry, whose import_map step joined the imported MODULE (the
IMPORTS edge target, pkg.mod.nodes) with the whole remaining spelling
(mod.nodes.Context) and missed; the base kept its raw spelling, so the
Python LSP's inheritance view never saw it. Every member inherited through
a dotted base fell to a name guess or to nothing: self.m() became
unique_name, super().m() suffix_match, super().__init__() only resolved
through a synthesized QN.

pxc_resolve_base_qn now resolves such a spelling against the module the
import names: the import map's module when the root local is unique there,
else the dotted module path under the project's QN rule. Python only,
import-backed and exact (no short-name step), and only a type-like project
node is accepted. `import a.b as m` and `from a import b` bind the module
itself and keep resolving through the import map.

Tests: python_dotted_base_inheritance(_parallel): self.m(), super().m()
and super().__init__() through a dotted base resolve by the LSP; the
from-imported control keeps resolving; an untyped receiver stays without
an LSP edge.

Signed-off-by: Martin Vogel <[email protected]>
The sequential pipeline (50 files or fewer, one worker, CBM_WORKERS=1)
linked a method's DEFINES_METHOD edge while it was still registering
files. A method defined in a file the directory walk returns before its
type's file -- a Go method in another file of its package, an out-of-line
C++ method in foo.cpp before foo.h -- found no parent and lost the edge,
and with it the IMPLEMENTS and OVERRIDE edges derived from it. The
parallel registry build links after every node exists, so the same input
gave different graphs depending on repository size and worker count, and
on the order the filesystem enumerates a directory.

With the extraction cache, DEFINES_METHOD and diagram parent edges are now
linked in one pass after Phase 1, as the parallel registry build does.
Without the cache (allocation failure) each file still links its own.

The test pair puts each of two Go types in the file of the other's
method, so one method precedes its type whatever the walk order: RED on
main for the sequential venue (alpha_method == 0), and the venue-parity
case compares the padded input through both resolvers.

Signed-off-by: Martin Vogel <[email protected]>
Both Rust registries were built from the pipeline's mixed-language def
set. The shared Tier-2 build (cbm_rust_build_cross_registry) and the
per-file conversion (pxc_lspdefs_to_rust) copied every def, so a Perl
`sub new` or any C function became a Rust free function. The
lsp_short_name_unique fallback then bound `Store::new()` to the Perl
constructor at confidence 0.90 on both venues: its "crate scope" check
compares only the first module-QN segment, which is the project name.
(Found by the generic-engine lane on a 12-language fixture.)

Register Rust defs only, at both conversion points, exactly as the Go
builder filters to Go. Rust impl-relation records already carry
CBM_LANG_RUST. As a side effect, the shared Rust build no longer
registers the C defs of a mixed C+Rust tree.

Tests: pipeline_rust_call_never_binds_another_language (sequential and
parallel): no CALLS from the Rust caller into the Perl file, and the
Rust associated function still binds.

Signed-off-by: Martin Vogel <[email protected]>
DeusData and others added 24 commits October 18, 2026 19:02
fix(python): resolve a base class spelled through a root-binding import
…property-receivers

fix(kotlin): resolve calls through typed class properties (DeusData#1555)
…-defs-only

fix(rust-lsp): Rust calls never bind definitions of other languages
…nested-defs-v2

fix(python): extract defs nested in a function body and resolve bare names lexically (DeusData#1548)
…-call-scope

Signed-off-by: Martin Vogel <[email protected]>

# Conflicts:
#	tests/test_pipeline.c
The home-assistant radarr shape: RadarrCalendarEntity(RadarrEntity,
CalendarEntity) where RadarrEntity reaches the common base Entity through
CoordinatorEntity and CalendarEntity overrides Entity. In C3 order a common
base comes after every class deriving from it, so super().write_state() and
super().__init__() reach CalendarEntity, not Entity through the first base's
ancestry. Single inheritance as the control; sequential and parallel.

Signed-off-by: Martin Vogel <[email protected]>
super() binds to the enclosing class's method resolution order, Python's C3
linearization, in which a common base follows every class deriving from it.
The super() resolver walked the bases one by one, each through its whole
ancestry, so with RadarrCalendarEntity(RadarrEntity, CalendarEntity) the
first base reached Entity through CoordinatorEntity before CalendarEntity,
which overrides it, was ever looked at.

py_c3_linearize computes the order (memoized per lookup, capped in depth and
length; -1 when the hierarchy has none), and super() takes the first class
after the enclosing one that declares the member. A hierarchy without a C3
order keeps the base-by-base walk, as does the synthesized __init__ of an
undeclared constructor.

Signed-off-by: Martin Vogel <[email protected]>
…very-field

fix(pipeline): size definition properties for every field
…aller

fix(pipeline): DATA_FLOWS link every caller and handler of a route
…call-scope

fix(rust): generic impl methods source their own calls (DeusData#763 Rust share)
fix(python-lsp): resolve super() through the C3 method resolution order
…tream-13a-20261101

# Conflicts:
#	.github/workflows/_security.yml
#	.github/workflows/pr.yml
#	.github/workflows/release.yml
#	README.md
#	docs/index.html
#	docs/llms.txt
#	flake.nix
#	pkg/chocolatey/codebase-memory-cli.nuspec
#	pkg/chocolatey/tools/chocolateyInstall.ps1
#	pkg/go/cmd/codebase-memory-cli/main.go
#	pkg/homebrew/Formula/codebase-memory-cli.rb
#	pkg/npm/README.md
#	pkg/npm/install.js
#	pkg/npm/package.json
#	pkg/npm/test/archive-limits.test.js
#	pkg/pypi/README.md
#	pkg/pypi/pyproject.toml
#	pkg/pypi/src/codebase_memory_cli/_cli.py
#	pkg/pypi/tests/test_cli.py
#	pkg/scoop/codebase-memory-mcp.json
#	scripts/smoke-test.sh
#	server.json
#	src/main.c
#	src/operations/test_impact_cli.c
#	src/pipeline/pass_definitions.c
#	src/pipeline/pass_parallel.c
#	tests/test_grammar_probe_f.c
#	tests/test_main.c
#	tests/test_version_metadata_contract.sh
#	tests/windows/test_daemon_stability.py
@coderabbitai

coderabbitai Bot commented Nov 1, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@ngallodev ngallodev closed this Nov 2, 2026
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.

4 participants