mirror of
https://github.com/morluto/rea
synced 2026-10-27 14:42:18 -04: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:
@@ -748,6 +748,142 @@ it("bounds semantic node projection and reports the ceiling in coverage", () =>
|
||||
({ name }) => name === "semantic_graph_node_ceiling",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(graph.coverage.limits).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ name: "max_semantic_nodes" }),
|
||||
expect.objectContaining({ name: "max_semantic_nodes_per_file" }),
|
||||
]),
|
||||
);
|
||||
expect(graph.limitations.join("\n")).toContain(
|
||||
"max_semantic_nodes_per_file is 20000",
|
||||
);
|
||||
expect(graph.limitations.join("\n")).not.toContain(
|
||||
"max_semantic_nodes is 100000",
|
||||
);
|
||||
expect(graph.limitations.join("\n")).toContain("1 to 1000000");
|
||||
expect(graph.coverage.limits).toEqual(
|
||||
expect.arrayContaining([
|
||||
{ name: "semantic_graph_node_ceiling", value: 100_000, unit: "items" },
|
||||
{
|
||||
name: "semantic_graph_file_node_ceiling",
|
||||
value: 20_000,
|
||||
unit: "items",
|
||||
},
|
||||
{ name: "max_semantic_nodes", value: 100_000, unit: "items" },
|
||||
{ name: "max_semantic_nodes_per_file", value: 20_000, unit: "items" },
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
const semanticApplication = {
|
||||
graph_id: `jag_${"b".repeat(64)}`,
|
||||
nodes: [],
|
||||
};
|
||||
|
||||
const semanticFile = (path: string, value: string): JavaScriptArtifactFile => ({
|
||||
path,
|
||||
container_sha256: SHA256,
|
||||
sha256: SHA256,
|
||||
bytes: Buffer.byteLength(value),
|
||||
inventory_artifact_id: `art_${SHA256}`,
|
||||
kind: "javascript",
|
||||
unpacked: false,
|
||||
text: { included: true, value },
|
||||
});
|
||||
|
||||
const finishSources = (
|
||||
limits: {
|
||||
readonly totalNodes: number;
|
||||
readonly fileNodes: number;
|
||||
},
|
||||
sources: readonly { readonly path: string; readonly text: string }[],
|
||||
) => {
|
||||
const projection = createJavaScriptSemanticGraphProjection(limits);
|
||||
for (const source of sources)
|
||||
projection.projectFile(
|
||||
semanticFile(source.path, source.text),
|
||||
analyzeJavaScriptSemantics(source.text),
|
||||
);
|
||||
return projection.finish(SHA256, semanticApplication);
|
||||
};
|
||||
|
||||
it("names only the node ceiling that stopped retention", () => {
|
||||
const references = (count: number) => "external;\n".repeat(count);
|
||||
const perFile = finishSources({ totalNodes: 10, fileNodes: 3 }, [
|
||||
{ path: "only.js", text: references(5) },
|
||||
]);
|
||||
expect(perFile.nodes).toHaveLength(3);
|
||||
expect(perFile.limitations.join("\n")).toContain(
|
||||
"max_semantic_nodes_per_file is 3",
|
||||
);
|
||||
expect(perFile.limitations.join("\n")).not.toContain(
|
||||
"max_semantic_nodes is 10",
|
||||
);
|
||||
expect(perFile.coverage.limits).toEqual(
|
||||
expect.arrayContaining([
|
||||
{ name: "semantic_graph_node_ceiling", value: 10, unit: "items" },
|
||||
{ name: "semantic_graph_file_node_ceiling", value: 3, unit: "items" },
|
||||
{ name: "max_semantic_nodes", value: 10, unit: "items" },
|
||||
{ name: "max_semantic_nodes_per_file", value: 3, unit: "items" },
|
||||
]),
|
||||
);
|
||||
|
||||
const skipped = finishSources({ totalNodes: 4, fileNodes: 10 }, [
|
||||
{ path: "first.js", text: references(3) },
|
||||
{ path: "second.js", text: references(3) },
|
||||
]);
|
||||
expect(skipped.nodes).toHaveLength(4);
|
||||
expect(
|
||||
skipped.nodes.filter((node) => node.identity.module_path === "second.js"),
|
||||
).toHaveLength(0);
|
||||
expect(skipped.limitations.join("\n")).toContain("max_semantic_nodes is 4");
|
||||
expect(skipped.limitations.join("\n")).not.toContain(
|
||||
"max_semantic_nodes_per_file is 10",
|
||||
);
|
||||
|
||||
const remaining = finishSources({ totalNodes: 5, fileNodes: 4 }, [
|
||||
{ path: "first.js", text: references(2) },
|
||||
{ path: "second.js", text: references(3) },
|
||||
]);
|
||||
expect(remaining.nodes).toHaveLength(5);
|
||||
expect(remaining.limitations.join("\n")).toContain("max_semantic_nodes is 5");
|
||||
expect(remaining.limitations.join("\n")).not.toContain(
|
||||
"max_semantic_nodes_per_file is 4",
|
||||
);
|
||||
|
||||
const both = finishSources({ totalNodes: 5, fileNodes: 3 }, [
|
||||
{ path: "first.js", text: references(5) },
|
||||
{ path: "second.js", text: references(3) },
|
||||
]);
|
||||
expect(both.nodes).toHaveLength(5);
|
||||
expect(both.limitations.join("\n")).toContain("max_semantic_nodes is 5");
|
||||
expect(both.limitations.join("\n")).toContain(
|
||||
"max_semantic_nodes_per_file is 3",
|
||||
);
|
||||
expect(both.limitations.join("\n")).toContain(
|
||||
"Set max_semantic_nodes and max_semantic_nodes_per_file",
|
||||
);
|
||||
});
|
||||
|
||||
it("attributes an adopted file to the ceiling that bounded its offer", () => {
|
||||
const text = "external;\n".repeat(5);
|
||||
const projection = createJavaScriptSemanticGraphProjection({
|
||||
totalNodes: 10,
|
||||
fileNodes: 3,
|
||||
});
|
||||
const steps = projectJavaScriptSemanticFileSteps(
|
||||
semanticFile("adopted.js", text),
|
||||
analyzeJavaScriptSemantics(text),
|
||||
projection.remainingFileCapacity(),
|
||||
);
|
||||
let step = steps.next();
|
||||
while (!step.done) step = steps.next();
|
||||
projection.adoptFileProjection(step.value);
|
||||
const limitation = projection
|
||||
.finish(SHA256, semanticApplication)
|
||||
.limitations.join("\n");
|
||||
expect(limitation).toContain("max_semantic_nodes_per_file is 3");
|
||||
expect(limitation).not.toContain("max_semantic_nodes is 10");
|
||||
});
|
||||
|
||||
it("leaves a small application complete and untruncated", () => {
|
||||
|
||||
Reference in New Issue
Block a user