ucn 5.4.1 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/.claude/skills/ucn/SKILL.md +58 -236
  2. package/.claude/skills/ucn/references/commands.md +144 -68
  3. package/.claude/skills/ucn/references/resolution-rules.md +171 -0
  4. package/.claude/skills/ucn/references/trust-contract.md +27 -33
  5. package/README.md +18 -12
  6. package/cli/index.js +42 -16
  7. package/core/accessors.js +118 -3
  8. package/core/account.js +30 -0
  9. package/core/analysis.js +508 -264
  10. package/core/ast-analysis.js +76 -117
  11. package/core/async-producers.js +1729 -0
  12. package/core/bridge.js +1877 -268
  13. package/core/brief.js +6 -0
  14. package/core/build-worker.js +78 -14
  15. package/core/cache.js +522 -31
  16. package/core/callers.js +12053 -1047
  17. package/core/check.js +30 -38
  18. package/core/class-identity.js +1028 -0
  19. package/core/command-contracts.js +6 -6
  20. package/core/configuration-items.js +86 -0
  21. package/core/contract-membership.js +2262 -0
  22. package/core/cpp-scope.js +532 -0
  23. package/core/deadcode.js +171 -49
  24. package/core/decorator-binding.js +260 -0
  25. package/core/discovery.js +281 -164
  26. package/core/errors.js +52 -0
  27. package/core/execute.js +21 -9
  28. package/core/external-macros.js +326 -0
  29. package/core/graph-build.js +277 -8
  30. package/core/graph.js +35 -2
  31. package/core/ignore-rules.js +472 -0
  32. package/core/imports.js +504 -42
  33. package/core/index-ir.js +94 -11
  34. package/core/inprocess-clients.js +636 -0
  35. package/core/ir.js +87 -8
  36. package/core/macro-expansion.js +1416 -0
  37. package/core/output/analysis-ext.js +6 -6
  38. package/core/output/analysis.js +18 -2
  39. package/core/output/brief.js +3 -0
  40. package/core/output/doctor.js +4 -0
  41. package/core/output/endpoints.js +15 -6
  42. package/core/output/find.js +11 -2
  43. package/core/output/lines.js +8 -2
  44. package/core/output/refactoring.js +121 -14
  45. package/core/output/reporting.js +31 -3
  46. package/core/output/shared.js +14 -0
  47. package/core/output-budget.js +316 -122
  48. package/core/parallel-build.js +124 -47
  49. package/core/parser.js +3 -2
  50. package/core/project.js +457 -60
  51. package/core/provenance-facts.js +156 -12
  52. package/core/provenance-overload.js +30 -3
  53. package/core/provenance.js +104 -30
  54. package/core/pytest-fixtures.js +434 -0
  55. package/core/python-fixture-flow.js +17 -3
  56. package/core/python-modules.js +173 -0
  57. package/core/reflection.js +877 -0
  58. package/core/registry.js +1 -1
  59. package/core/reporting.js +234 -52
  60. package/core/request-helpers.js +561 -0
  61. package/core/route-graph.js +1922 -0
  62. package/core/route-lists.js +2414 -0
  63. package/core/rust-macro-expansion.js +2113 -0
  64. package/core/rust-modules.js +185 -0
  65. package/core/search.js +121 -29
  66. package/core/shared.js +19 -1
  67. package/core/test-name-bindings.js +256 -0
  68. package/core/type-denotation.js +1161 -0
  69. package/core/type-references.js +3229 -0
  70. package/core/verify.js +3360 -672
  71. package/languages/adapter.js +31 -5
  72. package/languages/c-family.js +4061 -212
  73. package/languages/c-macro-invocations.js +380 -0
  74. package/languages/c-preprocessor.js +254 -0
  75. package/languages/csharp.js +1406 -49
  76. package/languages/go.js +1243 -70
  77. package/languages/index.js +728 -6
  78. package/languages/java.js +473 -61
  79. package/languages/javascript.js +1270 -197
  80. package/languages/lexical-scope.js +1280 -0
  81. package/languages/python.js +1557 -72
  82. package/languages/rust-macro-rules.js +1020 -0
  83. package/languages/rust-value-flow.js +416 -0
  84. package/languages/rust.js +2237 -115
  85. package/languages/utils.js +298 -4
  86. package/mcp/server.js +25 -11
  87. package/package.json +1 -1
package/core/index-ir.js CHANGED
@@ -9,15 +9,32 @@
9
9
  */
10
10
 
11
11
  function createImportBindings(imports) {
12
- return imports.flatMap(item => (item.names || [])
12
+ return imports.flatMap(item => {
13
+ const names = item.names || [];
14
+ let renames;
15
+ if (item.renames?.length) {
16
+ const sourceNames = new Set(names);
17
+ renames = new Map();
18
+ // Reverse once so each per-name stack pops in source order.
19
+ for (let i = item.renames.length - 1; i >= 0; i--) {
20
+ const rename = item.renames[i];
21
+ const spelling = sourceNames.has(rename.original) ? rename.original : rename.local;
22
+ if (!renames.has(spelling)) renames.set(spelling, []);
23
+ renames.get(spelling).push(rename);
24
+ }
25
+ }
26
+ return names
13
27
  .filter(name => name && name !== '*' && name !== '_' && name !== '.')
14
28
  .map(name => {
15
29
  // A rename may be recorded under its original name (Python
16
30
  // `from m import a as b` lists 'a') or under its local alias
17
31
  // (Rust `use m::a as b` lists 'b', fix #357); both yield the
18
32
  // binding {name: original, alias: local}.
19
- const rename = (item.renames || []).find(candidate =>
20
- candidate.original === name || candidate.local === name);
33
+ // Each rename belongs to one import specifier. Reusing it for
34
+ // every repeated source name loses the unaliased binding in
35
+ // `import { A, A as B }`. A local spelling is used only when
36
+ // this record does not also list the original spelling (Rust).
37
+ const rename = renames?.get(name)?.pop();
21
38
  return {
22
39
  name: rename ? rename.original : name,
23
40
  module: item.module,
@@ -27,8 +44,26 @@ function createImportBindings(imports) {
27
44
  ...(item.defaultLike && { defaultLike: true }),
28
45
  ...(item.deferred && { deferred: true }),
29
46
  ...(item.dynamic && { dynamic: true }),
47
+ ...(item.namespace && { namespace: item.namespace }),
30
48
  };
31
- }));
49
+ });
50
+ });
51
+ }
52
+
53
+ /** Names a C# slot-typed `new(..)` record depends on: the call or type it
54
+ * is an argument of, the receiver member of that call, or the member it is
55
+ * assigned to (fix #400). Null when the file has none. */
56
+ function targetTypedKeysOf(calls) {
57
+ let keys = null;
58
+ for (const call of calls || []) {
59
+ const slot = call?.targetSlot;
60
+ if (!slot) continue;
61
+ if (!keys) keys = new Set();
62
+ for (const key of [slot.ownerName, slot.receiverName, slot.member]) if (key) keys.add(key);
63
+ // A generic receiver's written type (fix #401) is its own key.
64
+ if (slot.receiverTypeText) keys.add(`~${slot.receiverTypeText}`);
65
+ }
66
+ return keys ? [...keys].sort() : null;
32
67
  }
33
68
 
34
69
  function createFileEntryFromIR({
@@ -63,6 +98,14 @@ function createFileEntryFromIR({
63
98
  ...(item.line != null && { line: item.line }),
64
99
  ...(item.deferred && { deferred: true }),
65
100
  ...(item.deferredReason && { deferredReason: item.deferredReason }),
101
+ // C# using directives (fix #395): the namespace the directive
102
+ // sits in (its name resolves from there), `using static`, and
103
+ // `global using`.
104
+ ...(item.namespace && { namespace: item.namespace }),
105
+ ...(item.static && { static: true }),
106
+ ...(item.global && { global: true }),
107
+ // Go (fix #400): the import writes no local name.
108
+ ...(item.implicitName && { implicitName: true }),
66
109
  })),
67
110
  globalImports: imports.filter(item => item.global).map(item => item.module),
68
111
  importNames: imports.flatMap(item => item.names || []),
@@ -73,10 +116,45 @@ function createFileEntryFromIR({
73
116
  bindings: [],
74
117
  dynamicImports: ir.dynamicImports || 0,
75
118
  ...(ir.diagnostics?.parseRecovery && { parseRecovery: true }),
119
+ ...(ir.diagnostics?.parseErrorRegions?.length > 0 && {
120
+ parseErrorRegions: ir.diagnostics.parseErrorRegions,
121
+ }),
76
122
  ...(ir.importAliases && { importAliases: ir.importAliases }),
77
123
  ...(ir.moduleAssignedNames?.length > 0 && {
78
124
  moduleAssignedNames: ir.moduleAssignedNames,
79
125
  }),
126
+ ...(ir.asyncClosureNames?.length > 0 && {
127
+ asyncClosureNames: ir.asyncClosureNames,
128
+ }),
129
+ ...(Array.isArray(ir.openCalls) && { openCalls: ir.openCalls }),
130
+ ...(ir.typeConversions?.length > 0 && {
131
+ typeConversions: ir.typeConversions,
132
+ }),
133
+ ...(ir.reflectionSites?.length > 0 && {
134
+ reflectionSites: ir.reflectionSites,
135
+ }),
136
+ ...(ir.macroScopeMarkers?.length > 0 && {
137
+ macroScopeMarkers: ir.macroScopeMarkers,
138
+ }),
139
+ ...(ir.cppUsings?.length > 0 && {
140
+ cppUsings: ir.cppUsings,
141
+ }),
142
+ ...(ir.languageFeatures?.length > 0 && {
143
+ languageFeatures: ir.languageFeatures,
144
+ }),
145
+ ...(Array.isArray(ir.conditionalViews) && { conditionalViews: ir.conditionalViews }),
146
+ // C# target-typed `new(..)` records whose type a call or member
147
+ // decides (fix #400): the names a query matches before reading them.
148
+ ...(targetTypedKeysOf(ir.calls) && { targetTypedKeys: targetTypedKeysOf(ir.calls) }),
149
+ ...(ir.packageName && { packageName: ir.packageName }),
150
+ ...(ir.packageVars?.length > 0 && { packageVars: ir.packageVars }),
151
+ ...(ir.buildConstraint && { buildConstraint: ir.buildConstraint }),
152
+ ...(ir.moduleValueAliases?.length > 0 && { moduleValueAliases: ir.moduleValueAliases }),
153
+ ...(ir.moduleConstructedValues?.length > 0 && { moduleConstructedValues: ir.moduleConstructedValues }),
154
+ ...(ir.configurationItems?.length > 0 && { configurationItems: ir.configurationItems }),
155
+ ...(Array.isArray(ir.recoveryBlanks) && { recoveryBlanks: ir.recoveryBlanks }),
156
+ ...(Array.isArray(ir.recoveryCandidates) && { recoveryCandidates: ir.recoveryCandidates }),
157
+ ...(Array.isArray(ir.externalMacroNames) && { externalMacroNames: ir.externalMacroNames }),
80
158
  ...(isBundled && { isBundled: true }),
81
159
  ...(isGenerated && { isGenerated: true }),
82
160
  };
@@ -85,20 +163,25 @@ function createFileEntryFromIR({
85
163
  const OPTIONAL_SYMBOL_FIELDS = Object.freeze([
86
164
  'returnedFunctionResult', 'isFunctionVariable', 'paramTypes', 'isAsync',
87
165
  'isGenerator', 'generics', 'ownerGenerics', 'genericBounds', 'extends', 'implements', 'indent', 'isNested',
88
- 'enclosingType', 'isMethod', 'receiver', 'memberType', 'fieldType',
89
- 'aliasOf', 'aliasMembers', 'aliasTypeText', 'aliasTypeParameters', 'aliasTypeDefaults', 'derefTarget', 'decorators', 'decoratorsWithArgs',
166
+ 'enclosingType', 'isMethod', 'receiver', 'memberType', 'fieldType', 'embedded',
167
+ 'aliasOf', 'aliasQualifier', 'aliasMembers', 'aliasTypeText', 'aliasTypeParameters', 'aliasTypeDefaults', 'derefTarget', 'decorators', 'decoratorsWithArgs',
90
168
  'annotationsWithArgs', 'attributesWithArgs', 'nameLine', 'traitImpl',
91
- 'traitName', 'isSignature', 'memberAssigned', 'assignedReceiver', 'bodyScopedName',
92
- 'registryMember', 'registryContainer', 'namespace',
93
- 'isExtensionMethod', 'extensionReceiver', 'explicitInterface',
169
+ 'traitName', 'isSignature', 'memberAssigned', 'assignedReceiver', 'assignedObject', 'selfNamed', 'bodyScopedName',
170
+ 'registryMember', 'registryContainer', 'registryContainerType', 'objectLiteralLine', 'namespace',
171
+ 'isExtensionMethod', 'extensionReceiver', 'explicitInterface', 'primaryParams',
94
172
  'lexicalScopeStartLine', 'lexicalScopeEndLine',
95
- 'returnTypeQualifier', 'macroNeverReturns', 'callbackParamTypes', 'iteratorItemType',
173
+ 'returnTypeQualifier', 'returnTypeResolved', 'supertraits', 'ownerGenericBounds', 'ownerSelfArgs', 'implSelfRef', 'implSelfQualifier', 'blanketSelfBounds', 'selfParamKind', 'macroNeverReturns', 'callbackParamTypes', 'iteratorItemType', 'futureReturn',
96
174
  'returnedConcreteType', 'returnedConstructors', 'templateDependent',
97
175
  'returnedCallStart', 'returnedCallEnd',
98
- 'returnedReceiverPath',
176
+ 'returnedReceiverPath', 'valueType', 'valueDerefVia',
99
177
  'isSpecialization',
100
178
  'linkage', 'functionLike', 'callableAlias', 'exportedAlias',
101
179
  'aliasOwner', 'aliasMember', 'callableTarget', 'macroParamEffects',
180
+ 'namespaceScope', 'ppParams', 'ppVariadic', 'ppBody', 'ppConditional', 'languageBranch', 'macroExpansion', 'macroScope', 'accessAfterMacro', 'ppBranch',
181
+ 'generatedByMacro',
182
+ 'typeArity', 'ownerTypeArity',
183
+ 'annotationType', 'valueShape', 'friendOf', 'templateParams', 'delegateParams',
184
+ 'typedefName',
102
185
  ]);
103
186
 
104
187
  function materializeSymbol(fileEntry, item) {