ucn 5.6.0 → 5.6.1
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 +4 -2
- package/.claude/skills/ucn/references/commands.md +1 -1
- package/CHANGELOG.md +11 -0
- package/README.md +5 -8
- package/core/analysis.js +3 -3
- package/core/cache.js +3 -1
- package/core/call-fit.js +130 -0
- package/core/callers.js +1 -1
- package/core/capture.js +40 -8
- package/core/change-kinds.js +221 -2
- package/core/check.js +48 -15
- package/core/command-contracts.js +2 -2
- package/core/deadcode.js +94 -23
- package/core/deletion.js +29 -9
- package/core/entrypoint-toml.js +110 -0
- package/core/index-ir.js +2 -2
- package/core/ir.js +1 -1
- package/core/outgoing-check.js +116 -0
- package/core/output/check.js +5 -2
- package/core/output/reporting.js +4 -0
- package/core/output/search.js +3 -0
- package/core/output/tracing.js +1 -1
- package/core/output-budget.js +29 -11
- package/core/python-binding-identity.js +707 -0
- package/core/reflection.js +99 -10
- package/core/registry.js +2 -2
- package/core/runtime-entrypoints.js +159 -0
- package/core/search.js +61 -38
- package/core/test-units.js +116 -42
- package/core/tracing.js +193 -635
- package/core/verify.js +37 -12
- package/languages/csharp.js +4 -4
- package/languages/go.js +1 -1
- package/languages/index.js +45 -1
- package/languages/java.js +4 -4
- package/languages/javascript.js +40 -6
- package/languages/python.js +49 -15
- package/languages/rust.js +126 -112
- package/languages/static-js.js +88 -0
- package/mcp/server.js +1 -1
- package/package.json +4 -3
package/core/output-budget.js
CHANGED
|
@@ -21,6 +21,9 @@ const CONTRACT_LINE_RE = /^\s*(?:(?:Summary|ACCOUNT|CONTRACT|WARNING|FILTERED|CA
|
|
|
21
21
|
// The pre-commit check's verdict line is one of them (`repo` prints a
|
|
22
22
|
// TRUST level of its own, which is orientation, not a verdict).
|
|
23
23
|
const TRUST_LINE_RE = /^(?:(?:ACCOUNT|CONTRACT|WARNING|FILTERED|CALLEE ACCOUNT|TREE ACCOUNT|VALUE ACCOUNT|TYPE ACCOUNT):|TRUST: (?:BLOCKED|REVIEW_REQUIRED|READY_FOR_TOOLCHAIN)\b)/;
|
|
24
|
+
// A count or deletion verdict is the answer the warnings qualify. Preserve
|
|
25
|
+
// it with those warnings, or explicitly withhold the answer when both cannot fit.
|
|
26
|
+
const RESULT_LINE_RE = /^(?:Dead code: \d+ unused symbol\(s\)|No dead code found\.|VERDICT: (?:no-static-dependents|has-static-dependents|review)\b)/;
|
|
24
27
|
const MAX_PRESERVED_CONTRACT_LINES = 24;
|
|
25
28
|
const MAX_PRESERVED_CONTRACT_CHARS = 8000;
|
|
26
29
|
|
|
@@ -45,10 +48,10 @@ function contractCandidates(fullText) {
|
|
|
45
48
|
// Shell-shaped MCP/interactive results prefix disclosures with '# '.
|
|
46
49
|
// Match their contents but retain the prefix in the preserved text.
|
|
47
50
|
const evidenceLine = contractLine.replace(/^\s*# /, '').trim();
|
|
48
|
-
if (!CONTRACT_LINE_RE.test(evidenceLine)) continue;
|
|
51
|
+
if (!CONTRACT_LINE_RE.test(evidenceLine) && !RESULT_LINE_RE.test(evidenceLine)) continue;
|
|
49
52
|
const line = contractLine.trim();
|
|
50
53
|
if (!line) continue;
|
|
51
|
-
const priority = TRUST_LINE_RE.test(evidenceLine)
|
|
54
|
+
const priority = TRUST_LINE_RE.test(evidenceLine) || RESULT_LINE_RE.test(evidenceLine)
|
|
52
55
|
? 0
|
|
53
56
|
: /^\d+ test-file usage\(s\) hidden\b/.test(evidenceLine) ? 1 : 2;
|
|
54
57
|
candidates.push({ line, priority, sourceIndex });
|
|
@@ -319,7 +322,7 @@ function applyOutputBudget(text, {
|
|
|
319
322
|
}
|
|
320
323
|
const supportsAll = FLAG_APPLICABILITY[canonical]?.includes('all') &&
|
|
321
324
|
!(canonical === 'deps' && params.cycles);
|
|
322
|
-
const noticesFor = (target, fullChars) => {
|
|
325
|
+
const noticesFor = (target, fullChars, budget = hardLimit) => {
|
|
323
326
|
const allHint = supportsAll
|
|
324
327
|
? (target === 'mcp'
|
|
325
328
|
? 'Use all=true or max_chars=<n> (100K maximum).'
|
|
@@ -333,21 +336,24 @@ function applyOutputBudget(text, {
|
|
|
333
336
|
? `Raise ${raiseHint}.`
|
|
334
337
|
: `Narrow with ${compactScope || raiseHint}; raise ${raiseHint}.`;
|
|
335
338
|
return {
|
|
336
|
-
longNotice: `... OUTPUT TRUNCATED: ${fullChars} chars total; hard limit ${
|
|
339
|
+
longNotice: `... OUTPUT TRUNCATED: ${fullChars} chars total; hard limit ${budget}. ` +
|
|
337
340
|
`${narrowingHint(command, target, params)} ${allHint}`,
|
|
338
|
-
compactNotice: `... OUTPUT TRUNCATED (${fullChars}→${
|
|
339
|
-
shortNotice: `... OUTPUT TRUNCATED. Raise ${raiseHint}.`,
|
|
341
|
+
compactNotice: `... OUTPUT TRUNCATED (${fullChars}→${budget}). ${compactGuidance}`,
|
|
342
|
+
shortNotice: `... OUTPUT TRUNCATED (${fullChars}→${budget}). Raise ${raiseHint}.`,
|
|
343
|
+
// At the tightest budgets, disclosures outrank the repeated
|
|
344
|
+
// raise-budget guidance; retain the full size and limit.
|
|
345
|
+
minimalNotice: `... OUTPUT TRUNCATED (${fullChars}→${budget}).`,
|
|
340
346
|
raiseHint,
|
|
341
347
|
};
|
|
342
348
|
};
|
|
343
349
|
const ownNotices = noticesFor(surface, text.length);
|
|
344
350
|
if (paired) {
|
|
345
351
|
const peerNotices = noticesFor(surface === 'mcp' ? 'cli' : 'mcp', peerText.length);
|
|
346
|
-
for (const name of ['longNotice', 'compactNotice', 'shortNotice']) {
|
|
352
|
+
for (const name of ['longNotice', 'compactNotice', 'shortNotice', 'minimalNotice']) {
|
|
347
353
|
costs.set(ownNotices[name], Math.max(ownNotices[name].length, peerNotices[name].length));
|
|
348
354
|
}
|
|
349
355
|
}
|
|
350
|
-
const { longNotice, compactNotice, shortNotice, raiseHint } = ownNotices;
|
|
356
|
+
const { longNotice, compactNotice, shortNotice, minimalNotice, raiseHint } = ownNotices;
|
|
351
357
|
const compactBudget = limit < 500;
|
|
352
358
|
|
|
353
359
|
// Trust lines (ACCOUNT/CONTRACT/WARNING/...) qualify the answer: room for
|
|
@@ -456,7 +462,16 @@ function applyOutputBudget(text, {
|
|
|
456
462
|
`... OUTPUT TRUNCATED (${fullChars}→${hardLimit}): answer withheld; ` +
|
|
457
463
|
`${shown} of ${trust.length} trust line(s) shown. Raise ${target === 'mcp' ? 'max_chars' : '--max-chars'} to at least ${needed}.`;
|
|
458
464
|
// Smallest budget whose shortest layout carries every trust line.
|
|
459
|
-
|
|
465
|
+
let needed = terminalChars + lineCost(minimalNotice) + trustChars;
|
|
466
|
+
// Raising the limit can add a digit to the notice itself. Compute
|
|
467
|
+
// the advertised budget using that budget's notice, for both peers.
|
|
468
|
+
for (;;) {
|
|
469
|
+
const noticeChars = Math.max(noticesFor(surface, text.length, needed).minimalNotice.length,
|
|
470
|
+
paired ? noticesFor(surface === 'mcp' ? 'cli' : 'mcp', peerText.length, needed).minimalNotice.length : 0);
|
|
471
|
+
const required = terminalChars + noticeChars + trustChars;
|
|
472
|
+
if (required <= needed) break;
|
|
473
|
+
needed = required;
|
|
474
|
+
}
|
|
460
475
|
let shown = 0;
|
|
461
476
|
const noticeCost = text => paired ? Math.max(text.length,
|
|
462
477
|
text.replace(surface === 'mcp' ? 'max_chars' : '--max-chars', surface === 'mcp' ? '--max-chars' : 'max_chars').length) : text.length;
|
|
@@ -507,7 +522,9 @@ function applyOutputBudget(text, {
|
|
|
507
522
|
|
|
508
523
|
if (compactBudget) {
|
|
509
524
|
// Tiny transports: every disclosure outranks body detail.
|
|
510
|
-
return pick(() => layout(compactNotice, '', '\n', limit),
|
|
525
|
+
return pick(() => layout(compactNotice, '', '\n', limit),
|
|
526
|
+
() => layout(shortNotice, '', '\n', limit),
|
|
527
|
+
() => layout(minimalNotice, '', '\n', limit)) ||
|
|
511
528
|
(trust.length > 0 ? withheld() : bare());
|
|
512
529
|
}
|
|
513
530
|
|
|
@@ -547,7 +564,8 @@ function applyOutputBudget(text, {
|
|
|
547
564
|
const optionalShare = Math.max(0, Math.min(MAX_PRESERVED_CONTRACT_CHARS, Math.floor(limit * 0.5)) - trustChars);
|
|
548
565
|
return pick(() => layout(longNotice, heading, '\n\n', optionalShare),
|
|
549
566
|
() => layout(compactNotice, '', '\n', optionalShare),
|
|
550
|
-
() => layout(shortNotice, '', '\n', optionalShare)
|
|
567
|
+
() => layout(shortNotice, '', '\n', optionalShare),
|
|
568
|
+
() => layout(minimalNotice, '', '\n', optionalShare)) ||
|
|
551
569
|
(trust.length > 0 ? withheld() : bare());
|
|
552
570
|
}
|
|
553
571
|
|