From a0bce3a8cfab8e49be5bea8d5dabb2cf0c7f850d Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Tue, 21 Apr 2026 08:38:52 +0100 Subject: [PATCH] fix(scope-resolution): filter export index to module-level defs + label-prefixed qualified key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex adversarial review on PR #980 flagged that buildWorkspaceResolutionIndex feeds defsByFileAndName and callablesBySimpleName from parsed.localDefs — the flat set of every def in the file including methods, fields, and nested functions. findExportedDef / findExportedDefByName treat those maps as file-level exports, so `mod.save()` could silently bind to User.save whenever a method's simple name appeared first in parse order. Plan: docs/plans/2026-04-21-001-fix-workspace-index-module-scope-only-plan.md Fix layers: 1. workspace-index.ts: split the single parsed.localDefs loop into two passes: - Module-export pass: iterate moduleScope.ownedDefs PLUS ownedDefs of every child scope whose parent is the module scope. Top-level class and function declarations each live in their own scope with parent=module, not in moduleScope.ownedDefs directly, so the "parent === moduleScope.id" walk is required to reach them. Methods (scope.parent === Class scope) and nested functions (scope.parent === another Function scope) are excluded. - Member-by-owner pass: keeps iterating parsed.localDefs since that map is keyed on ownerId and correctly saw class-owned defs before this change. 2. graph-bridge/node-lookup.ts: qualified keys now live in a separate keyspace (`:filePath::