Planner Autonomy: выбрать comparison chain для явного bidirectional graph

This commit is contained in:
dctouch 2026-05-01 14:20:24 +03:00
parent 1c1383b8b5
commit ea96df9ca1
5 changed files with 27 additions and 17 deletions

View File

@ -57,7 +57,7 @@ The planner now instantiates selected evidence chains from this catalog for the
The follow-up consolidation step moved the value-flow planner seams onto the same catalog fabric:
- bidirectional incoming-vs-outgoing comparison now instantiates `value_flow_comparison`;
- bidirectional incoming-vs-outgoing comparison now instantiates `value_flow_comparison`, including explicit-counterparty comparison graphs rather than only subjectless organization-scope graphs;
- ranked revenue/payment questions now instantiate `value_flow_ranking`;
- organization-scoped open totals now instantiate `value_flow` with subjectless primitives but catalog-owned axes and evidence-gate semantics;
- heuristic fallback routes for value-flow, lifecycle, metadata, movement, document, entity, and unclassified metadata inspection now also use catalog chain templates.
@ -213,6 +213,13 @@ Latest validation after runtime/debug propagation of structured chain matches:
- `npm.cmd run build`: passed
- graphify rebuild: `5940 nodes`, `12909 edges`, `137 communities`
Latest validation after subject-aware bidirectional comparison arbitration:
- targeted planner tests: passed, `36 passed`
- full MCP-discovery suite: passed, `282 passed`, `9 skipped`
- `npm.cmd run build`: passed
- graphify rebuild: `5940 nodes`, `12909 edges`, `137 communities`
## Next Step
The next safe step is still to re-run live replay once the 1C side is actively polling the proxy. In parallel, local-only consolidation can continue by letting selected downstream arbitration consume `catalog_chain_template_matches` where this can be done without changing exact runtime behavior.

View File

@ -81,6 +81,7 @@ It now documents a turnaround that is already operational in code, already mater
- inventory catalog templates now bridge through existing exact inventory recipes (`41.01` scoped stock, supplier overlap, purchase provenance, and sale trace) inside the bounded MCP discovery pilot, while missing selected-item anchors still clarify instead of guessing;
- unambiguous metadata surfaces can now infer the next reviewed lane from `Document.*`, `Register.*`, or `Catalog.*` objects even before upstream labels `downstream_route_family`, while mixed surfaces still do not guess;
- catalog index now scores reviewed chain templates directly from fact/action/axis/comparison/ranking needs, and planner/runtime/debug surfaces expose ranked catalog chain matches through the structured `catalog_chain_template_matches` contract path instead of relying only on reason-code strings;
- explicit-counterparty incoming-vs-outgoing data-need graphs now select the reviewed `value_flow_comparison` chain instead of falling back to generic `value_flow`;
- live map sync: [20 - planner_autonomy_consolidation_2026-05-01.md](./20%20-%20planner_autonomy_consolidation_2026-05-01.md)
Current honest status:
@ -92,7 +93,7 @@ Current honest status:
- open-world bounded-autonomy readiness: `~85%`
- Post-F semantic integrity module progress: `~99%` operationally closed, with remaining risk now treated as next-slice discovery rather than an open blocker inside the closed slice
- active inventory-stock breadth slice progress: `100%` for the declared scenario pack, not for arbitrary inventory questions
- Planner Autonomy Consolidation progress: `~82%` for the declared module, with catalog-fabric, value-flow arbitration, lifecycle bounded inference, broad-evaluation bridge, inventory catalog templates, inventory runtime-boundary honesty, exact inventory recipe bridging, unambiguous metadata-surface lane inference, catalog chain-template scoring, structured chain-match contract exposure, and runtime/debug propagation validated locally, but live replay for the new bridge is currently blocked by missing active 1C polling and broader unfamiliar 1C asks still need replay-backed growth
- Planner Autonomy Consolidation progress: `~83%` for the declared module, with catalog-fabric, value-flow arbitration, lifecycle bounded inference, broad-evaluation bridge, inventory catalog templates, inventory runtime-boundary honesty, exact inventory recipe bridging, unambiguous metadata-surface lane inference, catalog chain-template scoring, structured chain-match contract exposure, runtime/debug propagation, and subject-aware bidirectional comparison arbitration validated locally, but live replay for the new bridge is currently blocked by missing active 1C polling and broader unfamiliar 1C asks still need replay-backed growth
- graph snapshot after latest rebuild: `5940 nodes`, `12909 edges`, `137 communities`
- current breakpoint:
- the validated hot paths are no longer structurally broken;
@ -141,6 +142,7 @@ Latest live proof now includes:
- catalog chain-template scoring accepted locally: catalog/planner slice passed `54/54`; full MCP-discovery slice passed `282/282` with `9` skipped; build passed; graphify rebuilt to `5938 nodes`, `12903 edges`, `139 communities`
- structured chain-template planner contract accepted locally: planner slice passed `36/36`; full MCP-discovery slice passed `282/282` with `9` skipped; build passed; graphify rebuilt to `5939 nodes`, `12906 edges`, `138 communities`
- structured chain-template runtime/debug propagation accepted locally: runtime/debug slice passed `18/18`; full MCP-discovery slice passed `282/282` with `9` skipped; build passed; graphify rebuilt to `5940 nodes`, `12909 edges`, `137 communities`
- subject-aware bidirectional comparison arbitration accepted locally: planner slice passed `36/36`; full MCP-discovery slice passed `282/282` with `9` skipped; build passed; graphify rebuilt to `5940 nodes`, `12909 edges`, `137 communities`
Current architectural reading:

View File

@ -496,16 +496,19 @@ function recipeFor(input) {
});
}
if (graphFactFamily === "value_flow") {
if (dataNeedGraph?.comparison_need === "incoming_vs_outgoing" && !hasSubjectCandidates(dataNeedGraph)) {
if (dataNeedGraph?.comparison_need === "incoming_vs_outgoing") {
pushUnique(axes, "amount");
pushUnique(axes, "coverage_target");
if (requestedAggregationAxis === "month" || graphAggregation === "by_month") {
pushUnique(axes, "calendar_month");
}
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("value_flow_comparison");
const fallbackPrimitives = hasSubjectCandidates(dataNeedGraph)
? ["resolve_entity_reference", ...template.fallback_primitives]
: template.fallback_primitives;
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
fallbackPrimitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action,

View File

@ -703,16 +703,19 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
}
if (graphFactFamily === "value_flow") {
if (dataNeedGraph?.comparison_need === "incoming_vs_outgoing" && !hasSubjectCandidates(dataNeedGraph)) {
if (dataNeedGraph?.comparison_need === "incoming_vs_outgoing") {
pushUnique(axes, "amount");
pushUnique(axes, "coverage_target");
if (requestedAggregationAxis === "month" || graphAggregation === "by_month") {
pushUnique(axes, "calendar_month");
}
const template = getAssistantMcpCatalogChainTemplate("value_flow_comparison");
const fallbackPrimitives = hasSubjectCandidates(dataNeedGraph)
? (["resolve_entity_reference", ...template.fallback_primitives] as AssistantMcpDiscoveryPrimitive[])
: template.fallback_primitives;
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
fallbackPrimitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action,

View File

@ -520,7 +520,7 @@ describe("assistant MCP discovery planner", () => {
expect(result.reason_codes).not.toContain("planner_selected_movement_from_confirmed_metadata_surface_ref");
});
it("can select value-flow chain from data need graph even when turn meaning family is still under-specified", () => {
it("can select bidirectional value-flow comparison from data need graph even when turn meaning family is still under-specified", () => {
const result = planAssistantMcpDiscovery({
dataNeedGraph: {
schema_version: "assistant_data_need_graph_v1",
@ -552,23 +552,18 @@ describe("assistant MCP discovery planner", () => {
});
expect(result.planner_status).toBe("ready_for_execution");
expect(result.selected_chain_id).toBe("value_flow");
expect(result.proposed_primitives).toEqual([
"resolve_entity_reference",
"query_movements",
"aggregate_by_axis",
"probe_coverage"
]);
expect(result.selected_chain_id).toBe("value_flow_comparison");
expect(result.proposed_primitives).toEqual(["resolve_entity_reference", "query_movements", "probe_coverage"]);
expect(result.required_axes).toEqual([
"counterparty",
"period",
"aggregate_axis",
"amount",
"coverage_target",
"calendar_month"
]);
expect(result.reason_codes).toContain("planner_selected_monthly_value_flow_from_data_need_graph");
expect(result.reason_codes).toContain("planner_instantiated_catalog_chain_template_value_flow");
expect(result.reason_codes).toContain("planner_selected_bidirectional_value_flow_comparison_from_data_need_graph");
expect(result.reason_codes).toContain("planner_instantiated_catalog_chain_template_value_flow_comparison");
expect(result.catalog_chain_template_matches[0]).toBe("value_flow_comparison");
});
it("does not collapse a ranking-shaped value graph into entity-resolution just because no subject is preselected", () => {