Planner Autonomy: выводить lane из metadata surface
This commit is contained in:
parent
a4db26a76e
commit
ccfa9283e9
|
|
@ -29,3 +29,4 @@ graphify-out/
|
|||
# domain-case loop artifacts
|
||||
artifacts/domain_runs/*
|
||||
!artifacts/domain_runs/.gitkeep
|
||||
artifacts/runtime_logs/*.log
|
||||
|
|
|
|||
|
|
@ -102,6 +102,14 @@ The runtime answer boundary still makes unsupported or unconfirmed inventory sta
|
|||
- `must_not_claim` forbids presenting inventory planning as executed stock, supplier, purchase, or sale evidence;
|
||||
- technical unsupported-pilot limitation text is filtered out of user-facing lines, while existing bounded unknowns for lifecycle/value-flow remain intact.
|
||||
|
||||
The next local scoring step broadened metadata-surface autonomy without adding a new hard domain route:
|
||||
|
||||
- if a confirmed metadata surface is unambiguous and only exposes `Document.*`, `Register.*`, or `Catalog.*` objects, the planner can infer the next reviewed lane even when upstream has not yet filled `downstream_route_family`;
|
||||
- inferred document surfaces instantiate `document_evidence`;
|
||||
- inferred register/movement surfaces instantiate `movement_evidence`;
|
||||
- inferred catalog surfaces instantiate `catalog_drilldown`;
|
||||
- mixed or ambiguous surfaces still do not guess and continue through clarification / explicit data-need scoring.
|
||||
|
||||
## Why This Matters
|
||||
|
||||
This reduces the pressure to add one hard route per user wording.
|
||||
|
|
@ -166,16 +174,26 @@ Latest validation after the inventory exact-runtime bridge:
|
|||
- `npm.cmd run build`: passed
|
||||
- graphify rebuild: `5930 nodes`, `12884 edges`, `135 communities`
|
||||
|
||||
Latest validation after unambiguous metadata-surface lane inference:
|
||||
|
||||
- targeted planner tests: passed, `36 passed`
|
||||
- full MCP-discovery suite: passed, `281 passed`, `9 skipped`
|
||||
- `npm.cmd run build`: passed
|
||||
- graphify rebuild: `5937 nodes`, `12899 edges`, `138 communities`
|
||||
- live inventory full-pack attempt: `inventory_stock_exact_bridge_live_20260501_after_runtime_bridge`, status `partial`
|
||||
- live attempt interpretation: route/intent/recipe/capability selection matched, but MCP execution failed with `MCP fetch failed: This operation was aborted`; direct proxy `get_metadata` also timed out while `/health` reported `active_sessions_count=0` and pending commands, so this is an infrastructure/polling-session blocker rather than accepted semantic evidence.
|
||||
|
||||
## Next Step
|
||||
|
||||
The next safe step is to validate the inventory exact-runtime bridge with live replay and then continue into broader reviewed scoring.
|
||||
The next safe step is to re-run live replay once the 1C side is actively polling the proxy, then continue into broader reviewed scoring.
|
||||
|
||||
Recommended order:
|
||||
|
||||
1. rerun the inventory canary and a mixed cross-stage canary against live 1C/MCP once the proxy is available;
|
||||
2. broaden catalog scoring beyond explicit document/movement lane choice into unfamiliar 1C asks;
|
||||
3. grow primitive descriptors only where live replay shows a real evidence gap;
|
||||
4. keep phase19, phase21, phase22, value-flow, metadata ambiguity, and inventory-stock canaries as regression gates.
|
||||
1. reconnect or restart the 1C toolkit polling side, then rerun the inventory canary against live 1C/MCP;
|
||||
2. rerun a mixed cross-stage canary after the inventory canary is semantically clean;
|
||||
3. continue broadening catalog scoring into unfamiliar 1C asks where metadata surface and data-need graph can pick reviewed lanes;
|
||||
4. grow primitive descriptors only where live replay shows a real evidence gap;
|
||||
5. keep phase19, phase21, phase22, value-flow, metadata ambiguity, and inventory-stock canaries as regression gates.
|
||||
|
||||
The key rule remains:
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ It now documents a turnaround that is already operational in code, already mater
|
|||
- inventory stock snapshot, supplier overlap, purchase provenance, and sale trace are now reviewed catalog chain templates; generic free-form inventory execution remains forbidden, and evidence must pass through reviewed exact recipe bridges;
|
||||
- runtime bridge and answer adapter now keep unsupported inventory route templates behind an explicit user-facing boundary instead of letting template planning look like confirmed stock/supplier/purchase/sale evidence;
|
||||
- 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;
|
||||
- live map sync: [20 - planner_autonomy_consolidation_2026-05-01.md](./20%20-%20planner_autonomy_consolidation_2026-05-01.md)
|
||||
|
||||
Current honest status:
|
||||
|
|
@ -90,8 +91,8 @@ 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: `~74%` for the declared module, with catalog-fabric, value-flow arbitration, lifecycle bounded inference, broad-evaluation bridge, inventory catalog templates, inventory runtime-boundary honesty, and exact inventory recipe bridging validated locally, but live replay for the new bridge and broader unfamiliar 1C asks still pending
|
||||
- graph snapshot after latest rebuild: `5930 nodes`, `12884 edges`, `135 communities`
|
||||
- Planner Autonomy Consolidation progress: `~78%` 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, and unambiguous metadata-surface lane inference 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: `5937 nodes`, `12899 edges`, `138 communities`
|
||||
- current breakpoint:
|
||||
- the validated hot paths are no longer structurally broken;
|
||||
- flagship continuity collapse is no longer the primary risk;
|
||||
|
|
@ -134,6 +135,8 @@ Latest live proof now includes:
|
|||
- inventory template lift accepted locally: catalog/data-need/planner/turn-input slice passed `139/139` with `6` skipped; full MCP-discovery slice passed `276/276` with `9` skipped; build passed; graphify stayed at `5912 nodes`, `12833 edges`, `138 communities`
|
||||
- inventory runtime-boundary hardening accepted locally: runtime-bridge/answer-adapter/pilot-executor slice passed `68/68` with `1` skipped; full MCP-discovery slice passed `277/277` with `9` skipped; build passed; graphify rebuilt to `5913 nodes`, `12837 edges`, `138 communities`
|
||||
- inventory exact-runtime bridge accepted locally: runtime-bridge/answer-adapter/pilot-executor slice passed `70/70` with `1` skipped; full MCP-discovery slice passed `279/279` with `9` skipped; build passed; graphify rebuilt to `5930 nodes`, `12884 edges`, `135 communities`
|
||||
- unambiguous metadata-surface lane inference accepted locally: planner slice passed `36/36`; full MCP-discovery slice passed `281/281` with `9` skipped; build passed; graphify rebuilt to `5937 nodes`, `12899 edges`, `138 communities`
|
||||
- live inventory exact-bridge rerun `inventory_stock_exact_bridge_live_20260501_after_runtime_bridge` is recorded as infrastructure-blocked, not accepted: route/intent/recipe/capability matched, but MCP calls aborted and direct `get_metadata` timed out while proxy health showed `active_sessions_count=0` with pending commands
|
||||
|
||||
Current architectural reading:
|
||||
|
||||
|
|
|
|||
|
|
@ -123,6 +123,59 @@ function mergeCatalogPrimitivesWithFallback(catalogPrimitives, fallbackPrimitive
|
|||
}
|
||||
return result;
|
||||
}
|
||||
function normalizeMetadataSurfaceToken(value) {
|
||||
return String(value ?? "").trim().toLowerCase().replace(/[\s_.-]+/g, "");
|
||||
}
|
||||
function metadataSurfaceValueSuggestsDocument(value) {
|
||||
const token = normalizeMetadataSurfaceToken(value);
|
||||
return token.includes("document") || token.includes("invoice") || token.includes("waybill") || token.includes("act");
|
||||
}
|
||||
function metadataSurfaceValueSuggestsMovement(value) {
|
||||
const token = normalizeMetadataSurfaceToken(value);
|
||||
return token.includes("register") || token.includes("movement") || token.includes("operation") || token.includes("bank");
|
||||
}
|
||||
function metadataSurfaceValueSuggestsCatalog(value) {
|
||||
const token = normalizeMetadataSurfaceToken(value);
|
||||
return token.includes("catalog") || token.includes("directory");
|
||||
}
|
||||
function routeFamilyFromMetadataSurfaceRef(surface) {
|
||||
if (!surface || surface.ambiguity_detected) {
|
||||
return null;
|
||||
}
|
||||
if (surface.downstream_route_family) {
|
||||
return surface.downstream_route_family;
|
||||
}
|
||||
const values = [surface.selected_entity_set ?? "", ...surface.selected_surface_objects];
|
||||
const documentHit = values.some(metadataSurfaceValueSuggestsDocument);
|
||||
const movementHit = values.some(metadataSurfaceValueSuggestsMovement);
|
||||
const catalogHit = values.some(metadataSurfaceValueSuggestsCatalog);
|
||||
const hitCount = [documentHit, movementHit, catalogHit].filter(Boolean).length;
|
||||
if (hitCount !== 1) {
|
||||
return null;
|
||||
}
|
||||
if (documentHit) {
|
||||
return "document_evidence";
|
||||
}
|
||||
if (movementHit) {
|
||||
return "movement_evidence";
|
||||
}
|
||||
return "catalog_drilldown";
|
||||
}
|
||||
function inferredRouteFamilyFromMetadataSurfaceRef(surface) {
|
||||
return Boolean(surface && !surface.downstream_route_family && routeFamilyFromMetadataSurfaceRef(surface));
|
||||
}
|
||||
function preferredPrimitiveForRouteFamily(routeFamily) {
|
||||
if (routeFamily === "document_evidence") {
|
||||
return "query_documents";
|
||||
}
|
||||
if (routeFamily === "movement_evidence") {
|
||||
return "query_movements";
|
||||
}
|
||||
if (routeFamily === "catalog_drilldown") {
|
||||
return "drilldown_related_objects";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function preferredPrimitiveFromMetadataSurface(surface) {
|
||||
if (surface?.ambiguity_detected) {
|
||||
return null;
|
||||
|
|
@ -131,16 +184,7 @@ function preferredPrimitiveFromMetadataSurface(surface) {
|
|||
if (recommendedPrimitive) {
|
||||
return recommendedPrimitive;
|
||||
}
|
||||
if (surface?.downstream_route_family === "document_evidence") {
|
||||
return "query_documents";
|
||||
}
|
||||
if (surface?.downstream_route_family === "movement_evidence") {
|
||||
return "query_movements";
|
||||
}
|
||||
if (surface?.downstream_route_family === "catalog_drilldown") {
|
||||
return "drilldown_related_objects";
|
||||
}
|
||||
return null;
|
||||
return preferredPrimitiveForRouteFamily(routeFamilyFromMetadataSurfaceRef(surface));
|
||||
}
|
||||
function preferredPrimitiveFromExplicitDataNeedGraph(graph) {
|
||||
const factFamily = lower(graph?.business_fact_family);
|
||||
|
|
@ -289,7 +333,8 @@ function budgetOverrideFor(input, recipe) {
|
|||
}
|
||||
function routeFamilyFromThinMetadataSurfaceInput(input) {
|
||||
const surface = input.metadataSurface ?? null;
|
||||
if (!surface || surface.ambiguity_detected || !surface.downstream_route_family || !surface.recommended_next_primitive) {
|
||||
const surfaceRouteFamily = routeFamilyFromMetadataSurfaceRef(surface);
|
||||
if (!surface || surface.ambiguity_detected || !surfaceRouteFamily) {
|
||||
return null;
|
||||
}
|
||||
const meaning = input.turnMeaning ?? null;
|
||||
|
|
@ -305,20 +350,16 @@ function routeFamilyFromThinMetadataSurfaceInput(input) {
|
|||
return null;
|
||||
}
|
||||
if (graphFactFamily === "document_evidence" || includesAny(combined, ["document", "documents", "list_documents"])) {
|
||||
return surface.downstream_route_family === "document_evidence" ? "document_evidence" : null;
|
||||
return surfaceRouteFamily === "document_evidence" ? "document_evidence" : null;
|
||||
}
|
||||
if (graphFactFamily === "movement_evidence" || includesAny(combined, ["movement", "movements", "list_movements", "bank_operations"])) {
|
||||
return surface.downstream_route_family === "movement_evidence" ? "movement_evidence" : null;
|
||||
return surfaceRouteFamily === "movement_evidence" ? "movement_evidence" : null;
|
||||
}
|
||||
if (graphFactFamily === "schema_surface" || includesAny(combined, ["catalog", "directory", "inspect_catalog"])) {
|
||||
return surface.downstream_route_family === "catalog_drilldown" ? "catalog_drilldown" : null;
|
||||
return surfaceRouteFamily === "catalog_drilldown" ? "catalog_drilldown" : null;
|
||||
}
|
||||
if (!graphFactFamily && !domain && !action) {
|
||||
if (surface.downstream_route_family === "document_evidence" ||
|
||||
surface.downstream_route_family === "movement_evidence" ||
|
||||
surface.downstream_route_family === "catalog_drilldown") {
|
||||
return surface.downstream_route_family;
|
||||
}
|
||||
return surfaceRouteFamily;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -370,7 +411,12 @@ function recipeFor(input) {
|
|||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_document_from_confirmed_metadata_surface_ref",
|
||||
chainSummary: "Ground the next checked document lane from the confirmed metadata surface, then fetch scoped document rows and probe coverage before answering.",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
extraReasons: [
|
||||
...primitiveSelection.reasonCodes,
|
||||
...(inferredRouteFamilyFromMetadataSurfaceRef(input.metadataSurface)
|
||||
? ["planner_inferred_next_lane_from_unambiguous_metadata_surface"]
|
||||
: [])
|
||||
]
|
||||
});
|
||||
}
|
||||
if (thinSurfaceRouteFamily === "movement_evidence") {
|
||||
|
|
@ -389,7 +435,12 @@ function recipeFor(input) {
|
|||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_movement_from_confirmed_metadata_surface_ref",
|
||||
chainSummary: "Ground the next checked movement lane from the confirmed metadata surface, then fetch scoped movement rows and probe coverage before answering.",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
extraReasons: [
|
||||
...primitiveSelection.reasonCodes,
|
||||
...(inferredRouteFamilyFromMetadataSurfaceRef(input.metadataSurface)
|
||||
? ["planner_inferred_next_lane_from_unambiguous_metadata_surface"]
|
||||
: [])
|
||||
]
|
||||
});
|
||||
}
|
||||
if (thinSurfaceRouteFamily === "catalog_drilldown") {
|
||||
|
|
@ -408,7 +459,12 @@ function recipeFor(input) {
|
|||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_catalog_drilldown_from_confirmed_metadata_surface_ref",
|
||||
chainSummary: "Drill deeper into the confirmed catalog-oriented metadata surface, inspect related metadata objects, and keep the next safe lane grounded in checked schema evidence.",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
extraReasons: [
|
||||
...primitiveSelection.reasonCodes,
|
||||
...(inferredRouteFamilyFromMetadataSurfaceRef(input.metadataSurface)
|
||||
? ["planner_inferred_next_lane_from_unambiguous_metadata_surface"]
|
||||
: [])
|
||||
]
|
||||
});
|
||||
}
|
||||
if (graphFactFamily === "value_flow") {
|
||||
|
|
|
|||
|
|
@ -249,6 +249,73 @@ function mergeCatalogPrimitivesWithFallback(
|
|||
return result;
|
||||
}
|
||||
|
||||
function normalizeMetadataSurfaceToken(value: unknown): string {
|
||||
return String(value ?? "").trim().toLowerCase().replace(/[\s_.-]+/g, "");
|
||||
}
|
||||
|
||||
function metadataSurfaceValueSuggestsDocument(value: unknown): boolean {
|
||||
const token = normalizeMetadataSurfaceToken(value);
|
||||
return token.includes("document") || token.includes("invoice") || token.includes("waybill") || token.includes("act");
|
||||
}
|
||||
|
||||
function metadataSurfaceValueSuggestsMovement(value: unknown): boolean {
|
||||
const token = normalizeMetadataSurfaceToken(value);
|
||||
return token.includes("register") || token.includes("movement") || token.includes("operation") || token.includes("bank");
|
||||
}
|
||||
|
||||
function metadataSurfaceValueSuggestsCatalog(value: unknown): boolean {
|
||||
const token = normalizeMetadataSurfaceToken(value);
|
||||
return token.includes("catalog") || token.includes("directory");
|
||||
}
|
||||
|
||||
function routeFamilyFromMetadataSurfaceRef(
|
||||
surface: AssistantMcpDiscoveryMetadataSurfaceRef | null | undefined
|
||||
): AssistantMcpDiscoveryMetadataRouteFamily | null {
|
||||
if (!surface || surface.ambiguity_detected) {
|
||||
return null;
|
||||
}
|
||||
if (surface.downstream_route_family) {
|
||||
return surface.downstream_route_family;
|
||||
}
|
||||
|
||||
const values = [surface.selected_entity_set ?? "", ...surface.selected_surface_objects];
|
||||
const documentHit = values.some(metadataSurfaceValueSuggestsDocument);
|
||||
const movementHit = values.some(metadataSurfaceValueSuggestsMovement);
|
||||
const catalogHit = values.some(metadataSurfaceValueSuggestsCatalog);
|
||||
const hitCount = [documentHit, movementHit, catalogHit].filter(Boolean).length;
|
||||
if (hitCount !== 1) {
|
||||
return null;
|
||||
}
|
||||
if (documentHit) {
|
||||
return "document_evidence";
|
||||
}
|
||||
if (movementHit) {
|
||||
return "movement_evidence";
|
||||
}
|
||||
return "catalog_drilldown";
|
||||
}
|
||||
|
||||
function inferredRouteFamilyFromMetadataSurfaceRef(
|
||||
surface: AssistantMcpDiscoveryMetadataSurfaceRef | null | undefined
|
||||
): boolean {
|
||||
return Boolean(surface && !surface.downstream_route_family && routeFamilyFromMetadataSurfaceRef(surface));
|
||||
}
|
||||
|
||||
function preferredPrimitiveForRouteFamily(
|
||||
routeFamily: AssistantMcpDiscoveryMetadataRouteFamily | null
|
||||
): AssistantMcpDiscoveryPrimitive | null {
|
||||
if (routeFamily === "document_evidence") {
|
||||
return "query_documents";
|
||||
}
|
||||
if (routeFamily === "movement_evidence") {
|
||||
return "query_movements";
|
||||
}
|
||||
if (routeFamily === "catalog_drilldown") {
|
||||
return "drilldown_related_objects";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function preferredPrimitiveFromMetadataSurface(
|
||||
surface: AssistantMcpDiscoveryMetadataSurfaceRef | null | undefined
|
||||
): AssistantMcpDiscoveryPrimitive | null {
|
||||
|
|
@ -259,16 +326,7 @@ function preferredPrimitiveFromMetadataSurface(
|
|||
if (recommendedPrimitive) {
|
||||
return recommendedPrimitive;
|
||||
}
|
||||
if (surface?.downstream_route_family === "document_evidence") {
|
||||
return "query_documents";
|
||||
}
|
||||
if (surface?.downstream_route_family === "movement_evidence") {
|
||||
return "query_movements";
|
||||
}
|
||||
if (surface?.downstream_route_family === "catalog_drilldown") {
|
||||
return "drilldown_related_objects";
|
||||
}
|
||||
return null;
|
||||
return preferredPrimitiveForRouteFamily(routeFamilyFromMetadataSurfaceRef(surface));
|
||||
}
|
||||
|
||||
function preferredPrimitiveFromExplicitDataNeedGraph(
|
||||
|
|
@ -466,7 +524,8 @@ function routeFamilyFromThinMetadataSurfaceInput(
|
|||
input: AssistantMcpDiscoveryPlannerInput
|
||||
): AssistantMcpDiscoveryMetadataRouteFamily | null {
|
||||
const surface = input.metadataSurface ?? null;
|
||||
if (!surface || surface.ambiguity_detected || !surface.downstream_route_family || !surface.recommended_next_primitive) {
|
||||
const surfaceRouteFamily = routeFamilyFromMetadataSurfaceRef(surface);
|
||||
if (!surface || surface.ambiguity_detected || !surfaceRouteFamily) {
|
||||
return null;
|
||||
}
|
||||
const meaning = input.turnMeaning ?? null;
|
||||
|
|
@ -483,22 +542,16 @@ function routeFamilyFromThinMetadataSurfaceInput(
|
|||
return null;
|
||||
}
|
||||
if (graphFactFamily === "document_evidence" || includesAny(combined, ["document", "documents", "list_documents"])) {
|
||||
return surface.downstream_route_family === "document_evidence" ? "document_evidence" : null;
|
||||
return surfaceRouteFamily === "document_evidence" ? "document_evidence" : null;
|
||||
}
|
||||
if (graphFactFamily === "movement_evidence" || includesAny(combined, ["movement", "movements", "list_movements", "bank_operations"])) {
|
||||
return surface.downstream_route_family === "movement_evidence" ? "movement_evidence" : null;
|
||||
return surfaceRouteFamily === "movement_evidence" ? "movement_evidence" : null;
|
||||
}
|
||||
if (graphFactFamily === "schema_surface" || includesAny(combined, ["catalog", "directory", "inspect_catalog"])) {
|
||||
return surface.downstream_route_family === "catalog_drilldown" ? "catalog_drilldown" : null;
|
||||
return surfaceRouteFamily === "catalog_drilldown" ? "catalog_drilldown" : null;
|
||||
}
|
||||
if (!graphFactFamily && !domain && !action) {
|
||||
if (
|
||||
surface.downstream_route_family === "document_evidence" ||
|
||||
surface.downstream_route_family === "movement_evidence" ||
|
||||
surface.downstream_route_family === "catalog_drilldown"
|
||||
) {
|
||||
return surface.downstream_route_family;
|
||||
}
|
||||
return surfaceRouteFamily;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -555,7 +608,12 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
|
|||
reason: "planner_selected_document_from_confirmed_metadata_surface_ref",
|
||||
chainSummary:
|
||||
"Ground the next checked document lane from the confirmed metadata surface, then fetch scoped document rows and probe coverage before answering.",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
extraReasons: [
|
||||
...primitiveSelection.reasonCodes,
|
||||
...(inferredRouteFamilyFromMetadataSurfaceRef(input.metadataSurface)
|
||||
? ["planner_inferred_next_lane_from_unambiguous_metadata_surface"]
|
||||
: [])
|
||||
]
|
||||
});
|
||||
}
|
||||
if (thinSurfaceRouteFamily === "movement_evidence") {
|
||||
|
|
@ -575,7 +633,12 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
|
|||
reason: "planner_selected_movement_from_confirmed_metadata_surface_ref",
|
||||
chainSummary:
|
||||
"Ground the next checked movement lane from the confirmed metadata surface, then fetch scoped movement rows and probe coverage before answering.",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
extraReasons: [
|
||||
...primitiveSelection.reasonCodes,
|
||||
...(inferredRouteFamilyFromMetadataSurfaceRef(input.metadataSurface)
|
||||
? ["planner_inferred_next_lane_from_unambiguous_metadata_surface"]
|
||||
: [])
|
||||
]
|
||||
});
|
||||
}
|
||||
if (thinSurfaceRouteFamily === "catalog_drilldown") {
|
||||
|
|
@ -595,7 +658,12 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
|
|||
reason: "planner_selected_catalog_drilldown_from_confirmed_metadata_surface_ref",
|
||||
chainSummary:
|
||||
"Drill deeper into the confirmed catalog-oriented metadata surface, inspect related metadata objects, and keep the next safe lane grounded in checked schema evidence.",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
extraReasons: [
|
||||
...primitiveSelection.reasonCodes,
|
||||
...(inferredRouteFamilyFromMetadataSurfaceRef(input.metadataSurface)
|
||||
? ["planner_inferred_next_lane_from_unambiguous_metadata_surface"]
|
||||
: [])
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -218,6 +218,31 @@ describe("assistant MCP discovery planner", () => {
|
|||
expect(result.reason_codes).toContain("planner_selected_catalog_primitives_from_metadata_surface_search");
|
||||
});
|
||||
|
||||
it("infers document evidence from an unambiguous document metadata surface even before a downstream lane is labeled", () => {
|
||||
const result = planAssistantMcpDiscovery({
|
||||
metadataSurface: {
|
||||
selected_entity_set: "Document",
|
||||
selected_surface_objects: ["Document.InvoiceIssued"],
|
||||
downstream_route_family: null,
|
||||
route_family_selection_basis: null,
|
||||
recommended_next_primitive: null,
|
||||
ambiguity_detected: false,
|
||||
ambiguity_entity_sets: []
|
||||
},
|
||||
turnMeaning: {
|
||||
explicit_entity_candidates: ["SVK"],
|
||||
explicit_date_scope: "2020"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.planner_status).toBe("ready_for_execution");
|
||||
expect(result.selected_chain_id).toBe("document_evidence");
|
||||
expect(result.proposed_primitives).toEqual(["resolve_entity_reference", "query_documents", "probe_coverage"]);
|
||||
expect(result.proposed_primitives).not.toContain("query_movements");
|
||||
expect(result.reason_codes).toContain("planner_inferred_next_lane_from_unambiguous_metadata_surface");
|
||||
expect(result.reason_codes).toContain("planner_surface_aware_next_lane_from_confirmed_metadata_objects");
|
||||
});
|
||||
|
||||
it("builds a movement discovery plan without aggregating value-flow totals", () => {
|
||||
const result = planAssistantMcpDiscovery({
|
||||
dataNeedGraph: {
|
||||
|
|
@ -325,6 +350,31 @@ describe("assistant MCP discovery planner", () => {
|
|||
expect(result.reason_codes).toContain("planner_selected_catalog_primitives_from_metadata_surface_search");
|
||||
});
|
||||
|
||||
it("infers movement evidence from an unambiguous register metadata surface even before a downstream lane is labeled", () => {
|
||||
const result = planAssistantMcpDiscovery({
|
||||
metadataSurface: {
|
||||
selected_entity_set: "AccumulationRegister",
|
||||
selected_surface_objects: ["AccumulationRegister.BankOperations"],
|
||||
downstream_route_family: null,
|
||||
route_family_selection_basis: null,
|
||||
recommended_next_primitive: null,
|
||||
ambiguity_detected: false,
|
||||
ambiguity_entity_sets: []
|
||||
},
|
||||
turnMeaning: {
|
||||
explicit_entity_candidates: ["SVK"],
|
||||
explicit_date_scope: "2020"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.planner_status).toBe("ready_for_execution");
|
||||
expect(result.selected_chain_id).toBe("movement_evidence");
|
||||
expect(result.proposed_primitives).toEqual(["resolve_entity_reference", "query_movements", "probe_coverage"]);
|
||||
expect(result.proposed_primitives).not.toContain("query_documents");
|
||||
expect(result.reason_codes).toContain("planner_inferred_next_lane_from_unambiguous_metadata_surface");
|
||||
expect(result.reason_codes).toContain("planner_surface_aware_next_lane_from_confirmed_metadata_objects");
|
||||
});
|
||||
|
||||
it("can select catalog drilldown directly from a confirmed catalog metadata surface when the follow-up itself is thin", () => {
|
||||
const result = planAssistantMcpDiscovery({
|
||||
metadataSurface: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue