mirror of
https://github.com/morluto/rea.git
synced 2026-10-29 19:05:45 +00:00
fix(javascript): name heap and semantic ceilings (#6022)
* fix(javascript): name heap and semantic ceilings Refs #5910. Heap exhaustion names max_heap_mb with its effective value, range, and next-analysis worker restart. Semantic ceiling coverage names the four max_semantic_* arguments. Wakaru and transfer ceilings say this release has no runtime override. Co-authored-by: morluto <morluto@users.noreply.github.com> * fix(javascript): distinguish adjustable ceilings from fixed limits The effective transfer file ceiling and the parent result budget follow the CLI/MCP process heap, so recovery names NODE_OPTIONS instead of denying an override. A provenance report over 8 MiB keeps the fixed allowance guidance, and the Wakaru deadline says an unchanged retry may hit it again. Refs #5910 Co-authored-by: morluto <morluto@users.noreply.github.com> * fix(javascript): keep Bun OOM and checkpoint heap controls distinct Bun heap-exhaustion exits no longer claim the ignored max_heap_mb V8 old-space limit. Checkpoint decode names the parent heap and Node NODE_OPTIONS, the same control as the parent result budget. Refs #5910 Co-authored-by: morluto <morluto@users.noreply.github.com> * fix(javascript): name semantic ceilings without claiming both were reached Truncated semantic retention names the total and per-file controls as effective ceilings. Callers only know that retention was truncated, so the limitation no longer says both ceilings were reached. Refs #5910 Co-authored-by: morluto <morluto@users.noreply.github.com> * fix(javascript): name only the semantic ceiling that stopped retention Semantic ceiling limitations claimed both the application total and the per-file control whenever either one truncated the graph. Record which offered budget stopped node and unknown retention, and name only those controls. Coverage limits still list both effective values. Co-authored-by: morluto <morluto@users.noreply.github.com> * fix(javascript): require a value in the NODE_OPTIONS heap example A bare --max-old-space-size is an illegal V8 flag and prevents Node from starting. Parent-heap and transfer-ceiling recovery now share --max-old-space-size=<MiB>, and the Kuna heap remediation uses the same complete form. Co-authored-by: morluto <morluto@users.noreply.github.com> * fix(javascript): limit the old-space placeholder to NODE_OPTIONS recovery The review covers the CLI/MCP NODE_OPTIONS example and the transfer-ceiling copy. The Kuna heap-headroom sentence stays unchanged. Co-authored-by: morluto <morluto@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: morluto <morluto@users.noreply.github.com>
This commit is contained in:
22 files changed
+1166
-87
No files matched your search
@@ -53,6 +53,7 @@ import {
|
||||
JAVASCRIPT_ANALYSIS_RESOURCE_DEFAULTS,
|
||||
JAVASCRIPT_SEMANTIC_ITEM_MAXIMUM,
|
||||
javaScriptAnalysisCoverageLimits,
|
||||
javaScriptSemanticCeilingCoverage,
|
||||
} from "../../domain/javascript/javascriptAnalysisResourceControls.js";
|
||||
import { projectSemanticFunctionFingerprints } from "./JavaScriptSemanticGraphFingerprintProjection.js";
|
||||
import {
|
||||
@@ -205,6 +206,36 @@ export interface JavaScriptSemanticGraphProjection {
|
||||
) => Generator<void, JavaScriptSemanticGraph>;
|
||||
}
|
||||
|
||||
/** Ceilings whose offered budget actually stopped retention. */
|
||||
interface SemanticCeilingReached {
|
||||
total: boolean;
|
||||
perFile: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute a drop to the ceiling that bound this file's offer.
|
||||
*
|
||||
* The offer is the minimum of the per-file ceiling and the remaining
|
||||
* application room. Only that smaller ceiling stopped retention. When the
|
||||
* two values are equal, both did.
|
||||
*/
|
||||
const noteSemanticCeilingReached = (
|
||||
reached: SemanticCeilingReached,
|
||||
totalRoom: number,
|
||||
perFileCeiling: number,
|
||||
): void => {
|
||||
if (perFileCeiling <= totalRoom) reached.perFile = true;
|
||||
if (totalRoom <= perFileCeiling) reached.total = true;
|
||||
};
|
||||
|
||||
const semanticUnknownOccurrences = (
|
||||
omissions: ReadonlyMap<string, { readonly occurrences: number }>,
|
||||
): number => {
|
||||
let count = 0;
|
||||
for (const omission of omissions.values()) count += omission.occurrences;
|
||||
return count;
|
||||
};
|
||||
|
||||
/** Accumulate semantic nodes while each source IR is still file-local. */
|
||||
export const createJavaScriptSemanticGraphProjection = (
|
||||
limits: {
|
||||
@@ -239,6 +270,14 @@ export const createJavaScriptSemanticGraphProjection = (
|
||||
let truncatedFiles = 0;
|
||||
let unavailableFiles = 0;
|
||||
let resourceTruncatedFiles = 0;
|
||||
const nodeCeilingsReached: SemanticCeilingReached = {
|
||||
total: false,
|
||||
perFile: false,
|
||||
};
|
||||
const unknownCeilingsReached: SemanticCeilingReached = {
|
||||
total: false,
|
||||
perFile: false,
|
||||
};
|
||||
const executionLimits = new Map<
|
||||
string,
|
||||
ApplicationCoverage["limits"][number]
|
||||
@@ -250,20 +289,40 @@ export const createJavaScriptSemanticGraphProjection = (
|
||||
): Generator<void, void> {
|
||||
if (state.nodes.size >= nodeCeiling) {
|
||||
truncatedFiles += 1;
|
||||
noteSemanticCeilingReached(
|
||||
nodeCeilingsReached,
|
||||
nodeCeiling - state.nodes.size,
|
||||
fileNodeCeiling,
|
||||
);
|
||||
return;
|
||||
}
|
||||
const remainingTreeBudget = nodeCeiling - state.nodes.size;
|
||||
const unknownsBefore = state.unknowns.size;
|
||||
const omissionsBefore = semanticUnknownOccurrences(state.unknownOmissions);
|
||||
state.fileNodeBudget = Math.min(fileNodeCeiling, remainingTreeBudget);
|
||||
state.fileNodesDropped = false;
|
||||
state.unknownCapacity = Math.min(
|
||||
unknownCeiling,
|
||||
state.unknowns.size + fileUnknownCeiling,
|
||||
unknownsBefore + fileUnknownCeiling,
|
||||
);
|
||||
fingerprints.push(...(yield* projectFileSteps(file, ir, state, paths)));
|
||||
// Nodes were dropped only if the budget actually blocked creation. A file
|
||||
// that exactly fills its share ends with a zero budget without dropping
|
||||
// anything, so the remaining budget alone cannot decide truncation.
|
||||
if (state.fileNodesDropped) truncatedFiles += 1;
|
||||
if (state.fileNodesDropped) {
|
||||
truncatedFiles += 1;
|
||||
noteSemanticCeilingReached(
|
||||
nodeCeilingsReached,
|
||||
remainingTreeBudget,
|
||||
fileNodeCeiling,
|
||||
);
|
||||
}
|
||||
if (semanticUnknownOccurrences(state.unknownOmissions) > omissionsBefore)
|
||||
noteSemanticCeilingReached(
|
||||
unknownCeilingsReached,
|
||||
unknownCeiling - unknownsBefore,
|
||||
fileUnknownCeiling,
|
||||
);
|
||||
state.fileNodeBudget = null;
|
||||
state.unknownCapacity = null;
|
||||
};
|
||||
@@ -291,6 +350,23 @@ export const createJavaScriptSemanticGraphProjection = (
|
||||
unknownIdsByFamily.set(unknown.family, [unknown.unknown_id]);
|
||||
else identifiers.push(unknown.unknown_id);
|
||||
}
|
||||
const unknownCeilingCoverage = unknownsDropped
|
||||
? javaScriptSemanticCeilingCoverage(
|
||||
"unknowns",
|
||||
unknownCeiling,
|
||||
fileUnknownCeiling,
|
||||
unknownCeilingsReached,
|
||||
)
|
||||
: undefined;
|
||||
const nodeCeilingCoverage =
|
||||
truncatedFiles > 0
|
||||
? javaScriptSemanticCeilingCoverage(
|
||||
"nodes",
|
||||
nodeCeiling,
|
||||
fileNodeCeiling,
|
||||
nodeCeilingsReached,
|
||||
)
|
||||
: undefined;
|
||||
const graph = factory({
|
||||
schema: "JavaScriptSemanticRelationGraph",
|
||||
root_artifact_sha256: rootArtifactSha256,
|
||||
@@ -317,34 +393,8 @@ export const createJavaScriptSemanticGraphProjection = (
|
||||
truncatedFiles > 0 || unavailableFiles > 0 ? null : 0,
|
||||
limits: [
|
||||
...executionLimits.values(),
|
||||
...(unknownsDropped
|
||||
? [
|
||||
{
|
||||
name: "semantic_graph_unknown_ceiling",
|
||||
value: unknownCeiling,
|
||||
unit: "items" as const,
|
||||
},
|
||||
{
|
||||
name: "semantic_graph_file_unknown_ceiling",
|
||||
value: fileUnknownCeiling,
|
||||
unit: "items" as const,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(truncatedFiles > 0
|
||||
? [
|
||||
{
|
||||
name: "semantic_graph_node_ceiling",
|
||||
value: nodeCeiling,
|
||||
unit: "items" as const,
|
||||
},
|
||||
{
|
||||
name: "semantic_graph_file_node_ceiling",
|
||||
value: fileNodeCeiling,
|
||||
unit: "items" as const,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(unknownCeilingCoverage?.limits ?? []),
|
||||
...(nodeCeilingCoverage?.limits ?? []),
|
||||
],
|
||||
families: JAVASCRIPT_SEMANTIC_RELATION_FAMILIES.map((family) => ({
|
||||
family,
|
||||
@@ -356,11 +406,14 @@ export const createJavaScriptSemanticGraphProjection = (
|
||||
})),
|
||||
},
|
||||
limitations: [
|
||||
...(unknownsDropped
|
||||
? [
|
||||
"Semantic unknown retention reached an effective capacity. Omission coverage counts examined emission occurrences by family and reason, including repeats; it does not count unexamined source frontiers or distinct discarded identities.",
|
||||
]
|
||||
: []),
|
||||
...(unknownCeilingCoverage === undefined
|
||||
? []
|
||||
: [
|
||||
`${unknownCeilingCoverage.limitation} Omission coverage counts examined emission occurrences by family and reason, including repeats; it does not count unexamined source frontiers or distinct discarded identities.`,
|
||||
]),
|
||||
...(nodeCeilingCoverage === undefined
|
||||
? []
|
||||
: [nodeCeilingCoverage.limitation]),
|
||||
"The semantic graph contains static syntax observations and conservative relationship candidates; it does not claim runtime execution.",
|
||||
"Local data flow does not claim control-flow-sensitive reaching definitions or arbitrary dynamic property resolution.",
|
||||
"Promise ownership covers explicit unshadowed Promise construction, static factories, aggregation, chaining, and await syntax only.",
|
||||
@@ -395,6 +448,10 @@ export const createJavaScriptSemanticGraphProjection = (
|
||||
),
|
||||
}),
|
||||
adoptFileProjection: (projection) => {
|
||||
// Production offers remainingFileCapacity(), already the minimum of
|
||||
// the per-file ceiling and the room left in the application total.
|
||||
const remainingNodes = nodeCeiling - state.nodes.size;
|
||||
const remainingUnknowns = unknownCeiling - state.unknowns.size;
|
||||
const newNodes = projection.nodes.filter(
|
||||
({ node_id }) => !state.nodes.has(node_id),
|
||||
);
|
||||
@@ -426,7 +483,20 @@ export const createJavaScriptSemanticGraphProjection = (
|
||||
state.unknowns.set(unknown.unknown_id, unknown);
|
||||
for (const root of projection.roots) state.roots.add(root);
|
||||
fingerprints.push(...projection.fingerprints);
|
||||
if (projection.nodesTruncated) truncatedFiles += 1;
|
||||
if (projection.nodesTruncated) {
|
||||
truncatedFiles += 1;
|
||||
noteSemanticCeilingReached(
|
||||
nodeCeilingsReached,
|
||||
remainingNodes,
|
||||
fileNodeCeiling,
|
||||
);
|
||||
}
|
||||
if ((projection.omittedUnknownOccurrences?.length ?? 0) > 0)
|
||||
noteSemanticCeilingReached(
|
||||
unknownCeilingsReached,
|
||||
remainingUnknowns,
|
||||
fileUnknownCeiling,
|
||||
);
|
||||
},
|
||||
recordUnavailableFile: (file, reason, limits, unknownReason) => {
|
||||
// Both full and incremental construction enter here. Metadata/native
|
||||
@@ -460,9 +530,13 @@ export const createJavaScriptSemanticGraphProjection = (
|
||||
coverage: partialApplicationCoverage(retainedLimits, null),
|
||||
limitations: [reason],
|
||||
};
|
||||
const unknownsBefore = state.unknowns.size;
|
||||
const omissionsBefore = semanticUnknownOccurrences(
|
||||
state.unknownOmissions,
|
||||
);
|
||||
state.unknownCapacity = Math.min(
|
||||
unknownCeiling,
|
||||
state.unknowns.size + fileUnknownCeiling,
|
||||
unknownsBefore + fileUnknownCeiling,
|
||||
);
|
||||
for (const family of JAVASCRIPT_SEMANTIC_RELATION_FAMILIES) {
|
||||
addSemanticGraphUnknown(state, {
|
||||
@@ -479,6 +553,12 @@ export const createJavaScriptSemanticGraphProjection = (
|
||||
});
|
||||
}
|
||||
state.unknownCapacity = null;
|
||||
if (semanticUnknownOccurrences(state.unknownOmissions) > omissionsBefore)
|
||||
noteSemanticCeilingReached(
|
||||
unknownCeilingsReached,
|
||||
unknownCeiling - unknownsBefore,
|
||||
fileUnknownCeiling,
|
||||
);
|
||||
unavailableFiles += 1;
|
||||
if (unknownReason === "resource-limit" && retainedLimits.length > 0)
|
||||
resourceTruncatedFiles += 1;
|
||||
|
||||
Reference in new issue
Block a user