ucn 5.5.2 → 5.6.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 +35 -12
- package/.claude/skills/ucn/references/commands.md +21 -17
- package/.claude/skills/ucn/references/resolution-rules.md +4 -0
- package/.claude/skills/ucn/references/trust-contract.md +4 -4
- package/CHANGELOG.md +474 -0
- package/README.md +71 -29
- package/cli/flags.js +184 -0
- package/cli/index.js +138 -324
- package/core/account.js +44 -87
- package/core/analysis.js +273 -107
- package/core/ast-analysis.js +2 -0
- package/core/bridge.js +29 -65
- package/core/cache.js +101 -16
- package/core/callers.js +352 -70
- package/core/capture.js +331 -0
- package/core/change-kinds.js +888 -0
- package/core/check.js +1117 -139
- package/core/client-receivers.js +189 -0
- package/core/command-contracts.js +7 -6
- package/core/constructed-class.js +1195 -0
- package/core/contract-membership.js +142 -0
- package/core/deadcode.js +388 -85
- package/core/deletion.js +401 -0
- package/core/discovery.js +104 -9
- package/core/entrypoints.js +12 -6
- package/core/evidence-bands.js +68 -0
- package/core/evidence-bands.json +44 -0
- package/core/execute.js +172 -161
- package/core/hot-summary.js +241 -0
- package/core/index-ir.js +3 -1
- package/core/inprocess-clients.js +41 -15
- package/core/ir.js +5 -1
- package/core/member-signatures.js +789 -0
- package/core/output/analysis-ext.js +20 -10
- package/core/output/analysis.js +98 -60
- package/core/output/check.js +98 -37
- package/core/output/doctor.js +34 -1
- package/core/output/find.js +2 -1
- package/core/output/lines.js +63 -3
- package/core/output/public.js +30 -11
- package/core/output/refactoring.js +32 -0
- package/core/output/reporting.js +21 -2
- package/core/output/search.js +11 -2
- package/core/output/tracing.js +35 -7
- package/core/output-budget.js +124 -57
- package/core/parallel-build.js +3 -3
- package/core/project.js +106 -23
- package/core/provenance-type.js +12 -5
- package/core/public-command.js +35 -9
- package/core/python-modules.js +6 -0
- package/core/reflection.js +166 -23
- package/core/registry.js +623 -72
- package/core/reporting.js +69 -34
- package/core/request-helpers.js +63 -7
- package/core/review-items.js +75 -0
- package/core/search.js +89 -128
- package/core/shared.js +0 -45
- package/core/snapshot.js +350 -0
- package/core/source-universe.js +707 -0
- package/core/test-units.js +3624 -0
- package/core/tracing.js +150 -96
- package/core/verify.js +27 -11
- package/languages/adapter.js +8 -3
- package/languages/c-family.js +12 -0
- package/languages/csharp.js +634 -0
- package/languages/go.js +120 -0
- package/languages/index.js +422 -4
- package/languages/java.js +712 -0
- package/languages/javascript.js +1460 -2
- package/languages/lexical-scope.js +68 -0
- package/languages/python.js +1672 -1
- package/languages/rust.js +91 -0
- package/mcp/server.js +44 -110
- package/package.json +11 -6
|
@@ -2007,6 +2007,146 @@ function _defIdentity(def) {
|
|
|
2007
2007
|
return `${path.resolve(def.file)}\0${def.startLine}`;
|
|
2008
2008
|
}
|
|
2009
2009
|
|
|
2010
|
+
// Descendant types visited when asking who can satisfy a contract by shape;
|
|
2011
|
+
// past it the answer is "anything may" (the conservative direction).
|
|
2012
|
+
const STRUCTURAL_DESCENDANT_LIMIT = 512;
|
|
2013
|
+
|
|
2014
|
+
/** Members declared in one type definition's own body. */
|
|
2015
|
+
function _ownMembersOf(index, typeDef) {
|
|
2016
|
+
const end = typeDef.endLine || typeDef.startLine;
|
|
2017
|
+
return (index.files.get(typeDef.file)?.symbols || []).filter(member =>
|
|
2018
|
+
member.className === typeDef.name && member !== typeDef &&
|
|
2019
|
+
member.startLine >= typeDef.startLine && member.startLine <= end);
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
/**
|
|
2023
|
+
* Member names a type has, its own and those it inherits through declared
|
|
2024
|
+
* project supertypes. `open` when a supertype is not a project type: what it
|
|
2025
|
+
* contributes is unknown, so any name may be there.
|
|
2026
|
+
*/
|
|
2027
|
+
function _memberNamesOf(index, typeDefs) {
|
|
2028
|
+
const names = new Set();
|
|
2029
|
+
let open = false;
|
|
2030
|
+
const seen = new Set();
|
|
2031
|
+
const queue = [...typeDefs];
|
|
2032
|
+
while (queue.length > 0) {
|
|
2033
|
+
const typeDef = queue.shift();
|
|
2034
|
+
if (seen.has(typeDef)) continue;
|
|
2035
|
+
seen.add(typeDef);
|
|
2036
|
+
for (const member of _ownMembersOf(index, typeDef)) names.add(member.name);
|
|
2037
|
+
for (const raw of declaredSupertypes(typeDef)) {
|
|
2038
|
+
const parents = _projectTypeDefs(index, _bareTypeName(raw), typeDef);
|
|
2039
|
+
if (parents.length === 0) open = true;
|
|
2040
|
+
else queue.push(...parents);
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
return { names, open };
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
/**
|
|
2047
|
+
* What a project type says about a member called `name`, through its own
|
|
2048
|
+
* body and its declared project supertypes: 'required' (some declaration of
|
|
2049
|
+
* it is a requirement), 'optional' (declared, never required), 'unknown'
|
|
2050
|
+
* (not declared, but a supertype is not a project type and may require
|
|
2051
|
+
* it), 'absent'.
|
|
2052
|
+
*/
|
|
2053
|
+
function requirementIn(index, typeDefs, name) {
|
|
2054
|
+
const seen = new Set();
|
|
2055
|
+
const queue = [...typeDefs];
|
|
2056
|
+
let open = false;
|
|
2057
|
+
let declared = false;
|
|
2058
|
+
while (queue.length > 0) {
|
|
2059
|
+
const typeDef = queue.shift();
|
|
2060
|
+
if (seen.has(typeDef)) continue;
|
|
2061
|
+
seen.add(typeDef);
|
|
2062
|
+
for (const member of _ownMembersOf(index, typeDef)) {
|
|
2063
|
+
if (member.name !== name) continue;
|
|
2064
|
+
if (member.requiredMember) return 'required';
|
|
2065
|
+
declared = true;
|
|
2066
|
+
}
|
|
2067
|
+
for (const raw of declaredSupertypes(typeDef)) {
|
|
2068
|
+
const parents = _projectTypeDefs(index, _bareTypeName(raw), typeDef);
|
|
2069
|
+
if (parents.length === 0) open = true;
|
|
2070
|
+
else queue.push(...parents);
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
if (declared) return 'optional';
|
|
2074
|
+
return open ? 'unknown' : 'absent';
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
/**
|
|
2078
|
+
* Project contracts the owner of `def` satisfies WITHOUT naming them, and
|
|
2079
|
+
* that require a member called `def.name` (trait `structuralContract`: a
|
|
2080
|
+
* TypeScript interface or object type, a Python Protocol class). Such a
|
|
2081
|
+
* type can be passed, assigned or returned as the contract with no
|
|
2082
|
+
* `implements` clause to follow, so the member can be the thing that makes
|
|
2083
|
+
* a conversion compile while nothing in the project names it.
|
|
2084
|
+
*
|
|
2085
|
+
* Satisfaction is decided on member NAMES: the owner (with what it
|
|
2086
|
+
* inherits) has every member the contract's own body requires. That is
|
|
2087
|
+
* wider than the type checker's rule on purpose. It withholds a claim; it
|
|
2088
|
+
* never grants one.
|
|
2089
|
+
*/
|
|
2090
|
+
function structuralContractsRequiring(index, def) {
|
|
2091
|
+
if (!def?.className) return [];
|
|
2092
|
+
const isContract = langTraits(index.files.get(def.file)?.language)?.structuralContract;
|
|
2093
|
+
if (typeof isContract !== 'function') return [];
|
|
2094
|
+
const owners = ownerClassDefs(index, def);
|
|
2095
|
+
// A member OF a contract is the requirement, not a satisfier of one.
|
|
2096
|
+
if (owners.length === 0 || owners.some(owner => isContract(owner))) return [];
|
|
2097
|
+
const contracts = [];
|
|
2098
|
+
// Who can stand in for a contract through this member: its owner, and
|
|
2099
|
+
// every project type that inherits it. A descendant may be the one that
|
|
2100
|
+
// completes the shape (`Base.greet` plus `English.name`).
|
|
2101
|
+
let satisfiers = null;
|
|
2102
|
+
const satisfiersOf = () => {
|
|
2103
|
+
if (satisfiers) return satisfiers;
|
|
2104
|
+
const sets = [_memberNamesOf(index, owners)];
|
|
2105
|
+
const seen = new Set(owners);
|
|
2106
|
+
const queue = owners.map(owner => owner.name);
|
|
2107
|
+
let visited = 0;
|
|
2108
|
+
while (queue.length > 0) {
|
|
2109
|
+
if (++visited > STRUCTURAL_DESCENDANT_LIMIT) { sets.push({ names: new Set(), open: true }); break; }
|
|
2110
|
+
for (const child of index.extendedByGraph?.get(queue.shift()) || []) {
|
|
2111
|
+
const childName = typeof child === 'string' ? child : child.name;
|
|
2112
|
+
for (const childDef of _projectTypeDefs(index, childName)) {
|
|
2113
|
+
if (seen.has(childDef) || (child.file && childDef.file !== child.file)) continue;
|
|
2114
|
+
seen.add(childDef);
|
|
2115
|
+
sets.push(_memberNamesOf(index, [childDef]));
|
|
2116
|
+
queue.push(childDef.name);
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
// The member asked about is a member of its owner, and so of every
|
|
2121
|
+
// descendant, whether or not the file's own list holds it (a
|
|
2122
|
+
// declaration that was deleted is asked about as if it still stood
|
|
2123
|
+
// there).
|
|
2124
|
+
for (const set of sets) set.names.add(def.name);
|
|
2125
|
+
satisfiers = sets;
|
|
2126
|
+
return satisfiers;
|
|
2127
|
+
};
|
|
2128
|
+
for (const requirement of index.symbols.get(def.name) || []) {
|
|
2129
|
+
if (!requirement.requiredMember || !requirement.className) continue;
|
|
2130
|
+
const contractKind = langTraits(index.files.get(requirement.file)?.language)?.structuralContract;
|
|
2131
|
+
if (typeof contractKind !== 'function') continue;
|
|
2132
|
+
// The type the requirement is written in: any kind the trait
|
|
2133
|
+
// accepts (an object type alias is not a class kind).
|
|
2134
|
+
const declaring = (index.symbols.get(requirement.className) || []).filter(type =>
|
|
2135
|
+
type !== requirement && type.file === requirement.file &&
|
|
2136
|
+
type.startLine <= requirement.startLine &&
|
|
2137
|
+
(type.endLine || type.startLine) >= requirement.startLine);
|
|
2138
|
+
for (const contract of declaring) {
|
|
2139
|
+
if (!contractKind(contract) || contracts.includes(contract)) continue;
|
|
2140
|
+
const required = _ownMembersOf(index, contract)
|
|
2141
|
+
.filter(member => member.requiredMember).map(member => member.name);
|
|
2142
|
+
if (satisfiersOf().some(set => set.open || required.every(name => set.names.has(name)))) {
|
|
2143
|
+
contracts.push(contract);
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
return contracts;
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2010
2150
|
/**
|
|
2011
2151
|
* Go rename closure for a method or interface-method definition: the
|
|
2012
2152
|
* bipartite fixed point between interfaces requiring the name and named
|
|
@@ -2461,6 +2601,8 @@ module.exports = {
|
|
|
2461
2601
|
typedLiteralContract,
|
|
2462
2602
|
typedLiteralMembers,
|
|
2463
2603
|
goContractClosure,
|
|
2604
|
+
structuralContractsRequiring,
|
|
2605
|
+
requirementIn,
|
|
2464
2606
|
goMethodFingerprint,
|
|
2465
2607
|
splitGoSignatureList,
|
|
2466
2608
|
goDeclarationType,
|