ucn 5.5.1 → 5.5.2
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.
- package/.claude/skills/ucn/SKILL.md +35 -9
- package/.claude/skills/ucn/references/commands.md +38 -16
- package/.claude/skills/ucn/references/resolution-rules.md +126 -20
- package/.claude/skills/ucn/references/trust-contract.md +5 -3
- package/README.md +30 -21
- package/cli/index.js +1 -1
- package/core/accessors.js +341 -54
- package/core/account.js +74 -20
- package/core/analysis.js +257 -125
- package/core/ast-analysis.js +12 -3
- package/core/brief.js +8 -4
- package/core/build-worker.js +2 -1
- package/core/cache.js +137 -6
- package/core/call-name-cache.js +134 -0
- package/core/callable-scope.js +21 -0
- package/core/callers.js +4726 -940
- package/core/check.js +22 -5
- package/core/class-identity.js +399 -12
- package/core/constructor-calls.js +831 -0
- package/core/constructor-hierarchy.js +147 -0
- package/core/constructor-protocol.js +196 -0
- package/core/contract-membership.js +346 -140
- package/core/cpp-conversion-constraints.js +123 -0
- package/core/cpp-conversion-syntax.js +216 -0
- package/core/cpp-conversions.js +414 -0
- package/core/cpp-scope.js +245 -44
- package/core/deadcode.js +35 -15
- package/core/decorator-binding.js +137 -3
- package/core/enum-reference-syntax.js +134 -0
- package/core/execute.js +17 -1
- package/core/external-macros.js +42 -10
- package/core/go-packages.js +171 -0
- package/core/graph-build.js +2 -0
- package/core/graph.js +75 -59
- package/core/ignore-rules.js +2 -1
- package/core/imports.js +145 -19
- package/core/index-ir.js +41 -4
- package/core/ir.js +27 -6
- package/core/macro-expansion.js +38 -2
- package/core/out-of-class-members.js +182 -0
- package/core/output/analysis-ext.js +4 -2
- package/core/output/analysis.js +89 -20
- package/core/output/graph.js +12 -3
- package/core/output/lines.js +4 -3
- package/core/output/public.js +1 -0
- package/core/output/reporting.js +6 -1
- package/core/output/shared.js +2 -0
- package/core/output/tracing.js +28 -22
- package/core/output-budget.js +2 -2
- package/core/parallel-build.js +52 -1
- package/core/project.js +217 -112
- package/core/provenance-constructor-base.js +161 -0
- package/core/provenance-facts.js +257 -27
- package/core/provenance-overload.js +458 -54
- package/core/provenance-type.js +487 -0
- package/core/provenance.js +234 -15
- package/core/public-command.js +17 -2
- package/core/query-bodies.js +159 -0
- package/core/reflection.js +255 -2
- package/core/rename-token-syntax.js +111 -0
- package/core/reporting.js +13 -7
- package/core/rust-macro-expansion.js +151 -19
- package/core/rust-modules.js +1 -1
- package/core/rust-names.js +607 -0
- package/core/search.js +70 -17
- package/core/shared.js +98 -1
- package/core/source-memo.js +201 -0
- package/core/text-usage-syntax.js +38 -0
- package/core/tracing.js +7 -1
- package/core/type-denotation.js +124 -37
- package/core/type-references.js +615 -246
- package/core/value-references.js +2777 -0
- package/core/verify.js +1097 -281
- package/languages/adapter.js +28 -4
- package/languages/c-family.js +1118 -164
- package/languages/constructor-bases.js +105 -0
- package/languages/cpp-platform.js +26 -0
- package/languages/cpp-site-syntax.js +83 -0
- package/languages/csharp-scope.js +439 -0
- package/languages/csharp.js +428 -68
- package/languages/go.js +385 -207
- package/languages/html.js +4 -2
- package/languages/index.js +397 -2
- package/languages/java-platform.js +226 -0
- package/languages/java-unicode.js +269 -0
- package/languages/java.js +461 -117
- package/languages/javascript.js +418 -66
- package/languages/lexical-scope.js +190 -23
- package/languages/python.js +404 -54
- package/languages/rust.js +510 -82
- package/languages/utils.js +67 -8
- package/mcp/server.js +8 -2
- package/package.json +2 -2
package/languages/utils.js
CHANGED
|
@@ -80,7 +80,11 @@ function nodeToLocation(node, codeOrLines) {
|
|
|
80
80
|
const indentMatch = firstLine.match(/^(\s*)/);
|
|
81
81
|
const indent = indentMatch ? indentMatch[1].length : 0;
|
|
82
82
|
|
|
83
|
-
return { startLine, endLine, indent
|
|
83
|
+
return { startLine, endLine, indent, sourceSpan: {
|
|
84
|
+
start: node.startIndex, end: node.endIndex,
|
|
85
|
+
startLine, endLine,
|
|
86
|
+
startColumn: node.startPosition.column, endColumn: node.endPosition.column,
|
|
87
|
+
} };
|
|
84
88
|
}
|
|
85
89
|
|
|
86
90
|
/**
|
|
@@ -343,7 +347,7 @@ function parseRustParam(param, info) {
|
|
|
343
347
|
function parseJavaParam(param, info) {
|
|
344
348
|
if (param.type === 'formal_parameter' || param.type === 'spread_parameter') {
|
|
345
349
|
let nameNode = param.childForFieldName('name');
|
|
346
|
-
|
|
350
|
+
let typeNode = param.childForFieldName('type');
|
|
347
351
|
// Java varargs: spread_parameter wraps name in variable_declarator
|
|
348
352
|
// e.g., `String... args` → spread_parameter > variable_declarator > identifier
|
|
349
353
|
if (!nameNode && param.type === 'spread_parameter') {
|
|
@@ -355,8 +359,14 @@ function parseJavaParam(param, info) {
|
|
|
355
359
|
}
|
|
356
360
|
}
|
|
357
361
|
}
|
|
362
|
+
if (!typeNode && param.type === 'spread_parameter') {
|
|
363
|
+
const types = new Set(['type_identifier', 'scoped_type_identifier', 'generic_type',
|
|
364
|
+
'array_type', 'annotated_type', 'integral_type', 'floating_point_type', 'boolean_type']);
|
|
365
|
+
typeNode = param.namedChildren.find(child => types.has(child.type));
|
|
366
|
+
}
|
|
358
367
|
if (nameNode) info.name = nodeTextWithoutComments(nameNode);
|
|
359
|
-
if (typeNode) info.type = nodeTextWithoutComments(typeNode)
|
|
368
|
+
if (typeNode) info.type = nodeTextWithoutComments(typeNode) +
|
|
369
|
+
(param.type === 'spread_parameter' ? '[]' : '');
|
|
360
370
|
if (param.type === 'spread_parameter') info.rest = true;
|
|
361
371
|
}
|
|
362
372
|
}
|
|
@@ -676,6 +686,10 @@ function getTokenTypeAtPosition(rootNode, line, column) {
|
|
|
676
686
|
// Find the smallest node at this position
|
|
677
687
|
const node = rootNode.descendantForPosition({ row, column });
|
|
678
688
|
if (!node) return 'code';
|
|
689
|
+
// A comment in an aliased rule can be wrapped with the alias type,
|
|
690
|
+
// depending on which traversal read it first (fix #420): an extra's
|
|
691
|
+
// grammar type is stable.
|
|
692
|
+
if (node.isExtra && /comment/.test(node.grammarType || '')) return 'comment';
|
|
679
693
|
|
|
680
694
|
// Walk up the tree to check if we're in a comment or string
|
|
681
695
|
let current = node;
|
|
@@ -843,17 +857,16 @@ const NAMED_CHILDREN_LIST = Symbol.for('ucn.namedChildrenList');
|
|
|
843
857
|
function _buildNodeList(rootNode) {
|
|
844
858
|
const nodes = [];
|
|
845
859
|
const subtreeEnds = [];
|
|
846
|
-
//
|
|
847
|
-
|
|
848
|
-
function collect(node) {
|
|
860
|
+
// Depth-first preorder with each subtree boundary filled on return.
|
|
861
|
+
function collect(node, parent) {
|
|
849
862
|
const idx = nodes.length;
|
|
850
863
|
nodes.push(node);
|
|
851
864
|
subtreeEnds.push(0);
|
|
852
865
|
// Batched children read — one native call instead of N+1 (see
|
|
853
866
|
// traverseTree); the array stays on the node for later reads.
|
|
854
|
-
const children = node[NAMED_CHILDREN_LIST] ? node[NAMED_CHILDREN_LIST]() : node.namedChildren;
|
|
867
|
+
const children = node[NAMED_CHILDREN_LIST] ? node[NAMED_CHILDREN_LIST](parent) : node.namedChildren;
|
|
855
868
|
for (let i = 0; i < children.length; i++) {
|
|
856
|
-
collect(children[i]);
|
|
869
|
+
collect(children[i], node);
|
|
857
870
|
}
|
|
858
871
|
subtreeEnds[idx] = nodes.length;
|
|
859
872
|
}
|
|
@@ -1322,6 +1335,20 @@ function genericArityOf(text) {
|
|
|
1322
1335
|
return null;
|
|
1323
1336
|
}
|
|
1324
1337
|
|
|
1338
|
+
// A type argument list on an enclosing segment belongs to that segment:
|
|
1339
|
+
// erasing everything after the first '<' would turn Outer<T>.Inner into
|
|
1340
|
+
// Outer. Callers without enclosing generic identity must retain uncertainty.
|
|
1341
|
+
function hasParameterizedQualifier(text) {
|
|
1342
|
+
let depth = 0, parameterized = false;
|
|
1343
|
+
for (const ch of String(text || '')) {
|
|
1344
|
+
if (ch === '<') depth++;
|
|
1345
|
+
else if (ch === '>') {
|
|
1346
|
+
if (--depth === 0) parameterized = true;
|
|
1347
|
+
} else if (ch === '.' && depth === 0 && parameterized) return true;
|
|
1348
|
+
}
|
|
1349
|
+
return false;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1325
1352
|
// Exclusive clauses of one compound statement (fix #398F): `if`/`elif`/
|
|
1326
1353
|
// `else` and `case` arms never both run; a `try` body and its handlers, two
|
|
1327
1354
|
// handlers, a handler and the `try` `else` are alternatives. A `try` body and
|
|
@@ -1358,8 +1385,40 @@ function goPathPackageName(modulePath) {
|
|
|
1358
1385
|
return cut > 0 ? base.slice(0, cut) : base;
|
|
1359
1386
|
}
|
|
1360
1387
|
|
|
1388
|
+
// Node types that declare a type parameter, and the name-token types under
|
|
1389
|
+
// them (fix #421; shared with core/provenance-type.js).
|
|
1390
|
+
const TYPE_PARAMETER_PARENTS = Object.freeze(['type_parameter', 'type_parameters',
|
|
1391
|
+
'constrained_type_parameter', 'type_parameter_declaration',
|
|
1392
|
+
'optional_type_parameter_declaration', 'variadic_type_parameter_declaration']);
|
|
1393
|
+
const TYPE_PARAMETER_NAME_TOKENS = Object.freeze(['identifier', 'type_identifier', 'namespace_identifier',
|
|
1394
|
+
'qualified_identifier', 'scoped_type_identifier', 'qualified_name', 'alias_qualified_name']);
|
|
1395
|
+
const TYPE_PARAMETER_NAME_TOKEN_SET = new Set(TYPE_PARAMETER_NAME_TOKENS);
|
|
1396
|
+
|
|
1397
|
+
/**
|
|
1398
|
+
* Every name token written directly in a type-parameter declaration of the
|
|
1399
|
+
* trees (fix #421): a superset of the file's type-parameter names (bounds
|
|
1400
|
+
* and defaults included), sorted. A name outside it is no type parameter
|
|
1401
|
+
* anywhere in the file, which a construction's name-scope proof reads
|
|
1402
|
+
* without parsing the file again.
|
|
1403
|
+
*/
|
|
1404
|
+
function declaredTypeParameterNames(...trees) {
|
|
1405
|
+
const names = new Set();
|
|
1406
|
+
for (const tree of trees) {
|
|
1407
|
+
for (const parent of tree?.rootNode?.descendantsOfType([...TYPE_PARAMETER_PARENTS]) || []) {
|
|
1408
|
+
for (const node of parent.children) {
|
|
1409
|
+
if (TYPE_PARAMETER_NAME_TOKEN_SET.has(node.type)) names.add(node.text);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
return [...names].sort();
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1361
1416
|
module.exports = {
|
|
1417
|
+
TYPE_PARAMETER_PARENTS,
|
|
1418
|
+
TYPE_PARAMETER_NAME_TOKENS,
|
|
1419
|
+
declaredTypeParameterNames,
|
|
1362
1420
|
genericArityOf,
|
|
1421
|
+
hasParameterizedQualifier,
|
|
1363
1422
|
goPathPackageName,
|
|
1364
1423
|
parseErrorRegions,
|
|
1365
1424
|
containsOwnNode,
|
package/mcp/server.js
CHANGED
|
@@ -35,6 +35,7 @@ const {
|
|
|
35
35
|
formatSurfaceMessage,
|
|
36
36
|
} = require('../core/registry');
|
|
37
37
|
const { execute } = require('../core/execute');
|
|
38
|
+
const { sourceRangeTarget } = require('../core/public-command');
|
|
38
39
|
const { describeError, UcnError } = require('../core/errors');
|
|
39
40
|
const { applyOutputBudget, MAX_OUTPUT_CHARS } = require('../core/output-budget');
|
|
40
41
|
|
|
@@ -245,7 +246,7 @@ Use UCN for semantic questions: exact definitions, symbol-aware callers/callees,
|
|
|
245
246
|
- check: symbol signature check when name is set; precommit check when omitted. plan previews the selected declaration plus indexed call/import/export edits.
|
|
246
247
|
- deadcode/audit_async/stacktrace: focused audits and runtime evidence. Computed dispatch is reported as a health/deletion blind spot; unknown decorators and member-assigned handlers are withheld from default dead-code claims.
|
|
247
248
|
|
|
248
|
-
CONFIRMED carries target-identity evidence. UNVERIFIED is possible and requires review; when same-name definitions compete, show returns their stable handles once above the sites. ACCOUNT conserves observed literal-name lines; an observed-text zero never claims semantic completeness or safe deletion. Evidence weights are ordinal, not probabilities. Warnings, excluded reasons, and contract metadata remain visible when caller evidence is returned.
|
|
249
|
+
CONFIRMED carries target-identity evidence. UNVERIFIED is possible and requires review; when same-name definitions compete, show returns their stable handles once above the sites. ACCOUNT conserves observed literal-name lines; an observed-text zero never claims semantic completeness or safe deletion. Evidence weights are ordinal, not probabilities. Warnings, excluded reasons, and contract metadata remain visible when caller evidence is returned. Releases are gated on pinned real repositories: sampled callers, callees, value references, and dead-code claims are compared with ts-morph, Pyright, gopls, rust-analyzer, JDT LS, Roslyn, and clangd, and one handle's claims must agree across find, show, source, impact, tests, check, and caller trace.` + generateMcpParamSection();
|
|
249
250
|
|
|
250
251
|
// The default description is the only public contract. The former verbose
|
|
251
252
|
// description is intentionally not selectable: it documented retired commands
|
|
@@ -306,7 +307,7 @@ const INPUT_SHAPE = {
|
|
|
306
307
|
rename_to: stringParam('New name for the function, method, or type (plan command)'),
|
|
307
308
|
default_value: stringParam('Default value for added parameter (plan command)'),
|
|
308
309
|
stack: stringParam('The stack trace text to parse (stacktrace command)'),
|
|
309
|
-
range: stringParam('source line range, e.g. "10-20" or "15"
|
|
310
|
+
range: stringParam('source line range, e.g. "10-20" or "15", of the file given as file or name.'),
|
|
310
311
|
base: stringParam('Git ref (default: HEAD). impact/check without a symbol: diff against it; check with a symbol: compare the declaration with its version there. E.g. "HEAD~3", "main", a commit SHA'),
|
|
311
312
|
staged: booleanParam('impact/check without a symbol: analyze staged changes.'),
|
|
312
313
|
deep: booleanParam('repo: include health and sample the ordinal resolution-evidence profile, not accuracy.'),
|
|
@@ -473,6 +474,11 @@ server.registerTool(
|
|
|
473
474
|
// Post-result checks are still retained below for symbol-derived
|
|
474
475
|
// paths, but a range request may point at a real file outside the
|
|
475
476
|
// project and must fail before any content leaves the process.
|
|
477
|
+
// `name` is the file of a range request (name=<file>, range="N-M").
|
|
478
|
+
if (canonicalCommand === 'source') {
|
|
479
|
+
const target = sourceRangeTarget(ep);
|
|
480
|
+
if (target !== ep) { delete ep.name; ep.file = target.file; }
|
|
481
|
+
}
|
|
476
482
|
if (canonicalCommand === 'source' && ep.file) {
|
|
477
483
|
const sourcePath = resolveAndValidatePath(index, ep.file);
|
|
478
484
|
if (typeof sourcePath !== 'string') return sourcePath;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ucn",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.2",
|
|
4
4
|
"mcpName": "io.github.mleoca/ucn",
|
|
5
5
|
"description": "Auditable AST code intelligence for AI agents: 18 task-oriented commands through one MCP tool, CLI, or agent skill. Supports JS/TS, Python, Go, Rust, Java, C, C++, C#, and HTML.",
|
|
6
6
|
"main": "index.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"version": "node scripts/sync-server-version.js && git add server.json",
|
|
13
|
-
"test": "node --test test/audit-5.4.0.test.js test/audit-5.3.8.test.js test/audit-5.3.7.test.js test/audit-5.3.6.test.js test/evidence-provenance.test.js test/provenance-unit.test.js test/shell-output.test.js test/parser-unit.test.js test/integration.test.js test/cache.test.js test/formatter.test.js test/interactive.test.js test/feature.test.js test/regression-js.test.js test/regression-py.test.js test/regression-go.test.js test/regression-java.test.js test/regression-rust.test.js test/regression-c-family.test.js test/regression-cross.test.js test/regression-mcp.test.js test/mcp-protocol.test.js test/mcp-sdk-compat.test.js test/dependency-security.test.js test/regression-parser.test.js test/regression-commands.test.js test/regression-fixes.test.js test/regression-bugfixes.test.js test/release-surface-regressions.test.js test/prerelease-audit.test.js test/release-readiness-audit.test.js test/cross-language.test.js test/accuracy.test.js test/command-coverage.test.js test/perf-optimizations.test.js test/performance-gate-policy.test.js test/oracle-gate-policy.test.js test/outcome-policy.test.js test/consistency-eval.test.js test/agent-public-surface-benchmark.test.js test/command-contracts.test.js test/language-adapter.test.js test/systematic-test.js test/mcp-edge-cases.js test/conservation.test.js test/parity-test.js test/trust-matrix.test.js",
|
|
13
|
+
"test": "node --test test/audit-5.4.0.test.js test/audit-5.3.8.test.js test/audit-5.3.7.test.js test/audit-5.3.6.test.js test/evidence-provenance.test.js test/provenance-unit.test.js test/provenance-scope.test.js test/shell-output.test.js test/parser-unit.test.js test/integration.test.js test/cache.test.js test/formatter.test.js test/interactive.test.js test/feature.test.js test/regression-js.test.js test/regression-py.test.js test/regression-go.test.js test/regression-java.test.js test/regression-rust.test.js test/regression-c-family.test.js test/regression-cross.test.js test/regression-mcp.test.js test/mcp-protocol.test.js test/mcp-sdk-compat.test.js test/dependency-security.test.js test/regression-parser.test.js test/regression-commands.test.js test/regression-fixes.test.js test/regression-bugfixes.test.js test/release-surface-regressions.test.js test/prerelease-audit.test.js test/release-readiness-audit.test.js test/cross-language.test.js test/accuracy.test.js test/command-coverage.test.js test/perf-optimizations.test.js test/performance-gate-policy.test.js test/oracle-gate-policy.test.js test/outcome-policy.test.js test/consistency-eval.test.js test/agent-public-surface-benchmark.test.js test/command-contracts.test.js test/language-adapter.test.js test/systematic-test.js test/mcp-edge-cases.js test/conservation.test.js test/parity-test.js test/trust-matrix.test.js",
|
|
14
14
|
"benchmark:agent": "node test/agent-public-surface-benchmark.js",
|
|
15
15
|
"benchmark:agent:gate": "node test/agent-public-surface-benchmark.js --gate",
|
|
16
16
|
"benchmark:agent:legacy": "node test/agent-understanding-benchmark.js",
|