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.
- package/.claude/skills/ucn/SKILL.md +58 -236
- package/.claude/skills/ucn/references/commands.md +144 -68
- package/.claude/skills/ucn/references/resolution-rules.md +171 -0
- package/.claude/skills/ucn/references/trust-contract.md +27 -33
- package/README.md +18 -12
- package/cli/index.js +42 -16
- package/core/accessors.js +118 -3
- package/core/account.js +30 -0
- package/core/analysis.js +508 -264
- package/core/ast-analysis.js +76 -117
- package/core/async-producers.js +1729 -0
- package/core/bridge.js +1877 -268
- package/core/brief.js +6 -0
- package/core/build-worker.js +78 -14
- package/core/cache.js +522 -31
- package/core/callers.js +12053 -1047
- package/core/check.js +30 -38
- package/core/class-identity.js +1028 -0
- package/core/command-contracts.js +6 -6
- package/core/configuration-items.js +86 -0
- package/core/contract-membership.js +2262 -0
- package/core/cpp-scope.js +532 -0
- package/core/deadcode.js +171 -49
- package/core/decorator-binding.js +260 -0
- package/core/discovery.js +281 -164
- package/core/errors.js +52 -0
- package/core/execute.js +21 -9
- package/core/external-macros.js +326 -0
- package/core/graph-build.js +277 -8
- package/core/graph.js +35 -2
- package/core/ignore-rules.js +472 -0
- package/core/imports.js +504 -42
- package/core/index-ir.js +94 -11
- package/core/inprocess-clients.js +636 -0
- package/core/ir.js +87 -8
- package/core/macro-expansion.js +1416 -0
- package/core/output/analysis-ext.js +6 -6
- package/core/output/analysis.js +18 -2
- package/core/output/brief.js +3 -0
- package/core/output/doctor.js +4 -0
- package/core/output/endpoints.js +15 -6
- package/core/output/find.js +11 -2
- package/core/output/lines.js +8 -2
- package/core/output/refactoring.js +121 -14
- package/core/output/reporting.js +31 -3
- package/core/output/shared.js +14 -0
- package/core/output-budget.js +316 -122
- package/core/parallel-build.js +124 -47
- package/core/parser.js +3 -2
- package/core/project.js +457 -60
- package/core/provenance-facts.js +156 -12
- package/core/provenance-overload.js +30 -3
- package/core/provenance.js +104 -30
- package/core/pytest-fixtures.js +434 -0
- package/core/python-fixture-flow.js +17 -3
- package/core/python-modules.js +173 -0
- package/core/reflection.js +877 -0
- package/core/registry.js +1 -1
- package/core/reporting.js +234 -52
- package/core/request-helpers.js +561 -0
- package/core/route-graph.js +1922 -0
- package/core/route-lists.js +2414 -0
- package/core/rust-macro-expansion.js +2113 -0
- package/core/rust-modules.js +185 -0
- package/core/search.js +121 -29
- package/core/shared.js +19 -1
- package/core/test-name-bindings.js +256 -0
- package/core/type-denotation.js +1161 -0
- package/core/type-references.js +3229 -0
- package/core/verify.js +3360 -672
- package/languages/adapter.js +31 -5
- package/languages/c-family.js +4061 -212
- package/languages/c-macro-invocations.js +380 -0
- package/languages/c-preprocessor.js +254 -0
- package/languages/csharp.js +1406 -49
- package/languages/go.js +1243 -70
- package/languages/index.js +728 -6
- package/languages/java.js +473 -61
- package/languages/javascript.js +1270 -197
- package/languages/lexical-scope.js +1280 -0
- package/languages/python.js +1557 -72
- package/languages/rust-macro-rules.js +1020 -0
- package/languages/rust-value-flow.js +416 -0
- package/languages/rust.js +2237 -115
- package/languages/utils.js +298 -4
- package/mcp/server.js +25 -11
- package/package.json +1 -1
|
@@ -69,11 +69,11 @@ const COMMAND_CONTRACTS = Object.freeze({
|
|
|
69
69
|
modes: [
|
|
70
70
|
{ name: 'inventory', when: 'Always.', answer: 'Occurrence records classified by usage kind.' },
|
|
71
71
|
],
|
|
72
|
-
defaults: ['
|
|
72
|
+
defaults: ['Test files included; `excludeTests=true` hides them and reports how many.', 'Comments/strings included unless `codeOnly=true`.'],
|
|
73
73
|
truth: 'The command reports the indexed literal-name occurrence universe, not exact semantic references to one definition. Classification is by syntax alone; show/impact ACCOUNT lines are engine-adjudicated, so the two breakdowns can legitimately differ (a method reference is a `reference` here but may be a confirmed caller there).',
|
|
74
74
|
nonGoals: ['Alias-only references whose source line does not contain the queried name.', 'Safe-delete proof.'],
|
|
75
75
|
invalidCombinations: ['A missing name is rejected.'],
|
|
76
|
-
examples: ['ucn usages parseRequest --
|
|
76
|
+
examples: ['ucn usages parseRequest --exclude-tests', 'ucn usages parseRequest --code-only --file=src'],
|
|
77
77
|
jsonData: 'Definition/reference records plus separately classified text occurrences, each with file, line, and content.',
|
|
78
78
|
output: 'Broad output; narrow with `file`, `in`, `exclude`, or `limit`.',
|
|
79
79
|
next: ['Use `find` plus `impact` when target identity matters.', 'Use `search` for arbitrary text.'],
|
|
@@ -182,17 +182,17 @@ const COMMAND_CONTRACTS = Object.freeze({
|
|
|
182
182
|
purpose: 'Validate a symbol signature against call sites or compose checks over a Git diff.',
|
|
183
183
|
target: 'Optional symbol/handle. Omitting it selects diff/precommit mode.',
|
|
184
184
|
modes: [
|
|
185
|
-
{ name: 'symbol', when: 'A symbol target is supplied.', answer: 'Argument-count compatibility, uncertain sites, and the caller account.' },
|
|
185
|
+
{ name: 'symbol', when: 'A symbol target is supplied; `base` names the revision whose declaration its call sites were written against.', answer: 'Argument-count compatibility, uncertain sites, and the caller account.' },
|
|
186
186
|
{ name: 'diff', when: 'No target is supplied; `base` or `staged` selects changes.', answer: 'Composed diff impact, signature checks, and affected tests.' },
|
|
187
187
|
],
|
|
188
|
-
defaults: ['Symbol mode checks static arity, not compiler type compatibility.'],
|
|
188
|
+
defaults: ['Symbol mode checks static arity, not compiler type compatibility.', '`base` defaults to HEAD in both modes.'],
|
|
189
189
|
truth: 'Findings are static diagnostics with explicit uncertainty; a clean result is not a compiler/test pass.',
|
|
190
190
|
nonGoals: ['Full type checking.', 'Linting or executing project tests.'],
|
|
191
191
|
invalidCombinations: [
|
|
192
|
-
'A named symbol cannot
|
|
192
|
+
'A named symbol cannot take `staged`.',
|
|
193
193
|
'`base` and `staged` cannot both select the diff.',
|
|
194
194
|
],
|
|
195
|
-
examples: ['ucn check publishOrderCreated', 'ucn check --staged'],
|
|
195
|
+
examples: ['ucn check publishOrderCreated', 'ucn check publishOrderCreated --base=main', 'ucn check --staged'],
|
|
196
196
|
jsonData: 'Symbol mode returns signature, valid/mismatched/uncertain sites and accounting; diff mode returns composed diagnostics.',
|
|
197
197
|
output: 'Broad diagnostic; scope to a symbol or focused Git diff.',
|
|
198
198
|
next: ['Run the language compiler/type checker and selected tests.', 'Use `plan` before a signature refactor.'],
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration items of dynamically configured scopes (fix #398F).
|
|
5
|
+
*
|
|
6
|
+
* A Python name bound in one scope only in mutually exclusive branches
|
|
7
|
+
* (`if sys.platform == "win32": def getchar` / `else: def getchar`, `try:
|
|
8
|
+
* from ._speedups import f` / `except ImportError: def f`) is one item with
|
|
9
|
+
* an alternative per configuration. The parser records each item
|
|
10
|
+
* (`fileEntry.configurationItems`): its sites (def, class, import or value),
|
|
11
|
+
* each site's branch path, and the line range of every clause on those paths.
|
|
12
|
+
*
|
|
13
|
+
* Reachability of an alternative from a line: code inside another exclusive
|
|
14
|
+
* clause of a statement on the site's branch path runs only in a
|
|
15
|
+
* configuration without that site. Code anywhere else may run in either.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const { branchClausesExclusive } = require('../languages/utils');
|
|
19
|
+
|
|
20
|
+
const NO_ITEMS = Object.freeze([]);
|
|
21
|
+
|
|
22
|
+
function configurationItemsOf(index, file) {
|
|
23
|
+
return index.files.get(file)?.configurationItems || NO_ITEMS;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const DEFINITION_KINDS = new Set(['def', 'class']);
|
|
27
|
+
|
|
28
|
+
/** The item a def/class definition is an alternative of, with its site. */
|
|
29
|
+
function itemOfDefinition(index, definition) {
|
|
30
|
+
if (!definition?.file || definition.startLine == null) return null;
|
|
31
|
+
for (const item of configurationItemsOf(index, definition.file)) {
|
|
32
|
+
if (item.name !== definition.name) continue;
|
|
33
|
+
const site = item.sites.find(s => DEFINITION_KINDS.has(s.kind) && s.line === definition.startLine);
|
|
34
|
+
if (site) return { item, site };
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Two definitions are alternatives of one configuration item. */
|
|
40
|
+
function sameConfigurationItem(index, a, b) {
|
|
41
|
+
if (!a || !b || a === b || a.file !== b.file || a.name !== b.name) return false;
|
|
42
|
+
const found = itemOfDefinition(index, a);
|
|
43
|
+
return !!found && found.item.sites.some(s => DEFINITION_KINDS.has(s.kind) && s.line === b.startLine &&
|
|
44
|
+
s !== found.site);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The module-scope item of `name` in `file`, if any. */
|
|
48
|
+
function moduleItemNamed(index, file, name) {
|
|
49
|
+
return configurationItemsOf(index, file).find(item => item.scope === 0 && item.name === name) || null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Items of `name` in `file` (any scope). */
|
|
53
|
+
function itemsNamed(index, file, name) {
|
|
54
|
+
return configurationItemsOf(index, file).filter(item => item.name === name);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Code at `line` never reaches `site`: the line lies inside another
|
|
59
|
+
* exclusive clause of a statement on the site's branch path.
|
|
60
|
+
*/
|
|
61
|
+
function siteExcludedAt(item, site, line) {
|
|
62
|
+
if (!Number.isInteger(line)) return false;
|
|
63
|
+
for (const [statement, tag] of site.branch) {
|
|
64
|
+
const clauses = item.clauses.find(([at]) => at === statement)?.[1];
|
|
65
|
+
if (!clauses) continue;
|
|
66
|
+
const holder = clauses.find(([, start, end]) => start <= line && line <= end);
|
|
67
|
+
if (holder && holder[0] !== tag && branchClausesExclusive(holder[0], tag)) return true;
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** The sites of `item` code at `line` may reach. */
|
|
73
|
+
function sitesReachableAt(item, line) {
|
|
74
|
+
return item.sites.filter(site => !siteExcludedAt(item, site, line));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
DEFINITION_KINDS,
|
|
79
|
+
configurationItemsOf,
|
|
80
|
+
itemOfDefinition,
|
|
81
|
+
sameConfigurationItem,
|
|
82
|
+
moduleItemNamed,
|
|
83
|
+
itemsNamed,
|
|
84
|
+
siteExcludedAt,
|
|
85
|
+
sitesReachableAt,
|
|
86
|
+
};
|