feat(javascript): query retained application facts by exact path (#4265)

Expose exact-path, selected-property, paged reads of retained JavaScript application facts through the shared CLI/MCP analysis view. Preserve original identities, complete row Evidence and partial coverage; retain reproducible real-Joplin and actual-agent measurements, including negative cost results.

Fixes #4190. Part of #4027. Code mode remains deferred by #4091.

Integrate main after #4274. Validation: 114 distinct focused cases across documented invocations, 106 Python cases, full static/docs checks and 18 version-labelled real-application workflows with 9 complete CLI/MCP view parity controls. Preserve two local fixture deadline failures and the unchanged test passing on an available single CPU. Final-head CI passed all 36 jobs after one Windows timeout retry without source changes; both exact-head automated reviews are clear and all review threads resolved. Downloadable apps and raw large Evidence/transcripts are excluded.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
This commit is contained in:
YsopwnableandKaoru0822 authored and GitHub committed 2026-10-16 12:46:53 +08:00
1 parent 1b97b0f370
commit d9d085a15e
18 files changed
+10256 -50

No files matched your search

@@ -8,6 +8,11 @@ import type { JavaScriptApplicationAnalysisResult } from "../javascript/javascri
import type { ApplicationNode } from "../javascript/javascriptApplicationGraphSchemas.js";
import { err, ok, type Result } from "../result.js";
import type { JavaScriptModuleReference } from "./javascriptModuleReferences.js";
import {
javascriptApplicationSourceCoverage,
type JavaScriptApplicationSourceCoverage,
} from "./javascriptApplicationCoverage.js";
import { projectJavaScriptFacts } from "./javascriptFactsView.js";
import {
boundedViewMessages,
completeWithinViewCoverage as completeCoverage,
@@ -190,32 +195,24 @@ const moduleReference = ({
};
};
const applicationUnknownCount = (
analysis: JavaScriptApplicationAnalysisResult,
): number =>
analysis.graph.nodes.reduce(
(count, node) => count + Number(node.kind === "unknown"),
0,
);
const javascriptCoverageUnknowns = (
analysis: JavaScriptApplicationAnalysisResult,
coverage: JavaScriptApplicationSourceCoverage,
): readonly string[] => {
const unknowns: string[] = [];
if (analysis.graph.coverage.status !== "complete")
unknowns.push(`graph.coverage.status is ${analysis.graph.coverage.status}`);
if (analysis.semantic_graph.coverage.status !== "complete")
if (coverage.application.status !== "complete")
unknowns.push(`graph.coverage.status is ${coverage.application.status}`);
if (coverage.semantic.status !== "complete")
unknowns.push(
`semantic_graph.coverage.status is ${analysis.semantic_graph.coverage.status}`,
`semantic_graph.coverage.status is ${coverage.semantic.status}`,
);
const applicationUnknowns = applicationUnknownCount(analysis);
const applicationUnknowns = coverage.application_unknown_count;
if (applicationUnknowns > 0)
unknowns.push(
`${String(applicationUnknowns)} application graph unknowns remain in the parent Evidence.`,
);
if (analysis.semantic_graph.unknowns.length > 0)
if (coverage.semantic_unknown_count > 0)
unknowns.push(
`${String(analysis.semantic_graph.unknowns.length)} semantic graph unknowns remain in the parent Evidence.`,
`${String(coverage.semantic_unknown_count)} semantic graph unknowns remain in the parent Evidence.`,
);
return unknowns;
};
@@ -223,6 +220,7 @@ const javascriptCoverageUnknowns = (
const parentFields = (
parent: AnalysisViewParent,
analysis: JavaScriptApplicationAnalysisResult,
sourceCoverage: JavaScriptApplicationSourceCoverage,
) => {
const limitations = [
...analysis.limitations,
@@ -246,7 +244,7 @@ const parentFields = (
limitations,
parent.evidenceId,
"unknowns",
javascriptCoverageUnknowns(analysis),
javascriptCoverageUnknowns(sourceCoverage),
),
};
};
@@ -315,33 +313,36 @@ export const projectJavaScriptApplicationView = (
view.kind !== "summary" &&
view.kind !== "item" &&
view.kind !== "page" &&
view.kind !== "javascript"
view.kind !== "javascript" &&
view.kind !== "javascript-facts"
)
return err(
jsIncompatible(
"JavaScript application Evidence supports summary, module item, module page or typed JavaScript reference views.",
"JavaScript application Evidence supports summary, module item/page, typed module references or selected JavaScript facts.",
),
);
const shared = parentFields(parent, analysis);
const sourceCoverage = javascriptApplicationSourceCoverage(analysis);
const shared = parentFields(parent, analysis, sourceCoverage);
if (view.kind === "javascript-facts") {
const { rows, total } = projectJavaScriptFacts(analysis.graph.nodes, view);
return ok({
...shared,
kind: "javascript-facts",
view,
rows,
source_coverage: sourceCoverage,
coverage: pageCoverage(view.offset, rows.length, total),
});
}
if (view.kind === "javascript") {
const { entries, total } = modulePage(analysis.graph.nodes, view);
const rows = entries.map(moduleReference);
const { families: _families, ...semantic } =
analysis.semantic_graph.coverage;
return ok({
...shared,
kind: "javascript",
view,
rows,
source_coverage: {
...(analysis.source_selection === undefined
? {}
: { source_selection: analysis.source_selection }),
application: analysis.graph.coverage,
semantic,
application_unknown_count: applicationUnknownCount(analysis),
semantic_unknown_count: analysis.semantic_graph.unknowns.length,
},
source_coverage: sourceCoverage,
coverage: pageCoverage(view.offset, rows.length, total),
});
}
@@ -375,8 +376,8 @@ export const projectJavaScriptApplicationView = (
}),
),
},
application_unknowns: applicationUnknownCount(analysis),
semantic_unknowns: analysis.semantic_graph.unknowns.length,
application_unknowns: sourceCoverage.application_unknown_count,
semantic_unknowns: sourceCoverage.semantic_unknown_count,
}),
limitation_count: analysis.limitations.length,
},