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.
Files changed (74) hide show
  1. package/.claude/skills/ucn/SKILL.md +35 -12
  2. package/.claude/skills/ucn/references/commands.md +21 -17
  3. package/.claude/skills/ucn/references/resolution-rules.md +4 -0
  4. package/.claude/skills/ucn/references/trust-contract.md +4 -4
  5. package/CHANGELOG.md +474 -0
  6. package/README.md +71 -29
  7. package/cli/flags.js +184 -0
  8. package/cli/index.js +138 -324
  9. package/core/account.js +44 -87
  10. package/core/analysis.js +273 -107
  11. package/core/ast-analysis.js +2 -0
  12. package/core/bridge.js +29 -65
  13. package/core/cache.js +101 -16
  14. package/core/callers.js +352 -70
  15. package/core/capture.js +331 -0
  16. package/core/change-kinds.js +888 -0
  17. package/core/check.js +1117 -139
  18. package/core/client-receivers.js +189 -0
  19. package/core/command-contracts.js +7 -6
  20. package/core/constructed-class.js +1195 -0
  21. package/core/contract-membership.js +142 -0
  22. package/core/deadcode.js +388 -85
  23. package/core/deletion.js +401 -0
  24. package/core/discovery.js +104 -9
  25. package/core/entrypoints.js +12 -6
  26. package/core/evidence-bands.js +68 -0
  27. package/core/evidence-bands.json +44 -0
  28. package/core/execute.js +172 -161
  29. package/core/hot-summary.js +241 -0
  30. package/core/index-ir.js +3 -1
  31. package/core/inprocess-clients.js +41 -15
  32. package/core/ir.js +5 -1
  33. package/core/member-signatures.js +789 -0
  34. package/core/output/analysis-ext.js +20 -10
  35. package/core/output/analysis.js +98 -60
  36. package/core/output/check.js +98 -37
  37. package/core/output/doctor.js +34 -1
  38. package/core/output/find.js +2 -1
  39. package/core/output/lines.js +63 -3
  40. package/core/output/public.js +30 -11
  41. package/core/output/refactoring.js +32 -0
  42. package/core/output/reporting.js +21 -2
  43. package/core/output/search.js +11 -2
  44. package/core/output/tracing.js +35 -7
  45. package/core/output-budget.js +124 -57
  46. package/core/parallel-build.js +3 -3
  47. package/core/project.js +106 -23
  48. package/core/provenance-type.js +12 -5
  49. package/core/public-command.js +35 -9
  50. package/core/python-modules.js +6 -0
  51. package/core/reflection.js +166 -23
  52. package/core/registry.js +623 -72
  53. package/core/reporting.js +69 -34
  54. package/core/request-helpers.js +63 -7
  55. package/core/review-items.js +75 -0
  56. package/core/search.js +89 -128
  57. package/core/shared.js +0 -45
  58. package/core/snapshot.js +350 -0
  59. package/core/source-universe.js +707 -0
  60. package/core/test-units.js +3624 -0
  61. package/core/tracing.js +150 -96
  62. package/core/verify.js +27 -11
  63. package/languages/adapter.js +8 -3
  64. package/languages/c-family.js +12 -0
  65. package/languages/csharp.js +634 -0
  66. package/languages/go.js +120 -0
  67. package/languages/index.js +422 -4
  68. package/languages/java.js +712 -0
  69. package/languages/javascript.js +1460 -2
  70. package/languages/lexical-scope.js +68 -0
  71. package/languages/python.js +1672 -1
  72. package/languages/rust.js +91 -0
  73. package/mcp/server.js +44 -110
  74. 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,