АРЧ АП11 - Архитектура после регресса: Архитектура: обновить статус pre-multidomain readiness и протянуть continuity snapshot в transition hot path
This commit is contained in:
parent
f58ef9ad55
commit
578f6643e6
|
|
@ -140,6 +140,7 @@ Completed in the current working pass:
|
||||||
- exact address intents can now stay in the address lane even if the semantic guard overflags deep investigation without an actual investigative user request;
|
- exact address intents can now stay in the address lane even if the semantic guard overflags deep investigation without an actual investigative user request;
|
||||||
- selected-object inventory follow-ups can now override a stale stock root intent when the semantic contract already marks `selected_object_scope_detected`, including exact user wording like `по выбранному объекту ... где взяли это`;
|
- selected-object inventory follow-ups can now override a stale stock root intent when the semantic contract already marks `selected_object_scope_detected`, including exact user wording like `по выбранному объекту ... где взяли это`;
|
||||||
- explicit capability-meta wording for `дельта по договорам` now keeps the asked capability in the user-facing answer instead of collapsing into the generic `что ты умеешь` catalog reply.
|
- explicit capability-meta wording for `дельта по договорам` now keeps the asked capability in the user-facing answer instead of collapsing into the generic `что ты умеешь` catalog reply.
|
||||||
|
- the transition hot path now starts consuming the shared continuity snapshot as fallback authority for active item / active organization / grounded inventory root frame instead of rebuilding those values only from local ad hoc history scans;
|
||||||
- live replay `address_truth_harness_phase7_meta_domain_mix_live_20260417_post_arch_fix_rerun2` is accepted end-to-end with `14/14` steps green, including the previously broken `step_01_counterparty_documents` and `step_04_open_items_account_60`.
|
- live replay `address_truth_harness_phase7_meta_domain_mix_live_20260417_post_arch_fix_rerun2` is accepted end-to-end with `14/14` steps green, including the previously broken `step_01_counterparty_documents` and `step_04_open_items_account_60`.
|
||||||
|
|
||||||
Still open after this pass:
|
Still open after this pass:
|
||||||
|
|
@ -233,6 +234,30 @@ Still open after the accepted phase11 replay:
|
||||||
- answer shaping on some long exact list answers is still heavier than the target human product feel, even though the truth path and routing are now correct;
|
- answer shaping on some long exact list answers is still heavier than the target human product feel, even though the truth path and routing are now correct;
|
||||||
- the next architecture slice should move to wider saved-session acceptance coverage and humanized exact-answer presentation, not back to isolated prompt-level repairs.
|
- the next architecture slice should move to wider saved-session acceptance coverage and humanized exact-answer presentation, not back to isolated prompt-level repairs.
|
||||||
|
|
||||||
|
## Next Execution Slice (2026-04-18)
|
||||||
|
|
||||||
|
The project is now moving from:
|
||||||
|
|
||||||
|
- `breakpoint recovery`
|
||||||
|
|
||||||
|
to:
|
||||||
|
|
||||||
|
- `danger-zone exit under explicit gates`
|
||||||
|
|
||||||
|
This next slice should be executed in the following order:
|
||||||
|
|
||||||
|
1. Finish continuity authority convergence in the hot runtime path.
|
||||||
|
2. Widen saved-session replay coverage beyond the already repaired flagship chains.
|
||||||
|
3. Tighten human answer shaping on long exact answers without reintroducing template drift.
|
||||||
|
4. Only after that, begin controlled domain-by-domain expansion toward the multi-domain stage.
|
||||||
|
|
||||||
|
Current explicit goals for this slice:
|
||||||
|
|
||||||
|
- fewer owners independently reconstruct `active context`;
|
||||||
|
- more replay breadth before any large expansion claim;
|
||||||
|
- cleaner user-facing business answers on already-correct truth paths;
|
||||||
|
- lower risk that new domains multiply orchestration chaos faster than capability growth.
|
||||||
|
|
||||||
## Ready Signal
|
## Ready Signal
|
||||||
|
|
||||||
The project can leave the current breakpoint when:
|
The project can leave the current breakpoint when:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
# 13 - Pre-Multidomain Readiness Audit (2026-04-18)
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
This note answers one question directly:
|
||||||
|
|
||||||
|
- are we already ready to expand into many new domains in parallel?
|
||||||
|
|
||||||
|
The answer must stay architecture-first and brutally honest.
|
||||||
|
|
||||||
|
## Executive Verdict
|
||||||
|
|
||||||
|
Short version:
|
||||||
|
|
||||||
|
- the project is no longer in the acute collapse state;
|
||||||
|
- the turnaround is real and already operational;
|
||||||
|
- but the system is still not ready for low-risk broad multi-domain expansion.
|
||||||
|
|
||||||
|
Current verdict:
|
||||||
|
|
||||||
|
- safe for continued hardening and controlled domain-by-domain expansion under replay gates;
|
||||||
|
- not yet safe for wide parallel multi-agent domain expansion.
|
||||||
|
|
||||||
|
## What Is Already True
|
||||||
|
|
||||||
|
The following claims are now supported by code plus live replay evidence:
|
||||||
|
|
||||||
|
- phase7-phase11 mixed/manual replays are accepted on the repaired hot paths;
|
||||||
|
- continuity on validated inventory / VAT / counterparty / company-authority chains is materially stronger than before;
|
||||||
|
- user-facing meta answers are significantly cleaner and no longer dominated by technical garbage;
|
||||||
|
- the assistant no longer depends on the old ambient monolith behavior on the validated seams;
|
||||||
|
- the team now has a working replay-driven hardening loop instead of blind local patching.
|
||||||
|
|
||||||
|
In practical terms:
|
||||||
|
|
||||||
|
- we are moving out of danger;
|
||||||
|
- we are not yet on stable pre-expansion ground.
|
||||||
|
|
||||||
|
## What Is Still Not Good Enough
|
||||||
|
|
||||||
|
### 1. Continuity authority is improved, but still not singular
|
||||||
|
|
||||||
|
The same active-context signal is still reconstructed in multiple places:
|
||||||
|
|
||||||
|
- normalizer semantic hints;
|
||||||
|
- semantic overlay;
|
||||||
|
- transition policy;
|
||||||
|
- query/runtime guards;
|
||||||
|
- capability binding / answer-time anchor checks.
|
||||||
|
|
||||||
|
This is much better than the old implicit monolith, but it still means:
|
||||||
|
|
||||||
|
- the system relies on multiple synchronized interpretations of context instead of one final runtime authority object.
|
||||||
|
|
||||||
|
### 2. Core orchestration remains too concentrated
|
||||||
|
|
||||||
|
The main pressure centers are still heavy:
|
||||||
|
|
||||||
|
- `assistantService.ts`
|
||||||
|
- `addressQueryService.ts`
|
||||||
|
- `answerComposer.ts`
|
||||||
|
- `decomposeStage.ts`
|
||||||
|
- `assistantTransitionPolicy.ts`
|
||||||
|
|
||||||
|
This does not mean the extraction failed.
|
||||||
|
|
||||||
|
It means the extraction is incomplete for the next scale step.
|
||||||
|
|
||||||
|
### 3. Some fixes are still seam-specific rather than declarative
|
||||||
|
|
||||||
|
Several repaired paths are now correct because explicit rules were added for real regressions.
|
||||||
|
|
||||||
|
That is the right move during stabilization.
|
||||||
|
|
||||||
|
But it also means:
|
||||||
|
|
||||||
|
- the system still contains special-case authority at service/policy level that should later move into more declarative runtime contracts or registries.
|
||||||
|
|
||||||
|
### 4. Acceptance breadth is still below the future blast radius
|
||||||
|
|
||||||
|
Current replay evidence is strong on validated hot paths.
|
||||||
|
|
||||||
|
It is not yet broad enough for the intended next stage:
|
||||||
|
|
||||||
|
- many new domains;
|
||||||
|
- many new follow-up trees;
|
||||||
|
- multiple agents hardening in parallel.
|
||||||
|
|
||||||
|
This is the single biggest reason not to declare the architecture expansion-ready yet.
|
||||||
|
|
||||||
|
## Readiness Assessment
|
||||||
|
|
||||||
|
### Safe right now
|
||||||
|
|
||||||
|
- continue architectural hardening;
|
||||||
|
- continue replay-driven stabilization;
|
||||||
|
- onboard one new domain at a time under strict scenario acceptance;
|
||||||
|
- keep improving continuity authority and answer shaping.
|
||||||
|
|
||||||
|
### Not safe right now
|
||||||
|
|
||||||
|
- broad multi-domain rollout without stronger gates;
|
||||||
|
- parallel domain expansion that assumes the orchestration layer is already platform-grade;
|
||||||
|
- treating phase7-phase11 green status as proof that the general architecture is already robust enough for the next development level.
|
||||||
|
|
||||||
|
## Required Before Next Development Level
|
||||||
|
|
||||||
|
The system should not be considered ready for the next level until all of the following are true:
|
||||||
|
|
||||||
|
1. `assistant_session_continuity_v1` is the real shared authority across route, transition, clarification, recap, and answer-shaping hot paths.
|
||||||
|
2. Saved-session acceptance is widened beyond the current repaired chains into a broader mixed replay pool.
|
||||||
|
3. Capability/meta handling is less service-special-case and more contract-driven.
|
||||||
|
4. `assistantService` pressure is reduced enough that new domains do not have to negotiate multiple partially overlapping owners.
|
||||||
|
5. Long exact answers feel human and business-first, not merely technically correct.
|
||||||
|
|
||||||
|
## Recommended Next Execution Sequence
|
||||||
|
|
||||||
|
### Pass 12. Continuity authority completion
|
||||||
|
|
||||||
|
Goal:
|
||||||
|
|
||||||
|
- reduce the number of places that reconstruct active context independently.
|
||||||
|
|
||||||
|
Target:
|
||||||
|
|
||||||
|
- transition / route / clarification should consume one continuity snapshot before making divergent decisions.
|
||||||
|
|
||||||
|
### Pass 13. Wider saved-session acceptance pool
|
||||||
|
|
||||||
|
Goal:
|
||||||
|
|
||||||
|
- prove stability on multiple real user trajectories, not only the already repaired flagship chains.
|
||||||
|
|
||||||
|
Target:
|
||||||
|
|
||||||
|
- several saved sessions covering inventory, VAT, counterparty, payables/receivables, meta interrupts, and cross-domain pivots.
|
||||||
|
|
||||||
|
### Pass 14. Human answer shaping cleanup
|
||||||
|
|
||||||
|
Goal:
|
||||||
|
|
||||||
|
- remove the remaining mechanical, template-heavy feel from long exact answers.
|
||||||
|
|
||||||
|
Target:
|
||||||
|
|
||||||
|
- product-quality business answers on already-correct truth paths.
|
||||||
|
|
||||||
|
### Pass 15. Coordinator pressure reduction
|
||||||
|
|
||||||
|
Goal:
|
||||||
|
|
||||||
|
- make the architecture safer for future domain onboarding by shrinking control-plane overload.
|
||||||
|
|
||||||
|
Target:
|
||||||
|
|
||||||
|
- less policy/service glue concentrated in `assistantService.ts` and adjacent god-modules.
|
||||||
|
|
||||||
|
## Final Statement
|
||||||
|
|
||||||
|
The current architecture is no longer failing in the same way it failed during the regression breakpoint.
|
||||||
|
|
||||||
|
That is a major win.
|
||||||
|
|
||||||
|
But if we pretend this already equals multi-domain readiness, we will recreate the same class of project risk at a larger scale.
|
||||||
|
|
||||||
|
The correct reading is:
|
||||||
|
|
||||||
|
- collapse averted;
|
||||||
|
- stabilization real;
|
||||||
|
- expansion still gated.
|
||||||
|
|
@ -29,12 +29,14 @@ This package answers the next question:
|
||||||
9. [09 - pre_expansion_cut_2026-04-17.md](./09%20-%20pre_expansion_cut_2026-04-17.md)
|
9. [09 - pre_expansion_cut_2026-04-17.md](./09%20-%20pre_expansion_cut_2026-04-17.md)
|
||||||
10. [10 - regression_breakpoint_analysis_2026-04-17.md](./10%20-%20regression_breakpoint_analysis_2026-04-17.md)
|
10. [10 - regression_breakpoint_analysis_2026-04-17.md](./10%20-%20regression_breakpoint_analysis_2026-04-17.md)
|
||||||
11. [11 - continuity_stabilization_plan_2026-04-17.md](./11%20-%20continuity_stabilization_plan_2026-04-17.md)
|
11. [11 - continuity_stabilization_plan_2026-04-17.md](./11%20-%20continuity_stabilization_plan_2026-04-17.md)
|
||||||
|
12. [12 - manual_run_system_analysis_3NilqwT1G2_2026-04-18.md](./12%20-%20manual_run_system_analysis_3NilqwT1G2_2026-04-18.md)
|
||||||
|
13. [13 - pre_multidomain_readiness_audit_2026-04-18.md](./13%20-%20pre_multidomain_readiness_audit_2026-04-18.md)
|
||||||
|
|
||||||
## Current Status Snapshot (2026-04-17)
|
## Current Status Snapshot (2026-04-18)
|
||||||
|
|
||||||
This package is no longer planning-only.
|
This package is no longer planning-only.
|
||||||
|
|
||||||
It now documents a turnaround that is already operational in code but still inside a pre-expansion stabilization breakpoint:
|
It now documents a turnaround that is already operational in code, already materially past the acute regression breakpoint, but still not ready for wide multi-domain expansion:
|
||||||
|
|
||||||
- route, transition, boundary, meta, memory, and provider policy owners exist as separate modules;
|
- route, transition, boundary, meta, memory, and provider policy owners exist as separate modules;
|
||||||
- exact-lane truth and coverage/evidence contracts exist as explicit runtime artifacts;
|
- exact-lane truth and coverage/evidence contracts exist as explicit runtime artifacts;
|
||||||
|
|
@ -43,18 +45,20 @@ It now documents a turnaround that is already operational in code but still insi
|
||||||
|
|
||||||
Current honest status:
|
Current honest status:
|
||||||
|
|
||||||
- turnaround implementation progress: `~88%`
|
- turnaround implementation progress: `~90%`
|
||||||
- pre-expansion readiness: `~62%`
|
- exit-from-danger-zone readiness: `~78%`
|
||||||
- graph snapshot after latest rebuild: `5312 nodes`, `11408 edges`, `136 communities`
|
- pre-multidomain readiness: `~58%`
|
||||||
|
- graph snapshot after latest rebuild: `5339 nodes`, `11476 edges`, `134 communities`
|
||||||
- current breakpoint:
|
- current breakpoint:
|
||||||
- mixed saved-session runtime still fails on continuity-critical edges;
|
- the validated hot paths are no longer structurally broken;
|
||||||
- clarification can outrank restored business context;
|
- but mixed continuity is still not governed by one fully central runtime authority;
|
||||||
- recap and user-facing packaging can remain smoother than the actual grounded thread.
|
- wider saved-session proof is still too narrow for low-risk multi-domain rollout;
|
||||||
|
- answer shaping is still heavier and more template-driven than the target product feel.
|
||||||
- main remaining architectural pressure:
|
- main remaining architectural pressure:
|
||||||
- no single authoritative continuity contract for live mixed sessions
|
- no single fully authoritative continuity contract consumed by all hot runtime owners
|
||||||
- residual coordinator/legacy pressure inside `assistantService.ts`
|
- residual coordinator/legacy pressure inside `assistantService.ts`
|
||||||
- central domain-intent pressure inside `resolveAddressIntent()`
|
- central domain-intent pressure inside `resolveAddressIntent()`
|
||||||
- remaining answer-semantics pressure inside `composeStage.ts`
|
- remaining answer-semantics pressure inside `composeStage.ts` / `answerComposer.ts`
|
||||||
|
|
||||||
For the detailed audit, current percentages, and remaining debt, read:
|
For the detailed audit, current percentages, and remaining debt, read:
|
||||||
|
|
||||||
|
|
@ -62,6 +66,8 @@ For the detailed audit, current percentages, and remaining debt, read:
|
||||||
- [09 - pre_expansion_cut_2026-04-17.md](./09%20-%20pre_expansion_cut_2026-04-17.md)
|
- [09 - pre_expansion_cut_2026-04-17.md](./09%20-%20pre_expansion_cut_2026-04-17.md)
|
||||||
- [10 - regression_breakpoint_analysis_2026-04-17.md](./10%20-%20regression_breakpoint_analysis_2026-04-17.md)
|
- [10 - regression_breakpoint_analysis_2026-04-17.md](./10%20-%20regression_breakpoint_analysis_2026-04-17.md)
|
||||||
- [11 - continuity_stabilization_plan_2026-04-17.md](./11%20-%20continuity_stabilization_plan_2026-04-17.md)
|
- [11 - continuity_stabilization_plan_2026-04-17.md](./11%20-%20continuity_stabilization_plan_2026-04-17.md)
|
||||||
|
- [12 - manual_run_system_analysis_3NilqwT1G2_2026-04-18.md](./12%20-%20manual_run_system_analysis_3NilqwT1G2_2026-04-18.md)
|
||||||
|
- [13 - pre_multidomain_readiness_audit_2026-04-18.md](./13%20-%20pre_multidomain_readiness_audit_2026-04-18.md)
|
||||||
|
|
||||||
## Architectural Objects Of Planning
|
## Architectural Objects Of Planning
|
||||||
|
|
||||||
|
|
@ -91,6 +97,8 @@ Read in this order:
|
||||||
10. `09 - pre_expansion_cut_2026-04-17.md`
|
10. `09 - pre_expansion_cut_2026-04-17.md`
|
||||||
11. `10 - regression_breakpoint_analysis_2026-04-17.md`
|
11. `10 - regression_breakpoint_analysis_2026-04-17.md`
|
||||||
12. `11 - continuity_stabilization_plan_2026-04-17.md`
|
12. `11 - continuity_stabilization_plan_2026-04-17.md`
|
||||||
|
13. `12 - manual_run_system_analysis_3NilqwT1G2_2026-04-18.md`
|
||||||
|
14. `13 - pre_multidomain_readiness_audit_2026-04-18.md`
|
||||||
|
|
||||||
## Planning Rules
|
## Planning Rules
|
||||||
|
|
||||||
|
|
@ -110,12 +118,13 @@ and start being described as:
|
||||||
|
|
||||||
- "a stateful exact-data assistant with explicit transition contracts and isolated truth gating."
|
- "a stateful exact-data assistant with explicit transition contracts and isolated truth gating."
|
||||||
|
|
||||||
As of `2026-04-17`, the project is already materially closer to the target description, but mixed-session continuity is still not governed by one runtime authority.
|
As of `2026-04-18`, the project is already materially closer to the target description and no longer in the same acute collapse state, but mixed-session continuity is still not governed by one runtime authority strongly enough to justify low-risk multi-domain expansion.
|
||||||
|
|
||||||
The biggest remaining blockers are:
|
The biggest remaining blockers are:
|
||||||
|
|
||||||
- split continuity ownership across route / transition / recap / coordinator glue;
|
- split continuity ownership across route / transition / recap / coordinator glue;
|
||||||
|
- saved-session acceptance still too narrow compared with the intended domain-expansion blast radius;
|
||||||
- clarification precedence still too strong in mixed sessions;
|
- clarification precedence still too strong in mixed sessions;
|
||||||
- residual `assistantService` overload;
|
- residual `assistantService` overload;
|
||||||
- central intent pressure in `resolveAddressIntent()`;
|
- central intent pressure in `resolveAddressIntent()`;
|
||||||
- remaining answer-semantics pressure in `composeStage.ts`.
|
- remaining answer-semantics pressure in `composeStage.ts` and `answerComposer.ts`.
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ exports.readAddressDebugFilters = readAddressDebugFilters;
|
||||||
exports.readAddressDebugItem = readAddressDebugItem;
|
exports.readAddressDebugItem = readAddressDebugItem;
|
||||||
exports.readAddressDebugOrganization = readAddressDebugOrganization;
|
exports.readAddressDebugOrganization = readAddressDebugOrganization;
|
||||||
exports.readAddressDebugScopedDate = readAddressDebugScopedDate;
|
exports.readAddressDebugScopedDate = readAddressDebugScopedDate;
|
||||||
|
exports.buildInventoryRootFrameFromAddressDebug = buildInventoryRootFrameFromAddressDebug;
|
||||||
exports.isGroundedAddressDebug = isGroundedAddressDebug;
|
exports.isGroundedAddressDebug = isGroundedAddressDebug;
|
||||||
exports.resolveAssistantContinuitySnapshot = resolveAssistantContinuitySnapshot;
|
exports.resolveAssistantContinuitySnapshot = resolveAssistantContinuitySnapshot;
|
||||||
function fallbackToNonEmptyString(value) {
|
function fallbackToNonEmptyString(value) {
|
||||||
|
|
@ -50,6 +51,53 @@ function readAddressDebugScopedDate(debug) {
|
||||||
formatIsoDateForReply(rootFrameContext?.as_of_date) ??
|
formatIsoDateForReply(rootFrameContext?.as_of_date) ??
|
||||||
formatIsoDateForReply(extractedFilters?.period_to));
|
formatIsoDateForReply(extractedFilters?.period_to));
|
||||||
}
|
}
|
||||||
|
function buildInventoryRootFrameFromAddressDebug(debug, toNonEmptyString = fallbackToNonEmptyString) {
|
||||||
|
if (!debug || typeof debug !== "object") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const rootFrameContext = toRecordObject(debug.address_root_frame_context);
|
||||||
|
const extractedFilters = readAddressDebugFilters(debug) ?? {};
|
||||||
|
const detectedIntent = toNonEmptyString(debug.detected_intent);
|
||||||
|
const rootIntent = toNonEmptyString(rootFrameContext?.root_intent);
|
||||||
|
const effectiveIntent = rootIntent ?? detectedIntent;
|
||||||
|
if (effectiveIntent !== "inventory_on_hand_as_of_date") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const rootFiltersCandidate = toRecordObject(rootFrameContext?.root_filters);
|
||||||
|
const filters = {
|
||||||
|
...(rootFiltersCandidate ?? {}),
|
||||||
|
...(rootFiltersCandidate ? {} : extractedFilters)
|
||||||
|
};
|
||||||
|
if (!filters.organization) {
|
||||||
|
const organization = readAddressDebugOrganization(debug, toNonEmptyString);
|
||||||
|
if (organization) {
|
||||||
|
filters.organization = organization;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!filters.as_of_date) {
|
||||||
|
const scopedDate = formatIsoDateForReply(readAddressScopedIso(debug));
|
||||||
|
if (scopedDate) {
|
||||||
|
const parts = scopedDate.split(".");
|
||||||
|
filters.as_of_date = `${parts[2]}-${parts[1]}-${parts[0]}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
intent: "inventory_on_hand_as_of_date",
|
||||||
|
filters,
|
||||||
|
anchorType: toNonEmptyString(rootFrameContext?.root_anchor_type) ?? toNonEmptyString(debug.anchor_type),
|
||||||
|
anchorValue: toNonEmptyString(rootFrameContext?.root_anchor_value) ??
|
||||||
|
toNonEmptyString(debug.anchor_value_resolved) ??
|
||||||
|
toNonEmptyString(debug.anchor_value_raw),
|
||||||
|
currentFrameKind: toNonEmptyString(rootFrameContext?.current_frame_kind) ?? "inventory_root"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function readAddressScopedIso(debug) {
|
||||||
|
const extractedFilters = readAddressDebugFilters(debug);
|
||||||
|
const rootFrameContext = toRecordObject(debug?.address_root_frame_context);
|
||||||
|
return (fallbackToNonEmptyString(extractedFilters?.as_of_date) ??
|
||||||
|
fallbackToNonEmptyString(rootFrameContext?.as_of_date) ??
|
||||||
|
fallbackToNonEmptyString(extractedFilters?.period_to));
|
||||||
|
}
|
||||||
function isGroundedAddressDebug(debug, toNonEmptyString = fallbackToNonEmptyString) {
|
function isGroundedAddressDebug(debug, toNonEmptyString = fallbackToNonEmptyString) {
|
||||||
if (!debug || typeof debug !== "object") {
|
if (!debug || typeof debug !== "object") {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -103,10 +151,13 @@ function resolveAssistantContinuitySnapshot(input) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const primaryDebug = lastGroundedItemAddressDebug ?? lastGroundedAddressDebug;
|
const primaryDebug = lastGroundedItemAddressDebug ?? lastGroundedAddressDebug;
|
||||||
|
const inventoryRootFrame = buildInventoryRootFrameFromAddressDebug(lastGroundedInventoryAddressDebug, toNonEmptyString) ??
|
||||||
|
buildInventoryRootFrameFromAddressDebug(lastGroundedAddressDebug, toNonEmptyString);
|
||||||
return {
|
return {
|
||||||
lastGroundedAddressDebug,
|
lastGroundedAddressDebug,
|
||||||
lastGroundedItemAddressDebug,
|
lastGroundedItemAddressDebug,
|
||||||
lastGroundedInventoryAddressDebug,
|
lastGroundedInventoryAddressDebug,
|
||||||
|
inventoryRootFrame,
|
||||||
activeItem: readAddressDebugItem(primaryDebug, toNonEmptyString),
|
activeItem: readAddressDebugItem(primaryDebug, toNonEmptyString),
|
||||||
activeOrganization: readAddressDebugOrganization(primaryDebug, toNonEmptyString),
|
activeOrganization: readAddressDebugOrganization(primaryDebug, toNonEmptyString),
|
||||||
activeScopedDate: readAddressDebugScopedDate(primaryDebug),
|
activeScopedDate: readAddressDebugScopedDate(primaryDebug),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
// @ts-nocheck
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.createAssistantTransitionPolicy = createAssistantTransitionPolicy;
|
exports.createAssistantTransitionPolicy = createAssistantTransitionPolicy;
|
||||||
|
// @ts-nocheck
|
||||||
|
const assistantContinuityPolicy_1 = require("./assistantContinuityPolicy");
|
||||||
function createAssistantTransitionPolicy(deps) {
|
function createAssistantTransitionPolicy(deps) {
|
||||||
function normalizeFollowupText(value) {
|
function normalizeFollowupText(value) {
|
||||||
return deps.compactWhitespace(deps.repairAddressMojibake(String(value ?? "")).toLowerCase()).replace(/ё/g, "е");
|
return deps.compactWhitespace(deps.repairAddressMojibake(String(value ?? "")).toLowerCase()).replace(/ё/g, "е");
|
||||||
|
|
@ -154,16 +155,6 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
function readAddressDebugItemHint(debug) {
|
|
||||||
if (!debug || typeof debug !== "object") {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const extractedFilters = debug.extracted_filters && typeof debug.extracted_filters === "object" ? debug.extracted_filters : null;
|
|
||||||
return (deps.toNonEmptyString(extractedFilters?.item) ??
|
|
||||||
(deps.toNonEmptyString(debug.anchor_type) === "item"
|
|
||||||
? deps.toNonEmptyString(debug.anchor_value_resolved) ?? deps.toNonEmptyString(debug.anchor_value_raw)
|
|
||||||
: null));
|
|
||||||
}
|
|
||||||
function findRecentInventoryPurchaseProvenanceItem(items, itemHint = null) {
|
function findRecentInventoryPurchaseProvenanceItem(items, itemHint = null) {
|
||||||
const normalizedItemHint = deps.toNonEmptyString(itemHint);
|
const normalizedItemHint = deps.toNonEmptyString(itemHint);
|
||||||
for (let index = Array.isArray(items) ? items.length - 1 : -1; index >= 0; index -= 1) {
|
for (let index = Array.isArray(items) ? items.length - 1 : -1; index >= 0; index -= 1) {
|
||||||
|
|
@ -178,7 +169,7 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
if (!normalizedItemHint) {
|
if (!normalizedItemHint) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
const candidateItem = readAddressDebugItemHint(debug);
|
const candidateItem = (0, assistantContinuityPolicy_1.readAddressDebugItem)(debug, deps.toNonEmptyString);
|
||||||
if (candidateItem && candidateItem === normalizedItemHint) {
|
if (candidateItem && candidateItem === normalizedItemHint) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
@ -340,6 +331,10 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
? latestAddressItem
|
? latestAddressItem
|
||||||
: findRecentUsableAddressAssistantItem(items)) ?? latestAddressItem;
|
: findRecentUsableAddressAssistantItem(items)) ?? latestAddressItem;
|
||||||
const previousAddressDebug = previousAddressItem?.debug ?? null;
|
const previousAddressDebug = previousAddressItem?.debug ?? null;
|
||||||
|
const continuitySnapshot = (0, assistantContinuityPolicy_1.resolveAssistantContinuitySnapshot)({
|
||||||
|
sessionItems: items,
|
||||||
|
toNonEmptyString: deps.toNonEmptyString
|
||||||
|
});
|
||||||
const lastOrganizationClarificationDebug = deps.findLastOrganizationClarificationAddressDebug(items);
|
const lastOrganizationClarificationDebug = deps.findLastOrganizationClarificationAddressDebug(items);
|
||||||
const organizationClarificationCandidates = Array.isArray(lastOrganizationClarificationDebug?.organization_candidates)
|
const organizationClarificationCandidates = Array.isArray(lastOrganizationClarificationDebug?.organization_candidates)
|
||||||
? deps.mergeKnownOrganizations(lastOrganizationClarificationDebug.organization_candidates)
|
? deps.mergeKnownOrganizations(lastOrganizationClarificationDebug.organization_candidates)
|
||||||
|
|
@ -591,7 +586,9 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
const selectedObjectRetargetIntent = hasSelectedObjectInventorySignalPrimary || hasSelectedObjectInventorySignalAlternate
|
const selectedObjectRetargetIntent = hasSelectedObjectInventorySignalPrimary || hasSelectedObjectInventorySignalAlternate
|
||||||
? inferSelectedObjectInventoryFollowupIntent(userMessage, alternateMessage)
|
? inferSelectedObjectInventoryFollowupIntent(userMessage, alternateMessage)
|
||||||
: null;
|
: null;
|
||||||
let inventoryRootFrame = deps.findRecentInventoryRootFrame(items);
|
let inventoryRootFrame = deps.findRecentInventoryRootFrame(items) ??
|
||||||
|
continuitySnapshot.inventoryRootFrame ??
|
||||||
|
(0, assistantContinuityPolicy_1.buildInventoryRootFrameFromAddressDebug)(continuitySnapshot.lastGroundedAddressDebug, deps.toNonEmptyString);
|
||||||
if (inventoryRootFrame && navigationOrganization && !deps.toNonEmptyString(inventoryRootFrame.filters?.organization)) {
|
if (inventoryRootFrame && navigationOrganization && !deps.toNonEmptyString(inventoryRootFrame.filters?.organization)) {
|
||||||
inventoryRootFrame = {
|
inventoryRootFrame = {
|
||||||
...inventoryRootFrame,
|
...inventoryRootFrame,
|
||||||
|
|
@ -653,6 +650,9 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
previousFilters.organization = historicalOrganization;
|
previousFilters.organization = historicalOrganization;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!deps.toNonEmptyString(previousFilters.organization) && continuitySnapshot.activeOrganization) {
|
||||||
|
previousFilters.organization = continuitySnapshot.activeOrganization;
|
||||||
|
}
|
||||||
if (!deps.toNonEmptyString(previousFilters.organization) && navigationOrganization) {
|
if (!deps.toNonEmptyString(previousFilters.organization) && navigationOrganization) {
|
||||||
previousFilters.organization = navigationOrganization;
|
previousFilters.organization = navigationOrganization;
|
||||||
}
|
}
|
||||||
|
|
@ -664,7 +664,7 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
deps.toNonEmptyString(previousAddressDebug?.detected_intent) === "inventory_purchase_provenance_for_item"
|
deps.toNonEmptyString(previousAddressDebug?.detected_intent) === "inventory_purchase_provenance_for_item"
|
||||||
? previousAddressItem
|
? previousAddressItem
|
||||||
: findRecentInventoryPurchaseProvenanceItem(items, deps.toNonEmptyString(navigationFocusObjectLabel) ??
|
: findRecentInventoryPurchaseProvenanceItem(items, deps.toNonEmptyString(navigationFocusObjectLabel) ??
|
||||||
readAddressDebugItemHint(previousAddressDebug) ??
|
(0, assistantContinuityPolicy_1.readAddressDebugItem)(previousAddressDebug, deps.toNonEmptyString) ??
|
||||||
deps.toNonEmptyString(previousFilters.item)) ?? previousAddressItem;
|
deps.toNonEmptyString(previousFilters.item)) ?? previousAddressItem;
|
||||||
const purchaseBridgeWindow = extractPurchaseDateBridgeWindow(purchaseBridgeItem, addressNavigationState);
|
const purchaseBridgeWindow = extractPurchaseDateBridgeWindow(purchaseBridgeItem, addressNavigationState);
|
||||||
if (purchaseBridgeWindow) {
|
if (purchaseBridgeWindow) {
|
||||||
|
|
@ -687,16 +687,31 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
deps.toNonEmptyString(navigationDateScope?.as_of_date)) {
|
deps.toNonEmptyString(navigationDateScope?.as_of_date)) {
|
||||||
previousFilters.as_of_date = deps.toNonEmptyString(navigationDateScope?.as_of_date);
|
previousFilters.as_of_date = deps.toNonEmptyString(navigationDateScope?.as_of_date);
|
||||||
}
|
}
|
||||||
|
if (shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
|
!deps.toNonEmptyString(previousFilters.as_of_date) &&
|
||||||
|
(0, assistantContinuityPolicy_1.readAddressDebugFilters)(continuitySnapshot.lastGroundedAddressDebug)?.as_of_date) {
|
||||||
|
previousFilters.as_of_date = deps.toNonEmptyString((0, assistantContinuityPolicy_1.readAddressDebugFilters)(continuitySnapshot.lastGroundedAddressDebug)?.as_of_date);
|
||||||
|
}
|
||||||
if (shouldBackfillPreviousDateScopeFromNavigation &&
|
if (shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
!deps.toNonEmptyString(previousFilters.period_from) &&
|
!deps.toNonEmptyString(previousFilters.period_from) &&
|
||||||
deps.toNonEmptyString(navigationDateScope?.period_from)) {
|
deps.toNonEmptyString(navigationDateScope?.period_from)) {
|
||||||
previousFilters.period_from = deps.toNonEmptyString(navigationDateScope?.period_from);
|
previousFilters.period_from = deps.toNonEmptyString(navigationDateScope?.period_from);
|
||||||
}
|
}
|
||||||
|
if (shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
|
!deps.toNonEmptyString(previousFilters.period_from) &&
|
||||||
|
(0, assistantContinuityPolicy_1.readAddressDebugFilters)(continuitySnapshot.lastGroundedAddressDebug)?.period_from) {
|
||||||
|
previousFilters.period_from = deps.toNonEmptyString((0, assistantContinuityPolicy_1.readAddressDebugFilters)(continuitySnapshot.lastGroundedAddressDebug)?.period_from);
|
||||||
|
}
|
||||||
if (shouldBackfillPreviousDateScopeFromNavigation &&
|
if (shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
!deps.toNonEmptyString(previousFilters.period_to) &&
|
!deps.toNonEmptyString(previousFilters.period_to) &&
|
||||||
deps.toNonEmptyString(navigationDateScope?.period_to)) {
|
deps.toNonEmptyString(navigationDateScope?.period_to)) {
|
||||||
previousFilters.period_to = deps.toNonEmptyString(navigationDateScope?.period_to);
|
previousFilters.period_to = deps.toNonEmptyString(navigationDateScope?.period_to);
|
||||||
}
|
}
|
||||||
|
if (shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
|
!deps.toNonEmptyString(previousFilters.period_to) &&
|
||||||
|
(0, assistantContinuityPolicy_1.readAddressDebugFilters)(continuitySnapshot.lastGroundedAddressDebug)?.period_to) {
|
||||||
|
previousFilters.period_to = deps.toNonEmptyString((0, assistantContinuityPolicy_1.readAddressDebugFilters)(continuitySnapshot.lastGroundedAddressDebug)?.period_to);
|
||||||
|
}
|
||||||
const rootContextOnlyPivot = Boolean((deps.isInventorySelectedObjectIntent(sourceIntentHint) || currentFrameKind === "inventory_drilldown") &&
|
const rootContextOnlyPivot = Boolean((deps.isInventorySelectedObjectIntent(sourceIntentHint) || currentFrameKind === "inventory_drilldown") &&
|
||||||
deps.hasForeignAccountingPivotOverInventoryMessage(userMessage, alternateMessage) &&
|
deps.hasForeignAccountingPivotOverInventoryMessage(userMessage, alternateMessage) &&
|
||||||
!inventoryPurchaseDateVatBridge);
|
!inventoryPurchaseDateVatBridge);
|
||||||
|
|
@ -767,6 +782,7 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
hasSelectedObjectInventorySignalPrimary ||
|
hasSelectedObjectInventorySignalPrimary ||
|
||||||
hasSelectedObjectInventorySignalAlternate)) {
|
hasSelectedObjectInventorySignalAlternate)) {
|
||||||
const selectedObjectLabel = (navigationFocusObjectType === "item" ? navigationFocusObjectLabel : null) ??
|
const selectedObjectLabel = (navigationFocusObjectType === "item" ? navigationFocusObjectLabel : null) ??
|
||||||
|
continuitySnapshot.activeItem ??
|
||||||
extractSelectedObjectLabel(userMessage) ??
|
extractSelectedObjectLabel(userMessage) ??
|
||||||
(deps.toNonEmptyString(alternateMessage) ? extractSelectedObjectLabel(String(alternateMessage ?? "")) : null);
|
(deps.toNonEmptyString(alternateMessage) ? extractSelectedObjectLabel(String(alternateMessage ?? "")) : null);
|
||||||
if (selectedObjectLabel) {
|
if (selectedObjectLabel) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,13 @@ export interface AssistantContinuitySnapshot {
|
||||||
lastGroundedAddressDebug: Record<string, unknown> | null;
|
lastGroundedAddressDebug: Record<string, unknown> | null;
|
||||||
lastGroundedItemAddressDebug: Record<string, unknown> | null;
|
lastGroundedItemAddressDebug: Record<string, unknown> | null;
|
||||||
lastGroundedInventoryAddressDebug: Record<string, unknown> | null;
|
lastGroundedInventoryAddressDebug: Record<string, unknown> | null;
|
||||||
|
inventoryRootFrame: {
|
||||||
|
intent: string;
|
||||||
|
filters: Record<string, unknown>;
|
||||||
|
anchorType: string | null;
|
||||||
|
anchorValue: string | null;
|
||||||
|
currentFrameKind: string;
|
||||||
|
} | null;
|
||||||
activeItem: string | null;
|
activeItem: string | null;
|
||||||
activeOrganization: string | null;
|
activeOrganization: string | null;
|
||||||
activeScopedDate: string | null;
|
activeScopedDate: string | null;
|
||||||
|
|
@ -75,6 +82,69 @@ export function readAddressDebugScopedDate(debug: Record<string, unknown> | null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildInventoryRootFrameFromAddressDebug(
|
||||||
|
debug: Record<string, unknown> | null,
|
||||||
|
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
|
||||||
|
): {
|
||||||
|
intent: string;
|
||||||
|
filters: Record<string, unknown>;
|
||||||
|
anchorType: string | null;
|
||||||
|
anchorValue: string | null;
|
||||||
|
currentFrameKind: string;
|
||||||
|
} | null {
|
||||||
|
if (!debug || typeof debug !== "object") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const rootFrameContext = toRecordObject(debug.address_root_frame_context);
|
||||||
|
const extractedFilters = readAddressDebugFilters(debug) ?? {};
|
||||||
|
const detectedIntent = toNonEmptyString(debug.detected_intent);
|
||||||
|
const rootIntent = toNonEmptyString(rootFrameContext?.root_intent);
|
||||||
|
const effectiveIntent = rootIntent ?? detectedIntent;
|
||||||
|
if (effectiveIntent !== "inventory_on_hand_as_of_date") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootFiltersCandidate = toRecordObject(rootFrameContext?.root_filters);
|
||||||
|
const filters = {
|
||||||
|
...(rootFiltersCandidate ?? {}),
|
||||||
|
...(rootFiltersCandidate ? {} : extractedFilters)
|
||||||
|
};
|
||||||
|
if (!filters.organization) {
|
||||||
|
const organization = readAddressDebugOrganization(debug, toNonEmptyString);
|
||||||
|
if (organization) {
|
||||||
|
filters.organization = organization;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!filters.as_of_date) {
|
||||||
|
const scopedDate = formatIsoDateForReply(readAddressScopedIso(debug));
|
||||||
|
if (scopedDate) {
|
||||||
|
const parts = scopedDate.split(".");
|
||||||
|
filters.as_of_date = `${parts[2]}-${parts[1]}-${parts[0]}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
intent: "inventory_on_hand_as_of_date",
|
||||||
|
filters,
|
||||||
|
anchorType: toNonEmptyString(rootFrameContext?.root_anchor_type) ?? toNonEmptyString(debug.anchor_type),
|
||||||
|
anchorValue:
|
||||||
|
toNonEmptyString(rootFrameContext?.root_anchor_value) ??
|
||||||
|
toNonEmptyString(debug.anchor_value_resolved) ??
|
||||||
|
toNonEmptyString(debug.anchor_value_raw),
|
||||||
|
currentFrameKind: toNonEmptyString(rootFrameContext?.current_frame_kind) ?? "inventory_root"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function readAddressScopedIso(debug: Record<string, unknown> | null): string | null {
|
||||||
|
const extractedFilters = readAddressDebugFilters(debug);
|
||||||
|
const rootFrameContext = toRecordObject(debug?.address_root_frame_context);
|
||||||
|
return (
|
||||||
|
fallbackToNonEmptyString(extractedFilters?.as_of_date) ??
|
||||||
|
fallbackToNonEmptyString(rootFrameContext?.as_of_date) ??
|
||||||
|
fallbackToNonEmptyString(extractedFilters?.period_to)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function isGroundedAddressDebug(
|
export function isGroundedAddressDebug(
|
||||||
debug: Record<string, unknown> | null,
|
debug: Record<string, unknown> | null,
|
||||||
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
|
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
|
||||||
|
|
@ -142,10 +212,14 @@ export function resolveAssistantContinuitySnapshot(
|
||||||
}
|
}
|
||||||
|
|
||||||
const primaryDebug = lastGroundedItemAddressDebug ?? lastGroundedAddressDebug;
|
const primaryDebug = lastGroundedItemAddressDebug ?? lastGroundedAddressDebug;
|
||||||
|
const inventoryRootFrame =
|
||||||
|
buildInventoryRootFrameFromAddressDebug(lastGroundedInventoryAddressDebug, toNonEmptyString) ??
|
||||||
|
buildInventoryRootFrameFromAddressDebug(lastGroundedAddressDebug, toNonEmptyString);
|
||||||
return {
|
return {
|
||||||
lastGroundedAddressDebug,
|
lastGroundedAddressDebug,
|
||||||
lastGroundedItemAddressDebug,
|
lastGroundedItemAddressDebug,
|
||||||
lastGroundedInventoryAddressDebug,
|
lastGroundedInventoryAddressDebug,
|
||||||
|
inventoryRootFrame,
|
||||||
activeItem: readAddressDebugItem(primaryDebug, toNonEmptyString),
|
activeItem: readAddressDebugItem(primaryDebug, toNonEmptyString),
|
||||||
activeOrganization: readAddressDebugOrganization(primaryDebug, toNonEmptyString),
|
activeOrganization: readAddressDebugOrganization(primaryDebug, toNonEmptyString),
|
||||||
activeScopedDate: readAddressDebugScopedDate(primaryDebug),
|
activeScopedDate: readAddressDebugScopedDate(primaryDebug),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import {
|
||||||
|
buildInventoryRootFrameFromAddressDebug,
|
||||||
|
readAddressDebugFilters,
|
||||||
|
readAddressDebugItem,
|
||||||
|
resolveAssistantContinuitySnapshot
|
||||||
|
} from "./assistantContinuityPolicy";
|
||||||
|
|
||||||
export function createAssistantTransitionPolicy(deps) {
|
export function createAssistantTransitionPolicy(deps) {
|
||||||
function normalizeFollowupText(value) {
|
function normalizeFollowupText(value) {
|
||||||
|
|
@ -186,20 +192,6 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function readAddressDebugItemHint(debug) {
|
|
||||||
if (!debug || typeof debug !== "object") {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const extractedFilters =
|
|
||||||
debug.extracted_filters && typeof debug.extracted_filters === "object" ? debug.extracted_filters : null;
|
|
||||||
return (
|
|
||||||
deps.toNonEmptyString(extractedFilters?.item) ??
|
|
||||||
(deps.toNonEmptyString(debug.anchor_type) === "item"
|
|
||||||
? deps.toNonEmptyString(debug.anchor_value_resolved) ?? deps.toNonEmptyString(debug.anchor_value_raw)
|
|
||||||
: null)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function findRecentInventoryPurchaseProvenanceItem(items, itemHint = null) {
|
function findRecentInventoryPurchaseProvenanceItem(items, itemHint = null) {
|
||||||
const normalizedItemHint = deps.toNonEmptyString(itemHint);
|
const normalizedItemHint = deps.toNonEmptyString(itemHint);
|
||||||
for (let index = Array.isArray(items) ? items.length - 1 : -1; index >= 0; index -= 1) {
|
for (let index = Array.isArray(items) ? items.length - 1 : -1; index >= 0; index -= 1) {
|
||||||
|
|
@ -214,7 +206,7 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
if (!normalizedItemHint) {
|
if (!normalizedItemHint) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
const candidateItem = readAddressDebugItemHint(debug);
|
const candidateItem = readAddressDebugItem(debug, deps.toNonEmptyString);
|
||||||
if (candidateItem && candidateItem === normalizedItemHint) {
|
if (candidateItem && candidateItem === normalizedItemHint) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
@ -421,6 +413,10 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
? latestAddressItem
|
? latestAddressItem
|
||||||
: findRecentUsableAddressAssistantItem(items)) ?? latestAddressItem;
|
: findRecentUsableAddressAssistantItem(items)) ?? latestAddressItem;
|
||||||
const previousAddressDebug = previousAddressItem?.debug ?? null;
|
const previousAddressDebug = previousAddressItem?.debug ?? null;
|
||||||
|
const continuitySnapshot = resolveAssistantContinuitySnapshot({
|
||||||
|
sessionItems: items,
|
||||||
|
toNonEmptyString: deps.toNonEmptyString
|
||||||
|
});
|
||||||
const lastOrganizationClarificationDebug = deps.findLastOrganizationClarificationAddressDebug(items);
|
const lastOrganizationClarificationDebug = deps.findLastOrganizationClarificationAddressDebug(items);
|
||||||
const organizationClarificationCandidates = Array.isArray(lastOrganizationClarificationDebug?.organization_candidates)
|
const organizationClarificationCandidates = Array.isArray(lastOrganizationClarificationDebug?.organization_candidates)
|
||||||
? deps.mergeKnownOrganizations(lastOrganizationClarificationDebug.organization_candidates)
|
? deps.mergeKnownOrganizations(lastOrganizationClarificationDebug.organization_candidates)
|
||||||
|
|
@ -727,7 +723,10 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
hasSelectedObjectInventorySignalPrimary || hasSelectedObjectInventorySignalAlternate
|
hasSelectedObjectInventorySignalPrimary || hasSelectedObjectInventorySignalAlternate
|
||||||
? inferSelectedObjectInventoryFollowupIntent(userMessage, alternateMessage)
|
? inferSelectedObjectInventoryFollowupIntent(userMessage, alternateMessage)
|
||||||
: null;
|
: null;
|
||||||
let inventoryRootFrame = deps.findRecentInventoryRootFrame(items);
|
let inventoryRootFrame =
|
||||||
|
deps.findRecentInventoryRootFrame(items) ??
|
||||||
|
continuitySnapshot.inventoryRootFrame ??
|
||||||
|
buildInventoryRootFrameFromAddressDebug(continuitySnapshot.lastGroundedAddressDebug, deps.toNonEmptyString);
|
||||||
if (inventoryRootFrame && navigationOrganization && !deps.toNonEmptyString(inventoryRootFrame.filters?.organization)) {
|
if (inventoryRootFrame && navigationOrganization && !deps.toNonEmptyString(inventoryRootFrame.filters?.organization)) {
|
||||||
inventoryRootFrame = {
|
inventoryRootFrame = {
|
||||||
...inventoryRootFrame,
|
...inventoryRootFrame,
|
||||||
|
|
@ -794,6 +793,9 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
previousFilters.organization = historicalOrganization;
|
previousFilters.organization = historicalOrganization;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!deps.toNonEmptyString(previousFilters.organization) && continuitySnapshot.activeOrganization) {
|
||||||
|
previousFilters.organization = continuitySnapshot.activeOrganization;
|
||||||
|
}
|
||||||
if (!deps.toNonEmptyString(previousFilters.organization) && navigationOrganization) {
|
if (!deps.toNonEmptyString(previousFilters.organization) && navigationOrganization) {
|
||||||
previousFilters.organization = navigationOrganization;
|
previousFilters.organization = navigationOrganization;
|
||||||
}
|
}
|
||||||
|
|
@ -808,7 +810,7 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
: findRecentInventoryPurchaseProvenanceItem(
|
: findRecentInventoryPurchaseProvenanceItem(
|
||||||
items,
|
items,
|
||||||
deps.toNonEmptyString(navigationFocusObjectLabel) ??
|
deps.toNonEmptyString(navigationFocusObjectLabel) ??
|
||||||
readAddressDebugItemHint(previousAddressDebug) ??
|
readAddressDebugItem(previousAddressDebug, deps.toNonEmptyString) ??
|
||||||
deps.toNonEmptyString(previousFilters.item)
|
deps.toNonEmptyString(previousFilters.item)
|
||||||
) ?? previousAddressItem;
|
) ?? previousAddressItem;
|
||||||
const purchaseBridgeWindow = extractPurchaseDateBridgeWindow(purchaseBridgeItem, addressNavigationState);
|
const purchaseBridgeWindow = extractPurchaseDateBridgeWindow(purchaseBridgeItem, addressNavigationState);
|
||||||
|
|
@ -835,6 +837,15 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
) {
|
) {
|
||||||
previousFilters.as_of_date = deps.toNonEmptyString(navigationDateScope?.as_of_date);
|
previousFilters.as_of_date = deps.toNonEmptyString(navigationDateScope?.as_of_date);
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
|
!deps.toNonEmptyString(previousFilters.as_of_date) &&
|
||||||
|
readAddressDebugFilters(continuitySnapshot.lastGroundedAddressDebug)?.as_of_date
|
||||||
|
) {
|
||||||
|
previousFilters.as_of_date = deps.toNonEmptyString(
|
||||||
|
readAddressDebugFilters(continuitySnapshot.lastGroundedAddressDebug)?.as_of_date
|
||||||
|
);
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
shouldBackfillPreviousDateScopeFromNavigation &&
|
shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
!deps.toNonEmptyString(previousFilters.period_from) &&
|
!deps.toNonEmptyString(previousFilters.period_from) &&
|
||||||
|
|
@ -842,6 +853,15 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
) {
|
) {
|
||||||
previousFilters.period_from = deps.toNonEmptyString(navigationDateScope?.period_from);
|
previousFilters.period_from = deps.toNonEmptyString(navigationDateScope?.period_from);
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
|
!deps.toNonEmptyString(previousFilters.period_from) &&
|
||||||
|
readAddressDebugFilters(continuitySnapshot.lastGroundedAddressDebug)?.period_from
|
||||||
|
) {
|
||||||
|
previousFilters.period_from = deps.toNonEmptyString(
|
||||||
|
readAddressDebugFilters(continuitySnapshot.lastGroundedAddressDebug)?.period_from
|
||||||
|
);
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
shouldBackfillPreviousDateScopeFromNavigation &&
|
shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
!deps.toNonEmptyString(previousFilters.period_to) &&
|
!deps.toNonEmptyString(previousFilters.period_to) &&
|
||||||
|
|
@ -849,6 +869,15 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
) {
|
) {
|
||||||
previousFilters.period_to = deps.toNonEmptyString(navigationDateScope?.period_to);
|
previousFilters.period_to = deps.toNonEmptyString(navigationDateScope?.period_to);
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
shouldBackfillPreviousDateScopeFromNavigation &&
|
||||||
|
!deps.toNonEmptyString(previousFilters.period_to) &&
|
||||||
|
readAddressDebugFilters(continuitySnapshot.lastGroundedAddressDebug)?.period_to
|
||||||
|
) {
|
||||||
|
previousFilters.period_to = deps.toNonEmptyString(
|
||||||
|
readAddressDebugFilters(continuitySnapshot.lastGroundedAddressDebug)?.period_to
|
||||||
|
);
|
||||||
|
}
|
||||||
const rootContextOnlyPivot = Boolean(
|
const rootContextOnlyPivot = Boolean(
|
||||||
(deps.isInventorySelectedObjectIntent(sourceIntentHint) || currentFrameKind === "inventory_drilldown") &&
|
(deps.isInventorySelectedObjectIntent(sourceIntentHint) || currentFrameKind === "inventory_drilldown") &&
|
||||||
deps.hasForeignAccountingPivotOverInventoryMessage(userMessage, alternateMessage) &&
|
deps.hasForeignAccountingPivotOverInventoryMessage(userMessage, alternateMessage) &&
|
||||||
|
|
@ -935,6 +964,7 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
) {
|
) {
|
||||||
const selectedObjectLabel =
|
const selectedObjectLabel =
|
||||||
(navigationFocusObjectType === "item" ? navigationFocusObjectLabel : null) ??
|
(navigationFocusObjectType === "item" ? navigationFocusObjectLabel : null) ??
|
||||||
|
continuitySnapshot.activeItem ??
|
||||||
extractSelectedObjectLabel(userMessage) ??
|
extractSelectedObjectLabel(userMessage) ??
|
||||||
(deps.toNonEmptyString(alternateMessage) ? extractSelectedObjectLabel(String(alternateMessage ?? "")) : null);
|
(deps.toNonEmptyString(alternateMessage) ? extractSelectedObjectLabel(String(alternateMessage ?? "")) : null);
|
||||||
if (selectedObjectLabel) {
|
if (selectedObjectLabel) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue