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:
morluto
2026-10-22 02:44:14 +08:00
committed by GitHub
parent 01788bac86
commit a0214e0e0e
22 changed files with 1166 additions and 87 deletions
@@ -70,8 +70,17 @@ it("bounds unknowns independently of retained nodes and accounts for examined om
expect.arrayContaining([
{ name: "semantic_graph_unknown_ceiling", value: 2, unit: "items" },
{ name: "semantic_graph_file_unknown_ceiling", value: 2, unit: "items" },
{ name: "max_semantic_unknowns", value: 2, unit: "items" },
{ name: "max_semantic_unknowns_per_file", value: 2, unit: "items" },
]),
);
expect(graph.limitations.join("\n")).toContain("max_semantic_unknowns is 2");
expect(graph.limitations.join("\n")).toContain(
"max_semantic_unknowns_per_file is 2",
);
expect(graph.limitations.join("\n")).toContain(
"Omission coverage counts examined emission occurrences",
);
expect(javaScriptSemanticGraphSchema.parse(graph)).toEqual(graph);
expect(
queryJavaScriptSemanticGraph(graph, {
@@ -123,6 +132,70 @@ it("enforces per-file and total unknown capacities across transferred files", ()
0,
),
).toBe(fileProjection().unknowns.length * 3 - 3);
expect(graph.limitations.join("\n")).toContain("max_semantic_unknowns is 3");
expect(graph.limitations.join("\n")).toContain(
"max_semantic_unknowns_per_file is 2",
);
expect(graph.coverage.limits).toEqual(
expect.arrayContaining([
{ name: "semantic_graph_unknown_ceiling", value: 3, unit: "items" },
{ name: "semantic_graph_file_unknown_ceiling", value: 2, unit: "items" },
{ name: "max_semantic_unknowns", value: 3, unit: "items" },
{ name: "max_semantic_unknowns_per_file", value: 2, unit: "items" },
]),
);
});
it("names only the unknown ceiling that stopped retention", () => {
const perFile = createJavaScriptSemanticGraphProjection({
totalUnknowns: 50,
fileUnknowns: 2,
});
perFile.projectFile(source(), analyzeJavaScriptSemantics(text));
const perFileGraph = perFile.finish(digest, application);
expect(perFileGraph.limitations.join("\n")).toContain(
"max_semantic_unknowns_per_file is 2",
);
expect(perFileGraph.limitations.join("\n")).not.toContain(
"max_semantic_unknowns is 50",
);
expect(perFileGraph.coverage.limits).toEqual(
expect.arrayContaining([
{ name: "semantic_graph_unknown_ceiling", value: 50, unit: "items" },
{ name: "semantic_graph_file_unknown_ceiling", value: 2, unit: "items" },
{ name: "max_semantic_unknowns", value: 50, unit: "items" },
{ name: "max_semantic_unknowns_per_file", value: 2, unit: "items" },
]),
);
const total = createJavaScriptSemanticGraphProjection({
totalUnknowns: 2,
fileUnknowns: 50,
});
total.projectFile(source(), analyzeJavaScriptSemantics(text));
const totalLimitation = total
.finish(digest, application)
.limitations.join("\n");
expect(totalLimitation).toContain("max_semantic_unknowns is 2");
expect(totalLimitation).not.toContain("max_semantic_unknowns_per_file is 50");
const unavailable = createJavaScriptSemanticGraphProjection({
totalUnknowns: 20,
fileUnknowns: 2,
});
unavailable.recordUnavailableFile(
source(),
"Source unavailable",
null,
"incomplete-module",
);
const unavailableLimitation = unavailable
.finish(digest, application)
.limitations.join("\n");
expect(unavailableLimitation).toContain(
"max_semantic_unknowns_per_file is 2",
);
expect(unavailableLimitation).not.toContain("max_semantic_unknowns is 20");
});
it("rejects excess transferred unknowns before adopting any file facts", () => {