Закрыть phase96 reviewed-route складских резервов и ликвидности
This commit is contained in:
parent
b99a3be083
commit
5220cb2e0e
|
|
@ -84,10 +84,11 @@ Fresh validation cut:
|
||||||
- Completed autonomy slice inside that loop: `Accounting Profit-Margin Reviewed Route`: `accounting_profit_margin` is now promoted from `needs_route_enablement` into a reviewed 90/91/99 accounting-result route with accepted live replay.
|
- Completed autonomy slice inside that loop: `Accounting Profit-Margin Reviewed Route`: `accounting_profit_margin` is now promoted from `needs_route_enablement` into a reviewed 90/91/99 accounting-result route with accepted live replay.
|
||||||
- Completed autonomy slice inside that loop: `Debt Due-Date Aging Reviewed Route`: `debt_due_date_aging_quality` is now promoted from proxy-only route-candidate gap into a reviewed payment-term/open-balance route with accepted live replay.
|
- Completed autonomy slice inside that loop: `Debt Due-Date Aging Reviewed Route`: `debt_due_date_aging_quality` is now promoted from proxy-only route-candidate gap into a reviewed payment-term/open-balance route with accepted live replay.
|
||||||
- Completed autonomy slice inside that loop: `Vendor/Procurement Quality Reviewed Route`: `vendor_risk_procurement_quality` now promotes to reviewed procurement-concentration evidence when confirmed outgoing payment, bank-like recipient segregation, non-financial recipient, counterparty-role, and contract-usage signals are reachable; phase95 live replay is accepted.
|
- Completed autonomy slice inside that loop: `Vendor/Procurement Quality Reviewed Route`: `vendor_risk_procurement_quality` now promotes to reviewed procurement-concentration evidence when confirmed outgoing payment, bank-like recipient segregation, non-financial recipient, counterparty-role, and contract-usage signals are reachable; phase95 live replay is accepted.
|
||||||
- Current live canary: `phase95_vendor_procurement_quality_reviewed_route_live2` accepted `7/7`.
|
- Completed autonomy slice inside that loop: `Inventory Reserve/Liquidation Quality Reviewed Route`: `inventory_reserve_liquidation_quality` now promotes to reviewed inventory quality-event evidence from posted write-off, receipt-adjustment, stocktaking, and revaluation documents; phase96 live replay is accepted.
|
||||||
- Current accepted autorun: `AGENT | Phase 95 vendor/procurement quality reviewed route` (`gen-ag05121357-9ea5d6`).
|
- Current live canary: `phase96_inventory_reserve_liquidation_quality_rerun` accepted `2/2`.
|
||||||
|
- Current accepted autorun: `AGENT | Phase 96 inventory reserve/liquidation quality-events` (`gen-ag05122057-c9786e`).
|
||||||
- Implementation breadth: `~99% (Open-World Bounded Autonomy Breadth through Slice 25)`.
|
- Implementation breadth: `~99% (Open-World Bounded Autonomy Breadth through Slice 25)`.
|
||||||
- Next active slice: select the remaining phase92 proof family `inventory_reserve_liquidation_quality`.
|
- Next active slice: start the broader open-world schema/primitive discovery module and use phase91-phase96 as regression canaries.
|
||||||
- Active module progress: `~99% (Agentic Semantic Development Loop, accepted dogfood loop + autorun hygiene; manual GUI confirmation still required)`.
|
- Active module progress: `~99% (Agentic Semantic Development Loop, accepted dogfood loop + autorun hygiene; manual GUI confirmation still required)`.
|
||||||
|
|
||||||
## Reporting Rule
|
## Reporting Rule
|
||||||
|
|
@ -99,7 +100,7 @@ Use these labels when reporting progress:
|
||||||
- `Прогресс модуля: 99% (Open-World Bounded Autonomy Breadth, active slice: Semantic Control Gate)` while discussing current module closure after the EHMO-derived critical subset accepted live again with W5/W7 hardening.
|
- `Прогресс модуля: 99% (Open-World Bounded Autonomy Breadth, active slice: Semantic Control Gate)` while discussing current module closure after the EHMO-derived critical subset accepted live again with W5/W7 hardening.
|
||||||
- `Прогресс модуля: 99% (Agentic Semantic Development Loop, accepted dogfood loop + autorun hygiene; manual GUI confirmation still required)` when discussing the current development-loop operating layer.
|
- `Прогресс модуля: 99% (Agentic Semantic Development Loop, accepted dogfood loop + autorun hygiene; manual GUI confirmation still required)` when discussing the current development-loop operating layer.
|
||||||
- `Прогресс модуля: 100% (Open-World Route Candidate Promotion, declared phase90 slice accepted)` when discussing the route-candidate handoff slice itself.
|
- `Прогресс модуля: 100% (Open-World Route Candidate Promotion, declared phase90 slice accepted)` when discussing the route-candidate handoff slice itself.
|
||||||
- `Прогресс модуля: 92% (Route-Candidate-Driven Enablement Loop, active slice: third reviewed proof-family route accepted)` when discussing the current candidate-driven enablement loop.
|
- `Прогресс модуля: 100% (Route-Candidate-Driven Enablement Loop, final reviewed proof-family route accepted; use as regression gate)` when discussing the current candidate-driven enablement loop.
|
||||||
- `Open-World Business Overview implementation breadth: ~99%, Semantic Control Gate critical subset accepted, fat GUI pack still pending` when discussing only the already wired Slice 25 breadth.
|
- `Open-World Business Overview implementation breadth: ~99%, Semantic Control Gate critical subset accepted, fat GUI pack still pending` when discussing only the already wired Slice 25 breadth.
|
||||||
- `Прогресс модуля: X% (Open-World Bounded Autonomy Breadth, active slice: <name>)` for later breadth work after the Semantic Control Gate is accepted.
|
- `Прогресс модуля: X% (Open-World Bounded Autonomy Breadth, active slice: <name>)` for later breadth work after the Semantic Control Gate is accepted.
|
||||||
|
|
||||||
|
|
@ -135,7 +136,7 @@ Remaining work belongs to the next breadth module:
|
||||||
- confirm the latest autorun Cyrillic hygiene cut in the GUI after backend refresh and inspect frontend/API payloads if old replacement characters remain visible;
|
- confirm the latest autorun Cyrillic hygiene cut in the GUI after backend refresh and inspect frontend/API payloads if old replacement characters remain visible;
|
||||||
- continue dogfooding the `Agentic Semantic Development Loop` on real stage packs, especially generated-question quality, semantic business audit, repair handoff, and rerun acceptance;
|
- continue dogfooding the `Agentic Semantic Development Loop` on real stage packs, especially generated-question quality, semantic business audit, repair handoff, and rerun acceptance;
|
||||||
- finish closure of the `Open-World Semantic Control Gate` opened by `assistant-stage1-EHMOy3lNFt`; the EHMO-derived critical subset is accepted live after W5/W7 hardening, but the fat GUI pack and residual answer-shape roughness still need final review;
|
- finish closure of the `Open-World Semantic Control Gate` opened by `assistant-stage1-EHMOy3lNFt`; the EHMO-derived critical subset is accepted live after W5/W7 hardening, but the fat GUI pack and residual answer-shape roughness still need final review;
|
||||||
- extend `business_overview` beyond money-flow/activity, customer and supplier concentration, document/account-section activity mix, counterparty role split, contract usage, yearly operating-flow dynamics, explicit profit/margin wording boundaries, explicit debt due-date wording boundaries, explicit inventory reserve/liquidation wording boundaries, explicit supplier/procurement-quality wording boundaries, explicit-period VAT/tax, as-of-date debt position, open-settlement concentration, contract-date debt age, debt staleness-risk proxy, as-of-date inventory position, trading-margin proxy, sales-to-stock inventory proxy, warehouse staleness-risk proxy, the missing-proof ledger, the reviewed accounting profit/margin route, the reviewed debt due-date aging route, and the reviewed vendor/procurement concentration route into confirmed reserve/write-off/liquidation inventory evidence families;
|
- extend open-world coverage beyond the reviewed `business_overview` families already wired for money-flow/activity, customer and supplier concentration, document/account-section activity mix, counterparty role split, contract usage, yearly operating-flow dynamics, explicit profit/margin, debt due-date aging, inventory reserve/liquidation quality events, supplier/procurement quality, explicit-period VAT/tax, as-of-date debt and inventory position, open-settlement concentration, contract-date debt age, staleness proxies, trading-margin proxy, sales-to-stock inventory proxy, the missing-proof ledger, and the phase93-phase96 reviewed routes;
|
||||||
- broader dynamic schema traversal for unfamiliar 1C asks;
|
- broader dynamic schema traversal for unfamiliar 1C asks;
|
||||||
- more primitive descriptors where live evidence proves a real gap;
|
- more primitive descriptors where live evidence proves a real gap;
|
||||||
- more replay-backed domain packs that start from user business meaning, not from route convenience;
|
- more replay-backed domain packs that start from user business meaning, not from route convenience;
|
||||||
|
|
@ -156,17 +157,19 @@ For current planning, read:
|
||||||
|
|
||||||
1. `README.md`
|
1. `README.md`
|
||||||
2. this document
|
2. this document
|
||||||
3. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
3. `31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md`
|
||||||
4. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
4. `30 - vendor_procurement_quality_reviewed_route_2026-05-12.md`
|
||||||
5. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
5. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
||||||
6. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
6. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
||||||
7. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
7. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
||||||
8. `24 - agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md`
|
8. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
||||||
9. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md`
|
9. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
||||||
10. `22 - open_world_bounded_autonomy_breadth_2026-05-01.md`
|
10. `24 - agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md`
|
||||||
11. `20 - planner_autonomy_consolidation_2026-05-01.md`
|
11. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md`
|
||||||
12. `19 - inventory_stock_open_world_breadth_proof_2026-05-01.md`
|
12. `22 - open_world_bounded_autonomy_breadth_2026-05-01.md`
|
||||||
13. `17 - post_f_semantic_integrity_hardening_2026-04-23.md`
|
13. `20 - planner_autonomy_consolidation_2026-05-01.md`
|
||||||
14. `16 - data_need_graph_and_open_world_mcp_plan_2026-04-22.md`
|
14. `19 - inventory_stock_open_world_breadth_proof_2026-05-01.md`
|
||||||
|
15. `17 - post_f_semantic_integrity_hardening_2026-04-23.md`
|
||||||
|
16. `16 - data_need_graph_and_open_world_mcp_plan_2026-04-22.md`
|
||||||
|
|
||||||
Documents `01` through `15` remain valuable, but mostly as the historical architecture trail.
|
Documents `01` through `15` remain valuable, but mostly as the historical architecture trail.
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ Status:
|
||||||
- implementation state: operational dogfood loop exists and has an accepted first loop artifact;
|
- implementation state: operational dogfood loop exists and has an accepted first loop artifact;
|
||||||
- semantic status: accepted loop artifact is useful, but manual GUI confirmation remains required;
|
- semantic status: accepted loop artifact is useful, but manual GUI confirmation remains required;
|
||||||
- hygiene status: saved autorun/runtime Cyrillic repair is covered by code/tests and the GUI-side check is reported clean;
|
- hygiene status: saved autorun/runtime Cyrillic repair is covered by code/tests and the GUI-side check is reported clean;
|
||||||
- current autonomy status: `Open-World Route Candidate Promotion` is live-accepted at `5/5`; `Route-Candidate-Driven Enablement Loop` has accepted phase91/phase92 canaries; `accounting_profit_margin` is promoted into a reviewed 90/91/99 route by phase93; `debt_due_date_aging_quality` is promoted into a reviewed payment-term/open-balance route by phase94; both reviewed proof-family routes are saved as accepted AGENT autoruns;
|
- current autonomy status: `Open-World Route Candidate Promotion` is live-accepted at `5/5`; `Route-Candidate-Driven Enablement Loop` has accepted phase91/phase92 canaries; `accounting_profit_margin` is promoted into a reviewed 90/91/99 route by phase93; `debt_due_date_aging_quality` is promoted into a reviewed payment-term/open-balance route by phase94; `vendor_risk_procurement_quality` is promoted into reviewed procurement-concentration evidence by phase95; `inventory_reserve_liquidation_quality` is promoted into reviewed inventory quality-event evidence by phase96; all four reviewed proof-family routes are saved as accepted AGENT autoruns;
|
||||||
- risk: medium, because the loop is now infrastructure for future acceptance decisions, not just a local route fix.
|
- risk: medium, because the loop is now infrastructure for future acceptance decisions, not just a local route fix.
|
||||||
|
|
||||||
Recommended reporting line:
|
Recommended reporting line:
|
||||||
|
|
@ -113,16 +113,16 @@ Still open:
|
||||||
- the first accepted dogfood loop proves the mechanism, not all future stage packs;
|
- the first accepted dogfood loop proves the mechanism, not all future stage packs;
|
||||||
- generated question quality still needs pressure from real GUI runs and user feedback;
|
- generated question quality still needs pressure from real GUI runs and user feedback;
|
||||||
- broad arbitrary 1C autonomy is still bounded by reviewed routes, truth gates, and replay evidence;
|
- broad arbitrary 1C autonomy is still bounded by reviewed routes, truth gates, and replay evidence;
|
||||||
- route-candidate-driven enablement still needs more proof-family promotions after the accepted `accounting_profit_margin` and `debt_due_date_aging_quality` routes;
|
- route-candidate-driven enablement is now closed after the accepted phase93-phase96 proof-family routes, and should be treated as a regression gate rather than as an open promotion backlog;
|
||||||
- manual GUI confirmation remains required before declaring a fat AGENT pack fully accepted.
|
- manual GUI confirmation remains required before declaring a fat AGENT pack fully accepted.
|
||||||
|
|
||||||
## Next Work
|
## Next Work
|
||||||
|
|
||||||
Next operational pass:
|
Next operational pass:
|
||||||
|
|
||||||
1. Use phase94 as the current candidate-driven enablement canary.
|
1. Use phase91-phase96 as current candidate-driven enablement canaries.
|
||||||
2. Continue dogfooding the stage-loop on real Open-World/agentic packs.
|
2. Continue dogfooding the stage-loop on real Open-World/agentic packs.
|
||||||
3. Pick the next proof family, likely vendor/procurement quality or inventory reserve/liquidation, and require the same live replay/save-after-acceptance discipline.
|
3. Move the active autonomy work to broader schema/primitive discovery and keep the same live replay/save-after-acceptance discipline.
|
||||||
4. Keep Post-F, phase83, inventory, business-overview, and mojibake autorun cases as regression canaries.
|
4. Keep Post-F, phase83, inventory, business-overview, and mojibake autorun cases as regression canaries.
|
||||||
|
|
||||||
## Canonical Reading Order Update
|
## Canonical Reading Order Update
|
||||||
|
|
@ -131,13 +131,15 @@ For current planning, read:
|
||||||
|
|
||||||
1. `README.md`
|
1. `README.md`
|
||||||
2. `21 - current_status_canon_2026-05-01.md`
|
2. `21 - current_status_canon_2026-05-01.md`
|
||||||
3. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
3. `31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md`
|
||||||
4. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
4. `30 - vendor_procurement_quality_reviewed_route_2026-05-12.md`
|
||||||
5. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
5. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
||||||
6. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
6. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
||||||
7. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
7. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
||||||
8. this document
|
8. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
||||||
9. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md`
|
9. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
||||||
10. `22 - open_world_bounded_autonomy_breadth_2026-05-01.md`
|
10. this document
|
||||||
11. `20 - planner_autonomy_consolidation_2026-05-01.md`
|
11. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md`
|
||||||
12. `17 - post_f_semantic_integrity_hardening_2026-04-23.md`
|
12. `22 - open_world_bounded_autonomy_breadth_2026-05-01.md`
|
||||||
|
13. `20 - planner_autonomy_consolidation_2026-05-01.md`
|
||||||
|
14. `17 - post_f_semantic_integrity_hardening_2026-04-23.md`
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ Live semantic replay:
|
||||||
- accepted user-runnable autorun for that route replay: `AGENT | Phase 94 debt due-date aging reviewed route` (`gen-ag05101319-c04f79`).
|
- accepted user-runnable autorun for that route replay: `AGENT | Phase 94 debt due-date aging reviewed route` (`gen-ag05101319-c04f79`).
|
||||||
- third proof-family route replay: `artifacts/domain_runs/phase95_vendor_procurement_quality_reviewed_route_live2`, `7/7` passed, `0` warnings, `0` failures.
|
- third proof-family route replay: `artifacts/domain_runs/phase95_vendor_procurement_quality_reviewed_route_live2`, `7/7` passed, `0` warnings, `0` failures.
|
||||||
- accepted user-runnable autorun for that route replay: `AGENT | Phase 95 vendor/procurement quality reviewed route` (`gen-ag05121357-9ea5d6`).
|
- accepted user-runnable autorun for that route replay: `AGENT | Phase 95 vendor/procurement quality reviewed route` (`gen-ag05121357-9ea5d6`).
|
||||||
|
- final proof-family route replay: `artifacts/domain_runs/phase96_inventory_reserve_liquidation_quality_rerun`, `2/2` passed, `0` warnings, `0` failures.
|
||||||
|
- accepted user-runnable autorun for that route replay: `AGENT | Phase 96 inventory reserve/liquidation quality-events` (`gen-ag05122057-c9786e`).
|
||||||
|
|
||||||
The replay proves the user-facing route-candidate canary remains healthy while the development tooling starts treating route candidates as repair-loop input:
|
The replay proves the user-facing route-candidate canary remains healthy while the development tooling starts treating route candidates as repair-loop input:
|
||||||
|
|
||||||
|
|
@ -64,25 +66,25 @@ The replay proves the user-facing route-candidate canary remains healthy while t
|
||||||
- exact accounting profit/margin wording now has the first reviewed route implementation and can move to `ready_for_reviewed_execution` through confirmed 90/91/99 accounting rows.
|
- exact accounting profit/margin wording now has the first reviewed route implementation and can move to `ready_for_reviewed_execution` through confirmed 90/91/99 accounting rows.
|
||||||
- exact due-date debt aging wording now has the second reviewed route implementation and can move to `ready_for_reviewed_execution` through confirmed open-balance/payment-term evidence, while absent payment terms produce an honest checked-negative boundary answer.
|
- exact due-date debt aging wording now has the second reviewed route implementation and can move to `ready_for_reviewed_execution` through confirmed open-balance/payment-term evidence, while absent payment terms produce an honest checked-negative boundary answer.
|
||||||
- exact vendor-risk/procurement wording now has a live-accepted reviewed procurement-concentration route that can move to `ready_for_reviewed_execution` when confirmed outgoing payment, bank-like recipient segregation, non-financial recipient, counterparty-role, and contract-usage evidence are reachable. It still does not prove supplier reliability, delivery quality, payment purpose, contract-term compliance, or full expense structure.
|
- exact vendor-risk/procurement wording now has a live-accepted reviewed procurement-concentration route that can move to `ready_for_reviewed_execution` when confirmed outgoing payment, bank-like recipient segregation, non-financial recipient, counterparty-role, and contract-usage evidence are reachable. It still does not prove supplier reliability, delivery quality, payment purpose, contract-term compliance, or full expense structure.
|
||||||
|
- exact reserve/write-off/liquidation wording now has a live-accepted reviewed inventory quality-events route that can move to `ready_for_reviewed_execution` when posted write-off, receipt-adjustment, stocktaking, or revaluation documents are reachable. It still does not prove market liquidation value, management reserve policy, or full warehouse health.
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
Current module wording:
|
Current module wording:
|
||||||
|
|
||||||
`Route-Candidate-Driven Enablement Loop, active slice: third reviewed proof-family route accepted`
|
`Route-Candidate-Driven Enablement Loop, active slice: final reviewed proof-family route accepted`
|
||||||
|
|
||||||
Progress: `92%`.
|
Progress: `100%`.
|
||||||
|
|
||||||
The first cut proved the handoff mechanics and live canary. The second cut proved real proof-family candidates and a saved accepted AGENT pack. The third cut proved the intended promotion loop on `accounting_profit_margin`. The fourth cut proved the same loop on `debt_due_date_aging_quality`, including short boundary follow-up continuity and saved accepted autorun hygiene. The fifth cut proves `vendor_risk_procurement_quality` as reviewed procurement-concentration evidence with accepted phase95 replay. The module is still not complete because the inventory reserve/liquidation proof family remains open.
|
The first cut proved the handoff mechanics and live canary. The second cut proved real proof-family candidates and a saved accepted AGENT pack. The third cut proved the intended promotion loop on `accounting_profit_margin`. The fourth cut proved the same loop on `debt_due_date_aging_quality`, including short boundary follow-up continuity and saved accepted autorun hygiene. The fifth cut proved `vendor_risk_procurement_quality` as reviewed procurement-concentration evidence with accepted phase95 replay. The final cut proved `inventory_reserve_liquidation_quality` as reviewed inventory quality-event evidence with accepted phase96 replay. The declared route-candidate-driven enablement loop is now closed; future arbitrary 1C breadth work should treat these routes as regression gates, not as open blockers.
|
||||||
|
|
||||||
## Next Work
|
## Next Work
|
||||||
|
|
||||||
Next slices:
|
Next slices:
|
||||||
|
|
||||||
1. Pick the final phase92 proof family: `inventory_reserve_liquidation_quality`.
|
1. Treat this module as closed and keep phase91/92/93/94/95/96 as regression canaries.
|
||||||
2. Implement or explicitly bound that final family only if reliable 1C evidence is reachable.
|
2. Start the next broader open-world autonomy slice: schema/primitive discovery beyond the selected phase92 proof families.
|
||||||
3. Rerun phase95 as a canary plus the focused inventory route-specific pack.
|
3. Keep save-after-acceptance discipline for any new AGENT packs.
|
||||||
4. Save the accepted pack into autoruns only after live replay and semantic review pass.
|
|
||||||
|
|
||||||
See also:
|
See also:
|
||||||
|
|
||||||
|
|
@ -90,3 +92,4 @@ See also:
|
||||||
- [28 - accounting_profit_margin_reviewed_route_2026-05-10.md](./28%20-%20accounting_profit_margin_reviewed_route_2026-05-10.md)
|
- [28 - accounting_profit_margin_reviewed_route_2026-05-10.md](./28%20-%20accounting_profit_margin_reviewed_route_2026-05-10.md)
|
||||||
- [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md)
|
- [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md)
|
||||||
- [30 - vendor_procurement_quality_reviewed_route_2026-05-12.md](./30%20-%20vendor_procurement_quality_reviewed_route_2026-05-12.md)
|
- [30 - vendor_procurement_quality_reviewed_route_2026-05-12.md](./30%20-%20vendor_procurement_quality_reviewed_route_2026-05-12.md)
|
||||||
|
- [31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md](./31%20-%20inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md)
|
||||||
|
|
|
||||||
|
|
@ -101,23 +101,23 @@ This means `vendor_risk_procurement_quality` is no longer only a missing-proof c
|
||||||
|
|
||||||
Current module wording:
|
Current module wording:
|
||||||
|
|
||||||
`Route-Candidate-Driven Enablement Loop, active slice: third reviewed proof-family route accepted`
|
`Route-Candidate-Driven Enablement Loop, final reviewed proof-family route accepted; use as regression gate`
|
||||||
|
|
||||||
Progress: `92%`.
|
Progress: `100%`.
|
||||||
|
|
||||||
This cut proved the missing-proof candidate surface and accepted user-runnable AGENT canary. Phase93 then implemented the first exact reviewed route for the accounting profit/margin family. Phase94 implemented the second reviewed route for due-date debt aging and verified short boundary follow-up continuity. Phase95 now promotes vendor/procurement quality through reviewed procurement-concentration evidence and accepted live replay. The remaining closure work is inventory reserve/liquidation enablement or an explicit bounded non-implementation decision.
|
This cut proved the missing-proof candidate surface and accepted user-runnable AGENT canary. Phase93 then implemented the first exact reviewed route for the accounting profit/margin family. Phase94 implemented the second reviewed route for due-date debt aging and verified short boundary follow-up continuity. Phase95 promoted vendor/procurement quality through reviewed procurement-concentration evidence. Phase96 promoted inventory reserve/liquidation quality through reviewed inventory quality-event documents. The declared route-candidate-driven enablement loop is now closed and should be used as a regression gate for broader autonomy work.
|
||||||
|
|
||||||
## Next Work
|
## Next Work
|
||||||
|
|
||||||
Next slices:
|
Next slices:
|
||||||
|
|
||||||
1. Wire or explicitly bound the final remaining family: `inventory_reserve_liquidation_quality`.
|
1. Use phase91-phase96 as regression canaries.
|
||||||
2. Keep proxy-only inventory reserve/liquidation wording bounded until reviewed evidence exists.
|
2. Start the next broader open-world schema/primitive discovery module.
|
||||||
3. Rerun phase95 as a canary plus the focused inventory route-specific pack.
|
3. Keep saving AGENT autoruns only after live replay and semantic review pass.
|
||||||
4. Save the next AGENT autorun only after live replay and semantic review pass.
|
|
||||||
|
|
||||||
See also:
|
See also:
|
||||||
|
|
||||||
- [28 - accounting_profit_margin_reviewed_route_2026-05-10.md](./28%20-%20accounting_profit_margin_reviewed_route_2026-05-10.md)
|
- [28 - accounting_profit_margin_reviewed_route_2026-05-10.md](./28%20-%20accounting_profit_margin_reviewed_route_2026-05-10.md)
|
||||||
- [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md)
|
- [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md)
|
||||||
- [30 - vendor_procurement_quality_reviewed_route_2026-05-12.md](./30%20-%20vendor_procurement_quality_reviewed_route_2026-05-12.md)
|
- [30 - vendor_procurement_quality_reviewed_route_2026-05-12.md](./30%20-%20vendor_procurement_quality_reviewed_route_2026-05-12.md)
|
||||||
|
- [31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md](./31%20-%20inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md)
|
||||||
|
|
|
||||||
|
|
@ -81,16 +81,16 @@ This keeps the phase93 accounting route as a canary while proving the candidate-
|
||||||
|
|
||||||
Current module wording:
|
Current module wording:
|
||||||
|
|
||||||
`Route-Candidate-Driven Enablement Loop, active slice: third reviewed proof-family route accepted`
|
`Route-Candidate-Driven Enablement Loop, final reviewed proof-family route accepted; use as regression gate`
|
||||||
|
|
||||||
Progress: `92%`.
|
Progress: `100%`.
|
||||||
|
|
||||||
This was the first proof that the loop can turn a route candidate into an executable reviewed route. Phase94 repeated the pattern for due-date debt aging, and phase95 accepted vendor/procurement quality through reviewed procurement-concentration evidence. The module is not yet complete because inventory reserve/liquidation still needs the same treatment or an explicit bounded non-implementation decision.
|
This was the first proof that the loop can turn a route candidate into an executable reviewed route. Phase94 repeated the pattern for due-date debt aging, phase95 accepted vendor/procurement quality through reviewed procurement-concentration evidence, and phase96 accepted inventory reserve/liquidation quality through reviewed inventory quality-event documents. The declared loop is now closed and this route remains a regression canary.
|
||||||
|
|
||||||
## Next Work
|
## Next Work
|
||||||
|
|
||||||
Next slices:
|
Next slices:
|
||||||
|
|
||||||
1. Select the remaining proof family: `inventory_reserve_liquidation_quality`.
|
1. Use this route as a regression canary during broader autonomy work.
|
||||||
2. Wire only the smallest reliable reviewed route, not a broad heuristic.
|
2. Continue the next module through open-world schema/primitive discovery rather than more phase92 proof-family closure.
|
||||||
3. Keep proxy-only reserve/liquidation wording bounded until the route is accepted.
|
3. Keep proof-specific wording bounded unless a reviewed route has live evidence.
|
||||||
|
|
|
||||||
|
|
@ -77,17 +77,16 @@ The accepted replay proves:
|
||||||
|
|
||||||
Current module wording:
|
Current module wording:
|
||||||
|
|
||||||
`Route-Candidate-Driven Enablement Loop, active slice: third reviewed proof-family route accepted`
|
`Route-Candidate-Driven Enablement Loop, final reviewed proof-family route accepted; use as regression gate`
|
||||||
|
|
||||||
Progress: `92%`.
|
Progress: `100%`.
|
||||||
|
|
||||||
This is the second live-accepted proof that the loop can turn a route candidate into an executable reviewed route. Phase95 now accepts `vendor_risk_procurement_quality` through reviewed procurement-concentration evidence. The module is not yet complete because inventory reserve/liquidation still needs either reviewed exact route enablement or an explicit bounded non-implementation decision.
|
This is the second live-accepted proof that the loop can turn a route candidate into an executable reviewed route. Phase95 accepted `vendor_risk_procurement_quality` through reviewed procurement-concentration evidence, and phase96 accepted `inventory_reserve_liquidation_quality` through reviewed inventory quality-event documents. The declared loop is now closed and this route remains a regression canary.
|
||||||
|
|
||||||
## Next Work
|
## Next Work
|
||||||
|
|
||||||
Next slices:
|
Next slices:
|
||||||
|
|
||||||
1. Identify whether reliable 1C evidence exists for `inventory_reserve_liquidation_quality`.
|
1. Use phase94, phase95, and phase96 as canaries for due-date, vendor, and inventory-quality continuity.
|
||||||
2. Wire the smallest reviewed route only if it can prove the inventory business claim without overreach.
|
2. Move the active plan to broader open-world schema/primitive discovery.
|
||||||
3. Keep proxy-only evidence bounded if exact proof is not reachable.
|
3. Keep proxy-only evidence bounded when a reviewed route is not available.
|
||||||
4. Rerun phase95 as a canary plus the focused inventory route-specific pack.
|
|
||||||
|
|
|
||||||
|
|
@ -62,29 +62,29 @@ Semantic/live replay:
|
||||||
|
|
||||||
Current module wording:
|
Current module wording:
|
||||||
|
|
||||||
`Route-Candidate-Driven Enablement Loop, active slice: third reviewed proof-family route accepted`
|
`Route-Candidate-Driven Enablement Loop, superseded by phase96 final reviewed proof-family acceptance`
|
||||||
|
|
||||||
Progress: `92%`.
|
Progress: `100%` in the parent loop after phase96.
|
||||||
|
|
||||||
The loop has now promoted three phase92 proof families from candidate gaps into reviewed execution or locally reviewed execution:
|
This phase remains the vendor/procurement-quality proof. After this note, phase96 promoted the final remaining inventory reserve/liquidation proof family, so the parent Route-Candidate-Driven Enablement Loop is now closed.
|
||||||
|
|
||||||
|
The loop has now promoted four phase92 proof families from candidate gaps into reviewed execution or locally reviewed execution:
|
||||||
|
|
||||||
- `accounting_profit_margin` accepted live by phase93;
|
- `accounting_profit_margin` accepted live by phase93;
|
||||||
- `debt_due_date_aging_quality` accepted live by phase94;
|
- `debt_due_date_aging_quality` accepted live by phase94;
|
||||||
- `vendor_risk_procurement_quality` accepted live through procurement-concentration evidence by phase95.
|
- `vendor_risk_procurement_quality` accepted live through procurement-concentration evidence by phase95.
|
||||||
|
- `inventory_reserve_liquidation_quality` accepted live through inventory quality-event evidence by phase96.
|
||||||
The module is still not complete because the remaining `inventory_reserve_liquidation_quality` family still needs either reviewed-route enablement or an explicit bounded non-implementation decision.
|
|
||||||
|
|
||||||
## Next Work
|
## Next Work
|
||||||
|
|
||||||
Next slices:
|
Next slices:
|
||||||
|
|
||||||
1. Select the final remaining phase92 family: `inventory_reserve_liquidation_quality`.
|
1. Use phase95 as a vendor/procurement regression canary during broader autonomy work.
|
||||||
2. Determine whether reachable 1C evidence can prove reserve/write-off/liquidation quality without overreach.
|
2. See phase96 for the final inventory reserve/liquidation route and module closure.
|
||||||
3. If yes, wire the smallest reviewed route and run a focused phase96 semantic replay.
|
|
||||||
4. If no, record an explicit bounded non-implementation decision and keep the proxy answer honest.
|
|
||||||
|
|
||||||
See also:
|
See also:
|
||||||
|
|
||||||
- [26 - route_candidate_driven_enablement_loop_2026-05-10.md](./26%20-%20route_candidate_driven_enablement_loop_2026-05-10.md)
|
- [26 - route_candidate_driven_enablement_loop_2026-05-10.md](./26%20-%20route_candidate_driven_enablement_loop_2026-05-10.md)
|
||||||
- [27 - proof_family_enablement_candidates_2026-05-10.md](./27%20-%20proof_family_enablement_candidates_2026-05-10.md)
|
- [27 - proof_family_enablement_candidates_2026-05-10.md](./27%20-%20proof_family_enablement_candidates_2026-05-10.md)
|
||||||
- [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md)
|
- [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md)
|
||||||
|
- [31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md](./31%20-%20inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
# 31 - Inventory Reserve/Liquidation Quality Reviewed Route (2026-05-12)
|
||||||
|
|
||||||
|
This note records the final phase92 proof-family promotion inside the `Route-Candidate-Driven Enablement Loop`.
|
||||||
|
|
||||||
|
## Why This Slice Exists
|
||||||
|
|
||||||
|
Phase92 exposed `inventory_reserve_liquidation_quality` as a real route-candidate gap:
|
||||||
|
|
||||||
|
- users can naturally ask whether warehouse stock has reserves, write-offs, obsolete goods, or liquidation value;
|
||||||
|
- earlier business overview could show stock position, sales-to-stock proxy, and staleness-risk proxy;
|
||||||
|
- those proxies were useful but still not reviewed evidence for write-offs, stocktaking, revaluation, reserve policy, or market liquidation value.
|
||||||
|
|
||||||
|
The safe implementation target was therefore not a fake "full inventory health" route. It was the narrowest reviewed 1C evidence route that can answer what is actually reachable.
|
||||||
|
|
||||||
|
## Implementation Cut
|
||||||
|
|
||||||
|
Implemented locally:
|
||||||
|
|
||||||
|
- added `inventory_quality_events_for_organization` as a reviewed address recipe intent;
|
||||||
|
- added `inventory_quality_events_profile` over posted 1C documents:
|
||||||
|
- `Документ.СписаниеТоваров`;
|
||||||
|
- `Документ.ОприходованиеТоваров`;
|
||||||
|
- `Документ.ИнвентаризацияТоваровНаСкладе`;
|
||||||
|
- `Документ.ПереоценкаТоваровВРознице`;
|
||||||
|
- `business_overview` now runs this probe only for reserve/liquidation/write-off/obsolete-stock boundary wording;
|
||||||
|
- `derived_business_overview.inventory_quality_events` records:
|
||||||
|
- checked period;
|
||||||
|
- matched event rows;
|
||||||
|
- write-off count and amount;
|
||||||
|
- receipt-adjustment count and amount;
|
||||||
|
- stocktaking count;
|
||||||
|
- revaluation count;
|
||||||
|
- first/latest event date when events exist;
|
||||||
|
- evidence status: `reviewed_no_quality_events_found`, `reviewed_inventory_control_events_only`, or `reviewed_writeoff_or_adjustment_events_found`;
|
||||||
|
- `inventory_reserve_liquidation_quality` is removed from `missing_proof_families` only when this reviewed route executed;
|
||||||
|
- `inventory_reserve_boundary` route candidates can now promote to `ready_for_reviewed_execution`;
|
||||||
|
- user-facing direct answers include the organization scope, period, checked document families, and explicit no-overclaim boundary.
|
||||||
|
|
||||||
|
## Boundaries
|
||||||
|
|
||||||
|
Still not claimed:
|
||||||
|
|
||||||
|
- market liquidation value;
|
||||||
|
- management reserve amount or reserve policy;
|
||||||
|
- confirmed obsolete stock classification;
|
||||||
|
- complete warehouse health;
|
||||||
|
- FIFO liquidation or sell-through quality;
|
||||||
|
- accounting correctness of the source documents.
|
||||||
|
|
||||||
|
The route can honestly say "checked documents found / not found". It cannot turn absence of events into a legal or market conclusion that no obsolete stock exists.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
Local validation:
|
||||||
|
|
||||||
|
- `npm.cmd test -- assistantMcpDiscoveryAnswerAdapter.test.ts assistantMcpDiscoveryRuntimeBridge.test.ts assistantMcpDiscoveryResponseCandidate.test.ts` passed `84/84` with `1` skipped;
|
||||||
|
- `npm.cmd test -- assistantMcpDiscoveryPilotExecutor.test.ts` passed `34/34`;
|
||||||
|
- `npm.cmd run build` passed;
|
||||||
|
- direct live MCP query for `address_inventory_quality_events_for_organization_v1` against `ООО Альтернатива Плюс / 2020` returned `fetched_rows=0`, `matched_rows=0`, `error=null`, proving the new union query is syntactically valid and yields a checked negative in the current base.
|
||||||
|
|
||||||
|
Semantic/live replay:
|
||||||
|
|
||||||
|
- spec: `docs/orchestration/address_truth_harness_phase96_inventory_reserve_liquidation_quality.json`;
|
||||||
|
- first live run: `artifacts/domain_runs/phase96_inventory_reserve_liquidation_quality_live`, partial/fail because the answer did not repeat the explicit organization in the direct line;
|
||||||
|
- rerun after organization anchoring and compact-candidate cleanup: `artifacts/domain_runs/phase96_inventory_reserve_liquidation_quality_rerun`;
|
||||||
|
- final status: `accepted`, `2/2` passed, `0` warnings, `0` failures;
|
||||||
|
- accepted autorun: `AGENT | Phase 96 inventory reserve/liquidation quality-events` (`gen-ag05122057-c9786e`).
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Current module wording:
|
||||||
|
|
||||||
|
`Route-Candidate-Driven Enablement Loop, active slice: final reviewed proof-family route accepted`
|
||||||
|
|
||||||
|
Progress: `100%`.
|
||||||
|
|
||||||
|
The loop has now promoted all phase92 proof-family candidates that were selected for this module:
|
||||||
|
|
||||||
|
- `accounting_profit_margin` accepted live by phase93;
|
||||||
|
- `debt_due_date_aging_quality` accepted live by phase94;
|
||||||
|
- `vendor_risk_procurement_quality` accepted live through procurement-concentration evidence by phase95;
|
||||||
|
- `inventory_reserve_liquidation_quality` accepted live through reviewed inventory quality-event documents by phase96.
|
||||||
|
|
||||||
|
This closes the declared Route-Candidate-Driven Enablement Loop slice. It does not close arbitrary 1C autonomy: the next work should move to the next broader module, using these proof-family routes as regression gates.
|
||||||
|
|
||||||
|
## Next Work
|
||||||
|
|
||||||
|
Next slices:
|
||||||
|
|
||||||
|
1. Reclassify Route-Candidate-Driven Enablement Loop as closed and use it as a regression gate.
|
||||||
|
2. Start the next open-world autonomy slice: broader schema/primitive discovery beyond the phase92 proof families.
|
||||||
|
3. Preserve phase93/94/95/96 accepted autoruns as canaries before expanding new unknown 1C domains.
|
||||||
|
|
||||||
|
See also:
|
||||||
|
|
||||||
|
- [26 - route_candidate_driven_enablement_loop_2026-05-10.md](./26%20-%20route_candidate_driven_enablement_loop_2026-05-10.md)
|
||||||
|
- [27 - proof_family_enablement_candidates_2026-05-10.md](./27%20-%20proof_family_enablement_candidates_2026-05-10.md)
|
||||||
|
- [28 - accounting_profit_margin_reviewed_route_2026-05-10.md](./28%20-%20accounting_profit_margin_reviewed_route_2026-05-10.md)
|
||||||
|
- [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md)
|
||||||
|
- [30 - vendor_procurement_quality_reviewed_route_2026-05-12.md](./30%20-%20vendor_procurement_quality_reviewed_route_2026-05-12.md)
|
||||||
|
|
@ -48,8 +48,9 @@ This package answers the next question:
|
||||||
28. [28 - accounting_profit_margin_reviewed_route_2026-05-10.md](./28%20-%20accounting_profit_margin_reviewed_route_2026-05-10.md)
|
28. [28 - accounting_profit_margin_reviewed_route_2026-05-10.md](./28%20-%20accounting_profit_margin_reviewed_route_2026-05-10.md)
|
||||||
29. [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md)
|
29. [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md)
|
||||||
30. [30 - vendor_procurement_quality_reviewed_route_2026-05-12.md](./30%20-%20vendor_procurement_quality_reviewed_route_2026-05-12.md)
|
30. [30 - vendor_procurement_quality_reviewed_route_2026-05-12.md](./30%20-%20vendor_procurement_quality_reviewed_route_2026-05-12.md)
|
||||||
|
31. [31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md](./31%20-%20inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md)
|
||||||
|
|
||||||
## Current Status Snapshot (2026-05-10)
|
## Current Status Snapshot (2026-05-12)
|
||||||
|
|
||||||
This package is no longer planning-only.
|
This package is no longer planning-only.
|
||||||
|
|
||||||
|
|
@ -103,16 +104,19 @@ Status canon for planning:
|
||||||
- The accepted user-runnable autorun for that slice is `AGENT | Phase 94 debt due-date aging reviewed route` (`gen-ag05101319-c04f79`).
|
- The accepted user-runnable autorun for that slice is `AGENT | Phase 94 debt due-date aging reviewed route` (`gen-ag05101319-c04f79`).
|
||||||
- The third proof-family route is now implemented and accepted: `vendor_risk_procurement_quality` moves from missing proof-family gap into reviewed procurement-concentration evidence when outgoing payment, bank-like recipient, non-financial recipient, counterparty-role, and contract-usage signals are reachable; `phase95_vendor_procurement_quality_reviewed_route_live2` passed `7/7`.
|
- The third proof-family route is now implemented and accepted: `vendor_risk_procurement_quality` moves from missing proof-family gap into reviewed procurement-concentration evidence when outgoing payment, bank-like recipient, non-financial recipient, counterparty-role, and contract-usage signals are reachable; `phase95_vendor_procurement_quality_reviewed_route_live2` passed `7/7`.
|
||||||
- The accepted user-runnable autorun for that slice is `AGENT | Phase 95 vendor/procurement quality reviewed route` (`gen-ag05121357-9ea5d6`).
|
- The accepted user-runnable autorun for that slice is `AGENT | Phase 95 vendor/procurement quality reviewed route` (`gen-ag05121357-9ea5d6`).
|
||||||
|
- The fourth/final proof-family route is now implemented and accepted: `inventory_reserve_liquidation_quality` moves from missing proof-family gap into reviewed inventory quality-event evidence over posted write-off, receipt-adjustment, stocktaking, and revaluation documents; `phase96_inventory_reserve_liquidation_quality_rerun` passed `2/2`.
|
||||||
|
- The accepted user-runnable autorun for that slice is `AGENT | Phase 96 inventory reserve/liquidation quality-events` (`gen-ag05122057-c9786e`).
|
||||||
- The phase94 replay spec was repaired to real UTF-8 Russian before autorun persistence, so the saved user-runnable pack does not repeat the earlier GUI mojibake/card-text regression.
|
- The phase94 replay spec was repaired to real UTF-8 Russian before autorun persistence, so the saved user-runnable pack does not repeat the earlier GUI mojibake/card-text regression.
|
||||||
- The short source of truth for status wording is [21 - current_status_canon_2026-05-01.md](./21%20-%20current_status_canon_2026-05-01.md).
|
- The short source of truth for status wording is [21 - current_status_canon_2026-05-01.md](./21%20-%20current_status_canon_2026-05-01.md).
|
||||||
- The current execution spine after EHMO is [23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md](./23%20-%20current_execution_spine_and_semantic_control_gate_2026-05-05.md).
|
- The current execution spine after EHMO is [23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md](./23%20-%20current_execution_spine_and_semantic_control_gate_2026-05-05.md).
|
||||||
- The current stage-loop/hygiene overlay after the AGENT dogfood cut is [24 - agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md](./24%20-%20agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md).
|
- The current stage-loop/hygiene overlay after the AGENT dogfood cut is [24 - agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md](./24%20-%20agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md).
|
||||||
- The current route-candidate autonomy slice is [25 - open_world_route_candidate_promotion_2026-05-10.md](./25%20-%20open_world_route_candidate_promotion_2026-05-10.md).
|
- The current route-candidate autonomy slice is [25 - open_world_route_candidate_promotion_2026-05-10.md](./25%20-%20open_world_route_candidate_promotion_2026-05-10.md).
|
||||||
- The current route-candidate enablement-loop slice is [26 - route_candidate_driven_enablement_loop_2026-05-10.md](./26%20-%20route_candidate_driven_enablement_loop_2026-05-10.md).
|
- The closed route-candidate enablement-loop slice is [26 - route_candidate_driven_enablement_loop_2026-05-10.md](./26%20-%20route_candidate_driven_enablement_loop_2026-05-10.md), now used as a regression gate.
|
||||||
- The current proof-family enablement-candidate slice is [27 - proof_family_enablement_candidates_2026-05-10.md](./27%20-%20proof_family_enablement_candidates_2026-05-10.md).
|
- The closed proof-family enablement-candidate slice is [27 - proof_family_enablement_candidates_2026-05-10.md](./27%20-%20proof_family_enablement_candidates_2026-05-10.md).
|
||||||
- The current first reviewed proof-family route slice is [28 - accounting_profit_margin_reviewed_route_2026-05-10.md](./28%20-%20accounting_profit_margin_reviewed_route_2026-05-10.md).
|
- The first reviewed proof-family route slice is [28 - accounting_profit_margin_reviewed_route_2026-05-10.md](./28%20-%20accounting_profit_margin_reviewed_route_2026-05-10.md).
|
||||||
- The current second reviewed proof-family route slice is [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md).
|
- The second reviewed proof-family route slice is [29 - debt_due_date_aging_reviewed_route_2026-05-10.md](./29%20-%20debt_due_date_aging_reviewed_route_2026-05-10.md).
|
||||||
- The current third reviewed proof-family route slice is [30 - vendor_procurement_quality_reviewed_route_2026-05-12.md](./30%20-%20vendor_procurement_quality_reviewed_route_2026-05-12.md).
|
- The third reviewed proof-family route slice is [30 - vendor_procurement_quality_reviewed_route_2026-05-12.md](./30%20-%20vendor_procurement_quality_reviewed_route_2026-05-12.md).
|
||||||
|
- The fourth/final reviewed proof-family route slice is [31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md](./31%20-%20inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md).
|
||||||
|
|
||||||
It now documents a turnaround that is already operational in code, already materially past the acute regression breakpoint, and already moved through bounded MCP autonomy, Post-F hardening, inventory breadth proof, and the declared Planner Autonomy slice:
|
It now documents a turnaround that is already operational in code, already materially past the acute regression breakpoint, and already moved through bounded MCP autonomy, Post-F hardening, inventory breadth proof, and the declared Planner Autonomy slice:
|
||||||
|
|
||||||
|
|
@ -176,13 +180,13 @@ Current honest status:
|
||||||
- pre-multidomain readiness: `~90%`
|
- pre-multidomain readiness: `~90%`
|
||||||
- bounded-autonomy foundation readiness: `~89%`
|
- bounded-autonomy foundation readiness: `~89%`
|
||||||
- open-world bounded-autonomy readiness: `~87%`
|
- open-world bounded-autonomy readiness: `~87%`
|
||||||
- active Open-World Bounded Autonomy Breadth implementation breadth: `~99%`, with business-overview evidence fusion, the reviewed `business_overview` catalog/data-need/planner route-fabric slice, the fresh multi-probe runtime bridge, the explicit-period VAT/tax fact-family bridge, the explicit-period debt-position bridge, the explicit-date inventory-position bridge, the open-settlement quality bridge accepted by live semantic replay, selected-item profitability bridged by local semantic/runtime regression tests, contract-date debt age bridged locally, debt staleness-risk proxy bridged locally, debt due-date boundary arbitration bridged locally, inventory reserve/liquidation boundary arbitration bridged locally, supplier/procurement-quality boundary arbitration bridged locally, supplier concentration proxy bridged locally, document/account-section activity profile bridged locally, counterparty population/roles and contract usage profiles bridged locally, yearly operating-flow proxy bridged locally, earnings/best-year wording arbitration bridged locally, profit/margin wording boundary arbitration bridged locally, analyst synthesis added to business-overview answer drafting, company-period trading margin proxy bridged locally, inventory sales-to-stock proxy bridged locally, inventory staleness-risk proxy bridged locally, gap-specific answer shaping bridged locally, missing proof families recorded as runtime evidence ledger, exact accounting profit/margin promoted into a reviewed 90/91/99 route by phase93, debt due-date aging promoted into a reviewed payment-term/open-balance route by phase94, and vendor/procurement quality promoted into reviewed procurement-concentration evidence by phase95; confirmed reserve/write-off/liquidation inventory evidence is still pending
|
- active Open-World Bounded Autonomy Breadth implementation breadth: `~99%`, with business-overview evidence fusion, the reviewed `business_overview` catalog/data-need/planner route-fabric slice, the fresh multi-probe runtime bridge, the explicit-period VAT/tax fact-family bridge, the explicit-period debt-position bridge, the explicit-date inventory-position bridge, the open-settlement quality bridge accepted by live semantic replay, selected-item profitability bridged by local semantic/runtime regression tests, contract-date debt age bridged locally, debt staleness-risk proxy bridged locally, debt due-date boundary arbitration bridged locally, inventory reserve/liquidation boundary arbitration bridged locally, supplier/procurement-quality boundary arbitration bridged locally, supplier concentration proxy bridged locally, document/account-section activity profile bridged locally, counterparty population/roles and contract usage profiles bridged locally, yearly operating-flow proxy bridged locally, earnings/best-year wording arbitration bridged locally, profit/margin wording boundary arbitration bridged locally, analyst synthesis added to business-overview answer drafting, company-period trading margin proxy bridged locally, inventory sales-to-stock proxy bridged locally, inventory staleness-risk proxy bridged locally, gap-specific answer shaping bridged locally, missing proof families recorded as runtime evidence ledger, exact accounting profit/margin promoted into a reviewed 90/91/99 route by phase93, debt due-date aging promoted into a reviewed payment-term/open-balance route by phase94, vendor/procurement quality promoted into reviewed procurement-concentration evidence by phase95, and inventory reserve/write-off/liquidation quality promoted into reviewed inventory quality-event evidence by phase96
|
||||||
- active Open-World Bounded Autonomy Breadth accepted-module progress: `~99%`, because the EHMO-derived `Open-World Semantic Control Gate` critical subset accepts live at `21/21` after W5/W7 hardening; full closure is still held back for the fat manual GUI pack and remaining answer-shape residual review
|
- active Open-World Bounded Autonomy Breadth accepted-module progress: `~99%`, because the EHMO-derived `Open-World Semantic Control Gate` critical subset accepts live at `21/21` after W5/W7 hardening; full closure is still held back for the fat manual GUI pack and remaining answer-shape residual review
|
||||||
- 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
|
- 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
|
- active inventory-stock breadth slice progress: `100%` for the declared scenario pack, not for arbitrary inventory questions
|
||||||
- Planner Autonomy Consolidation progress: `100%` 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, subject-aware bidirectional comparison arbitration, structured catalog-alignment verdicts, representative alignment regression guard, catalog-alignment reason-code telemetry, explicit `alignment_status` propagation, truth-harness/acceptance-matrix surfacing, soft divergence warning, `catalog_alignment_ok` acceptance invariant, step-level expected catalog-alignment assertions, phase66 and phase32 spec alignment expectations, AGENT source-catalog surfacing, generated phase83 mixed planner-brain replay spec, checked-source user-facing error sanitation, surface-grounded catalog promotion, and guarded live phase83 acceptance validated. Broader unfamiliar 1C asks are now next-module breadth work rather than an open blocker inside this declared slice
|
- Planner Autonomy Consolidation progress: `100%` 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, subject-aware bidirectional comparison arbitration, structured catalog-alignment verdicts, representative alignment regression guard, catalog-alignment reason-code telemetry, explicit `alignment_status` propagation, truth-harness/acceptance-matrix surfacing, soft divergence warning, `catalog_alignment_ok` acceptance invariant, step-level expected catalog-alignment assertions, phase66 and phase32 spec alignment expectations, AGENT source-catalog surfacing, generated phase83 mixed planner-brain replay spec, checked-source user-facing error sanitation, surface-grounded catalog promotion, and guarded live phase83 acceptance validated. Broader unfamiliar 1C asks are now next-module breadth work rather than an open blocker inside this declared slice
|
||||||
- Open-World Route Candidate Promotion progress: `100%` for the declared phase90 slice, with structured `route_candidate` runtime contract, artifact propagation, live semantic replay accepted at `5/5`, and accepted AGENT autorun persistence; broader autonomous route enablement remains the next active slice
|
- Open-World Route Candidate Promotion progress: `100%` for the declared phase90 slice, with structured `route_candidate` runtime contract, artifact propagation, live semantic replay accepted at `5/5`, and accepted AGENT autorun persistence; broader autonomous route enablement remains the next active slice
|
||||||
- Route-Candidate-Driven Enablement Loop progress: `92%`, with deterministic repair-target grouping, Lead Codex handoff surfacing, local tooling tests, live phase91 canary acceptance, phase92 proof-family candidates accepted/saved as a user-runnable AGENT autorun, `accounting_profit_margin` promoted into reviewed 90/91/99 execution by phase93 live replay, `debt_due_date_aging_quality` promoted into reviewed payment-term/open-balance execution by phase94 live replay, and `vendor_risk_procurement_quality` promoted into reviewed procurement-concentration evidence by phase95 live replay; the remaining inventory reserve/liquidation proof family is still pending
|
- Route-Candidate-Driven Enablement Loop progress: `100%`, with deterministic repair-target grouping, Lead Codex handoff surfacing, local tooling tests, live phase91 canary acceptance, phase92 proof-family candidates accepted/saved as a user-runnable AGENT autorun, `accounting_profit_margin` promoted into reviewed 90/91/99 execution by phase93 live replay, `debt_due_date_aging_quality` promoted into reviewed payment-term/open-balance execution by phase94 live replay, `vendor_risk_procurement_quality` promoted into reviewed procurement-concentration evidence by phase95 live replay, and `inventory_reserve_liquidation_quality` promoted into reviewed inventory quality-event evidence by phase96 live replay; the declared route-candidate-driven enablement loop is now closed and should be used as a regression gate for the next broader autonomy slice
|
||||||
- graph snapshot after latest rebuild: see `graphify-out/GRAPH_REPORT.md`
|
- graph snapshot after latest rebuild: see `graphify-out/GRAPH_REPORT.md`
|
||||||
- current regression-gate breakpoint:
|
- current regression-gate breakpoint:
|
||||||
- the validated hot paths are no longer structurally broken;
|
- the validated hot paths are no longer structurally broken;
|
||||||
|
|
@ -272,6 +276,7 @@ Latest live proof now includes:
|
||||||
- accounting profit/margin reviewed route accepted locally/live: targeted runtime/answer/turn-input/candidate/intent tests passed `194/194` with `8` skipped; targeted VAT tax-period regression passed; `address_truth_harness_phase93_accounting_profit_margin_reviewed_route_live3_20260510` accepted `6/6`, proving 90/91/99 accounting result, short profit/loss follow-up continuity, VAT continuity, value-flow canary, and inventory reserve boundary canary together; the accepted autorun is `AGENT | Phase 93 accounting profit-margin reviewed route` (`gen-ag05101213-596d99`).
|
- accounting profit/margin reviewed route accepted locally/live: targeted runtime/answer/turn-input/candidate/intent tests passed `194/194` with `8` skipped; targeted VAT tax-period regression passed; `address_truth_harness_phase93_accounting_profit_margin_reviewed_route_live3_20260510` accepted `6/6`, proving 90/91/99 accounting result, short profit/loss follow-up continuity, VAT continuity, value-flow canary, and inventory reserve boundary canary together; the accepted autorun is `AGENT | Phase 93 accounting profit-margin reviewed route` (`gen-ag05101213-596d99`).
|
||||||
- debt due-date aging reviewed route accepted locally/live: transition policy passed `38/38`, turn-input adapter passed `103/103` with `7` skipped, executor/answer/candidate/runtime bridge passed `113/113` with `1` skipped, build passed; `phase94_debt_due_date_aging_reviewed_route_live4` accepted `7/7`, proving payment-term/open-balance checked-negative overdue answers, short due-date boundary follow-up continuity, profit/margin/VAT/value-flow canaries, and reserve/vendor boundary safety together; the accepted autorun is `AGENT | Phase 94 debt due-date aging reviewed route` (`gen-ag05101319-c04f79`).
|
- debt due-date aging reviewed route accepted locally/live: transition policy passed `38/38`, turn-input adapter passed `103/103` with `7` skipped, executor/answer/candidate/runtime bridge passed `113/113` with `1` skipped, build passed; `phase94_debt_due_date_aging_reviewed_route_live4` accepted `7/7`, proving payment-term/open-balance checked-negative overdue answers, short due-date boundary follow-up continuity, profit/margin/VAT/value-flow canaries, and reserve/vendor boundary safety together; the accepted autorun is `AGENT | Phase 94 debt due-date aging reviewed route` (`gen-ag05101319-c04f79`).
|
||||||
- vendor/procurement quality reviewed route accepted locally/live: executor/runtime bridge/answer/candidate tests passed `118/118` with `1` skipped, build passed; `phase95_vendor_procurement_quality_reviewed_route_live2` accepted `7/7`; `vendor_risk_procurement_quality` now derives reviewed procurement-concentration evidence from confirmed outgoing payment rows, separates bank-like outgoing leaders from ordinary supplier dependency, removes the proof family from `missing_proof_families` when this reviewed evidence exists, and can promote `vendor_risk_procurement_boundary` route candidates to `ready_for_reviewed_execution`; the accepted autorun is `AGENT | Phase 95 vendor/procurement quality reviewed route` (`gen-ag05121357-9ea5d6`).
|
- vendor/procurement quality reviewed route accepted locally/live: executor/runtime bridge/answer/candidate tests passed `118/118` with `1` skipped, build passed; `phase95_vendor_procurement_quality_reviewed_route_live2` accepted `7/7`; `vendor_risk_procurement_quality` now derives reviewed procurement-concentration evidence from confirmed outgoing payment rows, separates bank-like outgoing leaders from ordinary supplier dependency, removes the proof family from `missing_proof_families` when this reviewed evidence exists, and can promote `vendor_risk_procurement_boundary` route candidates to `ready_for_reviewed_execution`; the accepted autorun is `AGENT | Phase 95 vendor/procurement quality reviewed route` (`gen-ag05121357-9ea5d6`).
|
||||||
|
- inventory reserve/liquidation quality reviewed route accepted locally/live: answer/runtime/candidate tests passed `84/84` with `1` skipped, pilot-executor tests passed `34/34`, build passed; direct MCP query for `address_inventory_quality_events_for_organization_v1` returned `fetched_rows=0`, `matched_rows=0`, `error=null`; `phase96_inventory_reserve_liquidation_quality_rerun` accepted `2/2`; `inventory_reserve_liquidation_quality` now derives reviewed evidence from posted write-off, receipt-adjustment, stocktaking, and revaluation documents, removes the proof family from `missing_proof_families` when this reviewed route executes, anchors the organization in the direct answer, and can promote `inventory_reserve_boundary` route candidates to `ready_for_reviewed_execution`; the accepted autorun is `AGENT | Phase 96 inventory reserve/liquidation quality-events` (`gen-ag05122057-c9786e`).
|
||||||
|
|
||||||
Current architectural reading:
|
Current architectural reading:
|
||||||
|
|
||||||
|
|
@ -351,6 +356,7 @@ Read in this order:
|
||||||
29. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
29. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
||||||
30. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
30. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
||||||
31. `30 - vendor_procurement_quality_reviewed_route_2026-05-12.md`
|
31. `30 - vendor_procurement_quality_reviewed_route_2026-05-12.md`
|
||||||
|
32. `31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md`
|
||||||
|
|
||||||
## Planning Rules
|
## Planning Rules
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
{
|
||||||
|
"schema_version": "domain_truth_harness_spec_v1",
|
||||||
|
"scenario_id": "address_truth_harness_phase96_inventory_reserve_liquidation_quality",
|
||||||
|
"domain": "address_phase96_inventory_reserve_liquidation_quality",
|
||||||
|
"title": "Phase 96 inventory reserve/liquidation quality-events replay",
|
||||||
|
"description": "Targeted replay for the reviewed inventory quality-events route: direct reserve/write-off/liquidation questions should trigger checked 1C document evidence for write-offs, receipt adjustments, stocktaking, and retail revaluation, while still refusing to invent market liquidation value or management reserve policy.",
|
||||||
|
"bindings": {},
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"step_id": "step_01_direct_inventory_reserve_liquidation_boundary",
|
||||||
|
"title": "Direct reserve/liquidation boundary uses reviewed inventory quality events",
|
||||||
|
"question": "По ООО Альтернатива Плюс за 2020 год проверь склад: были ли списания товаров, оприходования/корректировки, инвентаризации, переоценки, резервы под неликвиды или ликвидационная стоимость? Скажи коротко и честно, что подтверждено 1С, а что нельзя утверждать.",
|
||||||
|
"expected_catalog_alignment_status": "selected_matches_top",
|
||||||
|
"expected_catalog_chain_top_match": "business_overview",
|
||||||
|
"expected_catalog_selected_matches_top": true,
|
||||||
|
"allowed_reply_types": [
|
||||||
|
"partial_coverage",
|
||||||
|
"factual_with_explanation"
|
||||||
|
],
|
||||||
|
"required_answer_patterns_all": [
|
||||||
|
"(?i)альтернатива|организац|компани",
|
||||||
|
"(?i)2020|2020 год",
|
||||||
|
"(?i)склад|товар",
|
||||||
|
"(?i)списан|оприход|инвентаризац|переоцен",
|
||||||
|
"(?i)провер|подтвержд|1с",
|
||||||
|
"(?i)не рыночн|не ликвидационн|не управленческ|не резерв"
|
||||||
|
],
|
||||||
|
"forbidden_answer_patterns": [
|
||||||
|
"(?i)business_overview_route_template_v1|inventory_quality_events_profile",
|
||||||
|
"(?i)query_movements|query_documents|primitive|planner_|runtime_|pilot_",
|
||||||
|
"(?i)ликвидационная стоимость составляет|резерв составляет|подтвержденный резерв под неликвид"
|
||||||
|
],
|
||||||
|
"criticality": "critical",
|
||||||
|
"semantic_tags": [
|
||||||
|
"inventory_reserve_liquidation_quality",
|
||||||
|
"reviewed_inventory_quality_events",
|
||||||
|
"direct_answer_first",
|
||||||
|
"no_market_liquidation_overclaim"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step_id": "step_02_followup_inventory_liquidity_boundary",
|
||||||
|
"title": "Follow-up does not turn checked quality events into full liquidity claim",
|
||||||
|
"question": "А по этим же данным можно сказать, что склад ликвидный и неликвидов нет?",
|
||||||
|
"expected_catalog_alignment_status": "selected_matches_top",
|
||||||
|
"expected_catalog_chain_top_match": "business_overview",
|
||||||
|
"expected_catalog_selected_matches_top": true,
|
||||||
|
"allowed_reply_types": [
|
||||||
|
"partial_coverage",
|
||||||
|
"factual_with_explanation"
|
||||||
|
],
|
||||||
|
"required_answer_patterns_all": [
|
||||||
|
"(?i)склад|товар|остат",
|
||||||
|
"(?i)ликвид|неликвид",
|
||||||
|
"(?i)не подтвержд|нельзя|не значит|отдельн",
|
||||||
|
"(?i)списан|инвентаризац|переоцен|quality|событ"
|
||||||
|
],
|
||||||
|
"forbidden_answer_patterns": [
|
||||||
|
"(?i)business_overview_route_template_v1|inventory_quality_events_profile",
|
||||||
|
"(?i)query_movements|query_documents|primitive|planner_|runtime_|pilot_",
|
||||||
|
"(?i)склад ликвидный$|неликвидов нет$|ликвидность подтверждена"
|
||||||
|
],
|
||||||
|
"criticality": "critical",
|
||||||
|
"semantic_tags": [
|
||||||
|
"inventory_liquidity_boundary",
|
||||||
|
"followup_context_carryover",
|
||||||
|
"no_inventory_health_overclaim"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -283,6 +283,61 @@ const INVENTORY_ON_HAND_AS_OF_QUERY_TEMPLATE = `
|
||||||
УПОРЯДОЧИТЬ ПО
|
УПОРЯДОЧИТЬ ПО
|
||||||
Количество __ORDER_DIRECTION__
|
Количество __ORDER_DIRECTION__
|
||||||
`;
|
`;
|
||||||
|
const INVENTORY_QUALITY_EVENTS_QUERY_TEMPLATE = `
|
||||||
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
|
Списание.Дата КАК Период,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Списание.Ссылка) КАК Регистратор,
|
||||||
|
"Списание товаров" КАК ТипСобытия,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Списание.Организация) КАК Организация,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Списание.Склад) КАК Склад,
|
||||||
|
Списание.СуммаДокумента КАК Сумма,
|
||||||
|
Списание.Основание КАК Основание,
|
||||||
|
Списание.Комментарий КАК Комментарий
|
||||||
|
ИЗ
|
||||||
|
Документ.СписаниеТоваров КАК Списание
|
||||||
|
__WHERE_WRITE_OFF__
|
||||||
|
ОБЪЕДИНИТЬ ВСЕ
|
||||||
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
|
Оприходование.Дата КАК Период,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Оприходование.Ссылка) КАК Регистратор,
|
||||||
|
"Оприходование товаров" КАК ТипСобытия,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Оприходование.Организация) КАК Организация,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Оприходование.Склад) КАК Склад,
|
||||||
|
Оприходование.СуммаДокумента КАК Сумма,
|
||||||
|
Оприходование.Основание КАК Основание,
|
||||||
|
Оприходование.Комментарий КАК Комментарий
|
||||||
|
ИЗ
|
||||||
|
Документ.ОприходованиеТоваров КАК Оприходование
|
||||||
|
__WHERE_RECEIPT__
|
||||||
|
ОБЪЕДИНИТЬ ВСЕ
|
||||||
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
|
Инвентаризация.Дата КАК Период,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Инвентаризация.Ссылка) КАК Регистратор,
|
||||||
|
"Инвентаризация товаров на складе" КАК ТипСобытия,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Инвентаризация.Организация) КАК Организация,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Инвентаризация.Склад) КАК Склад,
|
||||||
|
0 КАК Сумма,
|
||||||
|
Инвентаризация.ПричинаПроведенияИнвентаризации КАК Основание,
|
||||||
|
Инвентаризация.Комментарий КАК Комментарий
|
||||||
|
ИЗ
|
||||||
|
Документ.ИнвентаризацияТоваровНаСкладе КАК Инвентаризация
|
||||||
|
__WHERE_INVENTORY_COUNT__
|
||||||
|
ОБЪЕДИНИТЬ ВСЕ
|
||||||
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
|
Переоценка.Дата КАК Период,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Переоценка.Ссылка) КАК Регистратор,
|
||||||
|
"Переоценка товаров в рознице" КАК ТипСобытия,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Переоценка.Организация) КАК Организация,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Переоценка.Склад) КАК Склад,
|
||||||
|
0 КАК Сумма,
|
||||||
|
"" КАК Основание,
|
||||||
|
Переоценка.Комментарий КАК Комментарий
|
||||||
|
ИЗ
|
||||||
|
Документ.ПереоценкаТоваровВРознице КАК Переоценка
|
||||||
|
__WHERE_REVALUATION__
|
||||||
|
УПОРЯДОЧИТЬ ПО
|
||||||
|
Период __ORDER_DIRECTION__
|
||||||
|
`;
|
||||||
const BANK_DOCS_QUERY_TEMPLATE = `
|
const BANK_DOCS_QUERY_TEMPLATE = `
|
||||||
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
БанкСписание.Дата КАК Период,
|
БанкСписание.Дата КАК Период,
|
||||||
|
|
@ -933,6 +988,16 @@ const BASE_RECIPES = [
|
||||||
account_scope_mode: "strict",
|
account_scope_mode: "strict",
|
||||||
query_template: "inventory_aging_by_purchase_date_profile"
|
query_template: "inventory_aging_by_purchase_date_profile"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
recipe_id: "address_inventory_quality_events_for_organization_v1",
|
||||||
|
intent: "inventory_quality_events_for_organization",
|
||||||
|
purpose: "Check posted inventory quality event documents: write-offs, stocktaking, receipt adjustments, and retail revaluation",
|
||||||
|
required_filters: [],
|
||||||
|
optional_filters: ["as_of_date", "period_from", "period_to", "organization", "warehouse", "limit", "sort"],
|
||||||
|
default_limit: 400,
|
||||||
|
account_scope_mode: "preferred",
|
||||||
|
query_template: "inventory_quality_events_profile"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
recipe_id: "address_open_contracts_confirmed_as_of_date_v1",
|
recipe_id: "address_open_contracts_confirmed_as_of_date_v1",
|
||||||
intent: "open_contracts_confirmed_as_of_date",
|
intent: "open_contracts_confirmed_as_of_date",
|
||||||
|
|
@ -1326,6 +1391,48 @@ function buildInventoryMovementQuery(filters, resolvedLimit, side) {
|
||||||
.replace("__WHERE_CLAUSE__", buildWhereClause(filters, "Движения.Период", [inventoryCondition, itemCondition].filter((item) => Boolean(item))))
|
.replace("__WHERE_CLAUSE__", buildWhereClause(filters, "Движения.Период", [inventoryCondition, itemCondition].filter((item) => Boolean(item))))
|
||||||
.replaceAll("__ORDER_DIRECTION__", resolveOrderDirection(filters.sort));
|
.replaceAll("__ORDER_DIRECTION__", resolveOrderDirection(filters.sort));
|
||||||
}
|
}
|
||||||
|
function buildWarehouseReferenceCondition(filters, fieldPaths) {
|
||||||
|
const warehouse = typeof filters.warehouse === "string" ? filters.warehouse.trim() : "";
|
||||||
|
if (!warehouse) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const tokens = Array.from(new Set(warehouse
|
||||||
|
.split(/[^A-Za-zА-Яа-яЁё0-9]+/u)
|
||||||
|
.map((token) => token.trim())
|
||||||
|
.filter((token) => token.length >= 3)
|
||||||
|
.filter((token) => !["склад", "warehouse"].includes(token.toLowerCase()))));
|
||||||
|
const effectiveTokens = tokens.length > 0 ? tokens : [warehouse];
|
||||||
|
const clauses = fieldPaths
|
||||||
|
.map((fieldPath) => String(fieldPath ?? "").trim())
|
||||||
|
.filter((fieldPath) => fieldPath.length > 0)
|
||||||
|
.map((fieldPath) => {
|
||||||
|
const tokenConditions = effectiveTokens.map((token) => {
|
||||||
|
const escapedToken = toQueryStringLiteral(token);
|
||||||
|
return `${fieldPath}.Наименование ПОДОБНО "%${escapedToken}%"`;
|
||||||
|
});
|
||||||
|
return tokenConditions.length === 1 ? tokenConditions[0] : `(${tokenConditions.join(" И ")})`;
|
||||||
|
});
|
||||||
|
if (clauses.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return clauses.length === 1 ? clauses[0] : `(${clauses.join(" ИЛИ ")})`;
|
||||||
|
}
|
||||||
|
function buildInventoryQualityDocumentWhereClause(filters, dateFieldPath, organizationFieldPath, warehouseFieldPath) {
|
||||||
|
return buildWhereClause(filters, dateFieldPath, [
|
||||||
|
`${dateFieldPath.replace(/\.Дата$/u, ".Проведен")} = ИСТИНА`,
|
||||||
|
buildOrganizationReferenceCondition(filters, [organizationFieldPath]),
|
||||||
|
buildWarehouseReferenceCondition(filters, [warehouseFieldPath])
|
||||||
|
].filter((item) => Boolean(item)));
|
||||||
|
}
|
||||||
|
function buildInventoryQualityEventsQuery(filters, resolvedLimit) {
|
||||||
|
return INVENTORY_QUALITY_EVENTS_QUERY_TEMPLATE
|
||||||
|
.replaceAll("__LIMIT__", String(resolvedLimit))
|
||||||
|
.replace("__WHERE_WRITE_OFF__", buildInventoryQualityDocumentWhereClause(filters, "Списание.Дата", "Списание.Организация", "Списание.Склад"))
|
||||||
|
.replace("__WHERE_RECEIPT__", buildInventoryQualityDocumentWhereClause(filters, "Оприходование.Дата", "Оприходование.Организация", "Оприходование.Склад"))
|
||||||
|
.replace("__WHERE_INVENTORY_COUNT__", buildInventoryQualityDocumentWhereClause(filters, "Инвентаризация.Дата", "Инвентаризация.Организация", "Инвентаризация.Склад"))
|
||||||
|
.replace("__WHERE_REVALUATION__", buildInventoryQualityDocumentWhereClause(filters, "Переоценка.Дата", "Переоценка.Организация", "Переоценка.Склад"))
|
||||||
|
.replaceAll("__ORDER_DIRECTION__", resolveOrderDirection(filters.sort));
|
||||||
|
}
|
||||||
function buildInventoryItemReferenceCondition(filters, fieldPaths) {
|
function buildInventoryItemReferenceCondition(filters, fieldPaths) {
|
||||||
const item = typeof filters.item === "string" ? filters.item.trim() : "";
|
const item = typeof filters.item === "string" ? filters.item.trim() : "";
|
||||||
if (!item) {
|
if (!item) {
|
||||||
|
|
@ -1599,6 +1706,7 @@ function maxLimitForIntent(intent) {
|
||||||
intent === "inventory_profitability_for_item" ||
|
intent === "inventory_profitability_for_item" ||
|
||||||
intent === "inventory_purchase_to_sale_chain" ||
|
intent === "inventory_purchase_to_sale_chain" ||
|
||||||
intent === "inventory_aging_by_purchase_date" ||
|
intent === "inventory_aging_by_purchase_date" ||
|
||||||
|
intent === "inventory_quality_events_for_organization" ||
|
||||||
intent === "open_contracts_confirmed_as_of_date" ||
|
intent === "open_contracts_confirmed_as_of_date" ||
|
||||||
intent === "list_contracts_by_counterparty" ||
|
intent === "list_contracts_by_counterparty" ||
|
||||||
intent === "list_documents_by_counterparty" ||
|
intent === "list_documents_by_counterparty" ||
|
||||||
|
|
@ -1790,6 +1898,8 @@ function buildAddressRecipePlan(recipe, filters) {
|
||||||
? buildInventoryPurchaseToSaleDocumentQuery(filters, resolvedLimit)
|
? buildInventoryPurchaseToSaleDocumentQuery(filters, resolvedLimit)
|
||||||
: recipe.query_template === "inventory_aging_by_purchase_date_profile"
|
: recipe.query_template === "inventory_aging_by_purchase_date_profile"
|
||||||
? buildInventoryMovementQuery(filters, resolvedLimit, "dt")
|
? buildInventoryMovementQuery(filters, resolvedLimit, "dt")
|
||||||
|
: recipe.query_template === "inventory_quality_events_profile"
|
||||||
|
? buildInventoryQualityEventsQuery(filters, resolvedLimit)
|
||||||
: recipe.query_template === "contracts_by_counterparty_profile"
|
: recipe.query_template === "contracts_by_counterparty_profile"
|
||||||
? CONTRACTS_BY_COUNTERPARTY_QUERY_TEMPLATE.replaceAll("__LIMIT__", String(resolvedLimit))
|
? CONTRACTS_BY_COUNTERPARTY_QUERY_TEMPLATE.replaceAll("__LIMIT__", String(resolvedLimit))
|
||||||
: recipe.query_template === "open_contracts_confirmed_as_of_balance_profile"
|
: recipe.query_template === "open_contracts_confirmed_as_of_balance_profile"
|
||||||
|
|
|
||||||
|
|
@ -393,6 +393,9 @@ function isVendorRiskBoundaryTurn(pilot) {
|
||||||
return action === "vendor_risk_procurement_boundary" || unsupported === "vendor_risk_procurement_boundary";
|
return action === "vendor_risk_procurement_boundary" || unsupported === "vendor_risk_procurement_boundary";
|
||||||
}
|
}
|
||||||
function businessOverviewInventoryUnknownLabel(overview) {
|
function businessOverviewInventoryUnknownLabel(overview) {
|
||||||
|
if (overview.inventory_quality_events) {
|
||||||
|
return "рыночная ликвидационная стоимость и управленческий резерв склада";
|
||||||
|
}
|
||||||
if (overview.inventory_staleness_risk_proxy) {
|
if (overview.inventory_staleness_risk_proxy) {
|
||||||
return "резервы/списания/ликвидационная стоимость склада";
|
return "резервы/списания/ликвидационная стоимость склада";
|
||||||
}
|
}
|
||||||
|
|
@ -621,6 +624,24 @@ function businessOverviewVendorProcurementQualityText(overview) {
|
||||||
}
|
}
|
||||||
return `Procurement-concentration route за ${period} отработал по исходящим платежам на ${total}, но надежной небанковской концентрации поставщика по найденным строкам не хватает.${contractText} Полный vendor-risk аудит не подтвержден.`;
|
return `Procurement-concentration route за ${period} отработал по исходящим платежам на ${total}, но надежной небанковской концентрации поставщика по найденным строкам не хватает.${contractText} Полный vendor-risk аудит не подтвержден.`;
|
||||||
}
|
}
|
||||||
|
function businessOverviewInventoryQualityEventsText(overview) {
|
||||||
|
const quality = overview.inventory_quality_events;
|
||||||
|
if (!quality) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const period = quality.period_scope ?? "проверенное окно";
|
||||||
|
const organization = overview.organization_scope ? ` по организации ${overview.organization_scope}` : "";
|
||||||
|
const eventWindow = quality.first_event_date && quality.latest_event_date
|
||||||
|
? ` Окно найденных событий: ${quality.first_event_date} - ${quality.latest_event_date}.`
|
||||||
|
: "";
|
||||||
|
if (quality.evidence_status === "reviewed_no_quality_events_found") {
|
||||||
|
return `Коротко: проверил складские документы списания, оприходования, инвентаризации и переоценки${organization} за ${period}; подтвержденных событий списания/корректировки/инвентаризации/переоценки не найдено. Это сильный отрицательный сигнал по доступным документам 1С, но не рыночная ликвидационная стоимость и не управленческий резерв под неликвиды.`;
|
||||||
|
}
|
||||||
|
if (quality.evidence_status === "reviewed_inventory_control_events_only") {
|
||||||
|
return `Коротко: проверил складские quality-события${organization} за ${period}; списаний и оприходований/корректировок с суммой не найдено, но есть инвентаризации ${quality.inventory_count_rows} и переоценки ${quality.revaluation_rows}.${eventWindow} Это контрольные складские документы, а не подтвержденный резерв или рыночная ликвидационная оценка.`;
|
||||||
|
}
|
||||||
|
return `Коротко: проверил складские quality-события${organization} за ${period}; списаний ${quality.writeoff_rows} на ${quality.writeoff_amount_human_ru}, оприходований/корректировок ${quality.receipt_adjustment_rows} на ${quality.receipt_adjustment_amount_human_ru}, инвентаризаций ${quality.inventory_count_rows}, переоценок ${quality.revaluation_rows}.${eventWindow} Это подтвержденные документы 1С по складским событиям, но не самостоятельная рыночная ликвидационная стоимость и не расчет управленческого резерва.`;
|
||||||
|
}
|
||||||
function headlineFor(mode, pilot) {
|
function headlineFor(mode, pilot) {
|
||||||
const askedMonthlyBreakdown = pilot.derived_bidirectional_value_flow?.aggregation_axis === "month" ||
|
const askedMonthlyBreakdown = pilot.derived_bidirectional_value_flow?.aggregation_axis === "month" ||
|
||||||
pilot.derived_value_flow?.aggregation_axis === "month";
|
pilot.derived_value_flow?.aggregation_axis === "month";
|
||||||
|
|
@ -653,6 +674,10 @@ function headlineFor(mode, pilot) {
|
||||||
return "Нельзя точно определить, какая дебиторка просрочена, по текущему срезу 1С; есть только debt-quality proxy, но нет проверенного due-date маршрута по договорам, срокам оплаты и погашению расчетов.";
|
return "Нельзя точно определить, какая дебиторка просрочена, по текущему срезу 1С; есть только debt-quality proxy, но нет проверенного due-date маршрута по договорам, срокам оплаты и погашению расчетов.";
|
||||||
}
|
}
|
||||||
if (isInventoryReserveBoundaryTurn(pilot)) {
|
if (isInventoryReserveBoundaryTurn(pilot)) {
|
||||||
|
const inventoryQualityEventsText = businessOverviewInventoryQualityEventsText(overview);
|
||||||
|
if (inventoryQualityEventsText) {
|
||||||
|
return inventoryQualityEventsText;
|
||||||
|
}
|
||||||
const inventoryBasis = overview.inventory_staleness_risk_proxy
|
const inventoryBasis = overview.inventory_staleness_risk_proxy
|
||||||
? "есть только складской staleness-risk proxy по найденным строкам"
|
? "есть только складской staleness-risk proxy по найденным строкам"
|
||||||
: overview.inventory_position || overview.inventory_turnover_proxy
|
: overview.inventory_position || overview.inventory_turnover_proxy
|
||||||
|
|
@ -724,6 +749,9 @@ function headlineFor(mode, pilot) {
|
||||||
if (overview.inventory_staleness_risk_proxy) {
|
if (overview.inventory_staleness_risk_proxy) {
|
||||||
families.push("staleness risk proxy склада");
|
families.push("staleness risk proxy склада");
|
||||||
}
|
}
|
||||||
|
if (overview.inventory_quality_events) {
|
||||||
|
families.push("складские quality-события");
|
||||||
|
}
|
||||||
const unknownFamilies = overview.accounting_financial_result
|
const unknownFamilies = overview.accounting_financial_result
|
||||||
? ["аудированная/юридически подтвержденная прибыль"]
|
? ["аудированная/юридически подтвержденная прибыль"]
|
||||||
: [overview.trading_margin_proxy ? "чистая прибыль/точная маржа" : "прибыль/маржа"];
|
: [overview.trading_margin_proxy ? "чистая прибыль/точная маржа" : "прибыль/маржа"];
|
||||||
|
|
@ -946,6 +974,9 @@ function buildMustNotClaim(pilot) {
|
||||||
claims.push("Do not present an inventory snapshot or purchase-date aging signal as turnover, obsolescence, liquidation value, or full inventory health.");
|
claims.push("Do not present an inventory snapshot or purchase-date aging signal as turnover, obsolescence, liquidation value, or full inventory health.");
|
||||||
claims.push("Do not present business overview inventory turnover proxy as full inventory liquidity, FIFO turnover, obsolescence analysis, or liquidation value.");
|
claims.push("Do not present business overview inventory turnover proxy as full inventory liquidity, FIFO turnover, obsolescence analysis, or liquidation value.");
|
||||||
claims.push("Do not present business overview inventory staleness risk proxy as confirmed obsolete stock, reserve, write-off, or liquidation value.");
|
claims.push("Do not present business overview inventory staleness risk proxy as confirmed obsolete stock, reserve, write-off, or liquidation value.");
|
||||||
|
if (pilot.derived_business_overview?.inventory_quality_events) {
|
||||||
|
claims.push("Do not present reviewed inventory quality events as confirmed obsolete stock, reserve policy, market liquidation value, management reserve, or full inventory health.");
|
||||||
|
}
|
||||||
if (pilot.derived_business_overview?.top_customers?.some(isFinancialInstitutionBucket) ||
|
if (pilot.derived_business_overview?.top_customers?.some(isFinancialInstitutionBucket) ||
|
||||||
pilot.derived_business_overview?.top_suppliers?.some(isFinancialInstitutionBucket)) {
|
pilot.derived_business_overview?.top_suppliers?.some(isFinancialInstitutionBucket)) {
|
||||||
claims.push("Do not present bank-like counterparties as ordinary customers, suppliers, revenue, procurement dependency, or business quality evidence without payment-purpose/contract proof.");
|
claims.push("Do not present bank-like counterparties as ordinary customers, suppliers, revenue, procurement dependency, or business quality evidence without payment-purpose/contract proof.");
|
||||||
|
|
@ -1436,6 +1467,10 @@ function derivedBusinessOverviewConfirmedLines(pilot) {
|
||||||
const proxy = overview.inventory_staleness_risk_proxy;
|
const proxy = overview.inventory_staleness_risk_proxy;
|
||||||
lines.push(`Staleness risk proxy склада на ${proxy.as_of_date}: самая ранняя дата закупочного сигнала ${proxy.oldest_purchase_date}, возраст ${proxy.max_purchase_age_days} дн., sales-to-stock ${proxy.sales_to_stock_amount_ratio}x, оценка ${inventoryStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`);
|
lines.push(`Staleness risk proxy склада на ${proxy.as_of_date}: самая ранняя дата закупочного сигнала ${proxy.oldest_purchase_date}, возраст ${proxy.max_purchase_age_days} дн., sales-to-stock ${proxy.sales_to_stock_amount_ratio}x, оценка ${inventoryStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`);
|
||||||
}
|
}
|
||||||
|
const inventoryQualityEventsText = businessOverviewInventoryQualityEventsText(overview);
|
||||||
|
if (inventoryQualityEventsText) {
|
||||||
|
lines.push(inventoryQualityEventsText.replace(/^Коротко:\s*/u, ""));
|
||||||
|
}
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
function businessOverviewCashSynthesisLine(overview) {
|
function businessOverviewCashSynthesisLine(overview) {
|
||||||
|
|
@ -1603,6 +1638,15 @@ function businessOverviewRiskSynthesisLine(overview) {
|
||||||
if (overview.inventory_staleness_risk_proxy) {
|
if (overview.inventory_staleness_risk_proxy) {
|
||||||
signals.push(`staleness risk proxy склада: ${inventoryStalenessRiskBandRu(overview.inventory_staleness_risk_proxy.risk_band)}, возраст ${overview.inventory_staleness_risk_proxy.max_purchase_age_days} дн.`);
|
signals.push(`staleness risk proxy склада: ${inventoryStalenessRiskBandRu(overview.inventory_staleness_risk_proxy.risk_band)}, возраст ${overview.inventory_staleness_risk_proxy.max_purchase_age_days} дн.`);
|
||||||
}
|
}
|
||||||
|
if (overview.inventory_quality_events) {
|
||||||
|
const quality = overview.inventory_quality_events;
|
||||||
|
if (quality.evidence_status === "reviewed_no_quality_events_found") {
|
||||||
|
signals.push("складские quality-события: документы списания, оприходования, инвентаризации и переоценки проверены, подтвержденных событий не найдено");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
signals.push(`складские quality-события: списаний ${quality.writeoff_rows} на ${quality.writeoff_amount_human_ru}, оприходований/корректировок ${quality.receipt_adjustment_rows} на ${quality.receipt_adjustment_amount_human_ru}, инвентаризаций ${quality.inventory_count_rows}, переоценок ${quality.revaluation_rows}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
return signals.length > 0
|
return signals.length > 0
|
||||||
? `Риски и контуры внимания по подтвержденным данным: ${signals.join("; ")}.`
|
? `Риски и контуры внимания по подтвержденным данным: ${signals.join("; ")}.`
|
||||||
: null;
|
: null;
|
||||||
|
|
@ -1616,7 +1660,8 @@ function businessOverviewExecutiveVerdictLine(overview) {
|
||||||
overview.debt_staleness_risk_proxy ||
|
overview.debt_staleness_risk_proxy ||
|
||||||
overview.inventory_position ||
|
overview.inventory_position ||
|
||||||
overview.inventory_turnover_proxy ||
|
overview.inventory_turnover_proxy ||
|
||||||
overview.inventory_staleness_risk_proxy);
|
overview.inventory_staleness_risk_proxy ||
|
||||||
|
overview.inventory_quality_events);
|
||||||
const hasOperationalProfileSignal = Boolean(overview.document_activity_profile || overview.counterparty_profile || overview.contract_usage_profile);
|
const hasOperationalProfileSignal = Boolean(overview.document_activity_profile || overview.counterparty_profile || overview.contract_usage_profile);
|
||||||
const hasExtraSignals = hasTaxDebtInventorySignals || hasOperationalProfileSignal;
|
const hasExtraSignals = hasTaxDebtInventorySignals || hasOperationalProfileSignal;
|
||||||
if (!hasCash && !hasExtraSignals) {
|
if (!hasCash && !hasExtraSignals) {
|
||||||
|
|
@ -1750,6 +1795,10 @@ function buildAssistantMcpDiscoveryAnswerDraft(pilot) {
|
||||||
if (pilot.derived_business_overview?.inventory_staleness_risk_proxy) {
|
if (pilot.derived_business_overview?.inventory_staleness_risk_proxy) {
|
||||||
pushReason(reasonCodes, "answer_contains_business_overview_inventory_staleness_risk_proxy");
|
pushReason(reasonCodes, "answer_contains_business_overview_inventory_staleness_risk_proxy");
|
||||||
}
|
}
|
||||||
|
if (pilot.derived_business_overview?.inventory_quality_events) {
|
||||||
|
pushReason(reasonCodes, "answer_contains_business_overview_inventory_quality_events");
|
||||||
|
pushReason(reasonCodes, `answer_contains_business_overview_inventory_quality_events_${pilot.derived_business_overview.inventory_quality_events.evidence_status}`);
|
||||||
|
}
|
||||||
if (pilot.derived_business_overview?.missing_proof_families?.length) {
|
if (pilot.derived_business_overview?.missing_proof_families?.length) {
|
||||||
pushReason(reasonCodes, "answer_contains_business_overview_missing_proof_ledger");
|
pushReason(reasonCodes, "answer_contains_business_overview_missing_proof_ledger");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,16 @@ function shouldRunDebtDueDateAgingProbe(planner) {
|
||||||
.join(" ");
|
.join(" ");
|
||||||
return /(?:debt_due_date_boundary|due[-_ ]?date|overdue|aging|просроч|срок\s+оплат|дебиторк|кредиторск)/iu.test(combined);
|
return /(?:debt_due_date_boundary|due[-_ ]?date|overdue|aging|просроч|срок\s+оплат|дебиторк|кредиторск)/iu.test(combined);
|
||||||
}
|
}
|
||||||
|
function shouldRunInventoryQualityEventsProbe(planner) {
|
||||||
|
const actionFamily = toNonEmptyString(planner.data_need_graph?.action_family);
|
||||||
|
const turnActionFamily = toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.asked_action_family);
|
||||||
|
const unsupportedFamily = toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.unsupported_but_understood_family);
|
||||||
|
const proofExpectation = toNonEmptyString(planner.data_need_graph?.proof_expectation);
|
||||||
|
const combined = [actionFamily, turnActionFamily, unsupportedFamily, proofExpectation]
|
||||||
|
.filter((item) => Boolean(item))
|
||||||
|
.join(" ");
|
||||||
|
return /(?:inventory_reserve|reserve_liquidation|liquidation|write[-_ ]?off|obsolete|obsolescence|inventory_reserve_liquidation_quality|резерв|списан|ликвидац|неликвид|обесцен)/iu.test(combined);
|
||||||
|
}
|
||||||
function buildBusinessOverviewInventoryFilters(planner) {
|
function buildBusinessOverviewInventoryFilters(planner) {
|
||||||
const meaning = planner.discovery_plan.turn_meaning_ref;
|
const meaning = planner.discovery_plan.turn_meaning_ref;
|
||||||
const organization = toNonEmptyString(meaning?.explicit_organization_scope);
|
const organization = toNonEmptyString(meaning?.explicit_organization_scope);
|
||||||
|
|
@ -3021,6 +3031,69 @@ function deriveBusinessOverviewInventoryStalenessRiskProxy(input) {
|
||||||
inference_basis: "purchase_date_age_and_sales_to_stock_proxy_confirmed_1c_rows"
|
inference_basis: "purchase_date_age_and_sales_to_stock_proxy_confirmed_1c_rows"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
function rowInventoryQualityEventType(row) {
|
||||||
|
return rowTextValue(row, ["ТипСобытия", "EventType", "event_type", "Регистратор", "Registrator", "registrator"]) ?? "";
|
||||||
|
}
|
||||||
|
function deriveBusinessOverviewInventoryQualityEvents(input) {
|
||||||
|
const result = input.inventoryQualityEventsResult;
|
||||||
|
if (!result || result.error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let writeoffRows = 0;
|
||||||
|
let writeoffAmount = 0;
|
||||||
|
let receiptAdjustmentRows = 0;
|
||||||
|
let receiptAdjustmentAmount = 0;
|
||||||
|
let inventoryCountRows = 0;
|
||||||
|
let revaluationRows = 0;
|
||||||
|
const eventDates = [];
|
||||||
|
for (const row of result.rows) {
|
||||||
|
const eventType = rowInventoryQualityEventType(row);
|
||||||
|
const amount = rowAmountValue(row) ?? 0;
|
||||||
|
const date = rowDateValue(row);
|
||||||
|
if (date) {
|
||||||
|
eventDates.push(date);
|
||||||
|
}
|
||||||
|
if (/списан|write[-_ ]?off/iu.test(eventType)) {
|
||||||
|
writeoffRows += 1;
|
||||||
|
writeoffAmount += amount;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (/оприход|receipt|positive/i.test(eventType)) {
|
||||||
|
receiptAdjustmentRows += 1;
|
||||||
|
receiptAdjustmentAmount += amount;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (/инвентаризац|stocktaking|inventory count/i.test(eventType)) {
|
||||||
|
inventoryCountRows += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (/переоцен|revaluation/i.test(eventType)) {
|
||||||
|
revaluationRows += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const sortedDates = eventDates.sort((left, right) => left.localeCompare(right));
|
||||||
|
const evidenceStatus = writeoffRows > 0 || receiptAdjustmentRows > 0
|
||||||
|
? "reviewed_writeoff_or_adjustment_events_found"
|
||||||
|
: inventoryCountRows > 0 || revaluationRows > 0
|
||||||
|
? "reviewed_inventory_control_events_only"
|
||||||
|
: "reviewed_no_quality_events_found";
|
||||||
|
return {
|
||||||
|
period_scope: input.periodScope,
|
||||||
|
rows_matched: result.matched_rows,
|
||||||
|
writeoff_rows: writeoffRows,
|
||||||
|
writeoff_amount: writeoffAmount,
|
||||||
|
writeoff_amount_human_ru: formatAmountHumanRu(writeoffAmount),
|
||||||
|
receipt_adjustment_rows: receiptAdjustmentRows,
|
||||||
|
receipt_adjustment_amount: receiptAdjustmentAmount,
|
||||||
|
receipt_adjustment_amount_human_ru: formatAmountHumanRu(receiptAdjustmentAmount),
|
||||||
|
inventory_count_rows: inventoryCountRows,
|
||||||
|
revaluation_rows: revaluationRows,
|
||||||
|
first_event_date: sortedDates[0] ?? null,
|
||||||
|
latest_event_date: sortedDates[sortedDates.length - 1] ?? null,
|
||||||
|
evidence_status: evidenceStatus,
|
||||||
|
inference_basis: "inventory_quality_documents_confirmed_1c_rows"
|
||||||
|
};
|
||||||
|
}
|
||||||
function deriveBusinessOverviewVendorProcurementQuality(input) {
|
function deriveBusinessOverviewVendorProcurementQuality(input) {
|
||||||
if (!input.rankedOutgoing ||
|
if (!input.rankedOutgoing ||
|
||||||
input.rankedOutgoing.ranked_values.length <= 0 ||
|
input.rankedOutgoing.ranked_values.length <= 0 ||
|
||||||
|
|
@ -3109,10 +3182,10 @@ function buildBusinessOverviewMissingProofFamilies(input) {
|
||||||
must_not_claim: "confirmed_overdue_debt_credit_risk_or_due_date_aging"
|
must_not_claim: "confirmed_overdue_debt_credit_risk_or_due_date_aging"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (missing.has("inventory_position") ||
|
if ((missing.has("inventory_position") ||
|
||||||
missing.has("inventory_turnover_quality") ||
|
missing.has("inventory_turnover_quality") ||
|
||||||
missing.has("inventory_liquidity_quality") ||
|
missing.has("inventory_liquidity_quality") ||
|
||||||
missing.has("inventory_reserve_liquidation_quality")) {
|
missing.has("inventory_reserve_liquidation_quality")) && !input.inventoryQualityEvents) {
|
||||||
pushUnique({
|
pushUnique({
|
||||||
family: "inventory_reserve_liquidation_quality",
|
family: "inventory_reserve_liquidation_quality",
|
||||||
current_status: input.inventoryStalenessRiskProxy
|
current_status: input.inventoryStalenessRiskProxy
|
||||||
|
|
@ -3195,6 +3268,10 @@ function deriveBusinessOverview(input) {
|
||||||
inventoryPosition,
|
inventoryPosition,
|
||||||
inventoryTurnoverProxy
|
inventoryTurnoverProxy
|
||||||
});
|
});
|
||||||
|
const inventoryQualityEvents = deriveBusinessOverviewInventoryQualityEvents({
|
||||||
|
inventoryQualityEventsResult: input.inventoryQualityEventsResult,
|
||||||
|
periodScope: input.periodScope
|
||||||
|
});
|
||||||
const vendorProcurementQuality = deriveBusinessOverviewVendorProcurementQuality({
|
const vendorProcurementQuality = deriveBusinessOverviewVendorProcurementQuality({
|
||||||
rankedOutgoing,
|
rankedOutgoing,
|
||||||
outgoing,
|
outgoing,
|
||||||
|
|
@ -3219,6 +3296,7 @@ function deriveBusinessOverview(input) {
|
||||||
Boolean(inventoryPosition),
|
Boolean(inventoryPosition),
|
||||||
Boolean(inventoryTurnoverProxy),
|
Boolean(inventoryTurnoverProxy),
|
||||||
Boolean(inventoryStalenessRiskProxy),
|
Boolean(inventoryStalenessRiskProxy),
|
||||||
|
Boolean(inventoryQualityEvents),
|
||||||
Boolean(vendorProcurementQuality)
|
Boolean(vendorProcurementQuality)
|
||||||
].filter(Boolean).length;
|
].filter(Boolean).length;
|
||||||
if (checkedSignalCount <= 0) {
|
if (checkedSignalCount <= 0) {
|
||||||
|
|
@ -3232,7 +3310,9 @@ function deriveBusinessOverview(input) {
|
||||||
debtDueDateAging ? null : debtOpenSettlementQuality ? "debt_due_date_aging_quality" : "debt_open_settlement_quality",
|
debtDueDateAging ? null : debtOpenSettlementQuality ? "debt_due_date_aging_quality" : "debt_open_settlement_quality",
|
||||||
taxPosition ? null : "tax_position",
|
taxPosition ? null : "tax_position",
|
||||||
inventoryPosition
|
inventoryPosition
|
||||||
? inventoryStalenessRiskProxy
|
? inventoryQualityEvents
|
||||||
|
? null
|
||||||
|
: inventoryStalenessRiskProxy
|
||||||
? "inventory_reserve_liquidation_quality"
|
? "inventory_reserve_liquidation_quality"
|
||||||
: inventoryTurnoverProxy
|
: inventoryTurnoverProxy
|
||||||
? "inventory_liquidity_quality"
|
? "inventory_liquidity_quality"
|
||||||
|
|
@ -3250,6 +3330,7 @@ function deriveBusinessOverview(input) {
|
||||||
inventoryPosition,
|
inventoryPosition,
|
||||||
inventoryTurnoverProxy,
|
inventoryTurnoverProxy,
|
||||||
inventoryStalenessRiskProxy,
|
inventoryStalenessRiskProxy,
|
||||||
|
inventoryQualityEvents,
|
||||||
vendorProcurementQuality,
|
vendorProcurementQuality,
|
||||||
hasSupplierConcentrationSignal: (rankedOutgoing?.ranked_values.length ?? 0) > 0
|
hasSupplierConcentrationSignal: (rankedOutgoing?.ranked_values.length ?? 0) > 0
|
||||||
});
|
});
|
||||||
|
|
@ -3275,6 +3356,7 @@ function deriveBusinessOverview(input) {
|
||||||
inventory_position: inventoryPosition,
|
inventory_position: inventoryPosition,
|
||||||
inventory_turnover_proxy: inventoryTurnoverProxy,
|
inventory_turnover_proxy: inventoryTurnoverProxy,
|
||||||
inventory_staleness_risk_proxy: inventoryStalenessRiskProxy,
|
inventory_staleness_risk_proxy: inventoryStalenessRiskProxy,
|
||||||
|
inventory_quality_events: inventoryQualityEvents,
|
||||||
document_activity_profile: documentActivityProfile,
|
document_activity_profile: documentActivityProfile,
|
||||||
counterparty_profile: counterpartyProfile,
|
counterparty_profile: counterpartyProfile,
|
||||||
contract_usage_profile: contractUsageProfile,
|
contract_usage_profile: contractUsageProfile,
|
||||||
|
|
@ -3283,7 +3365,7 @@ function deriveBusinessOverview(input) {
|
||||||
checked_signal_count: checkedSignalCount,
|
checked_signal_count: checkedSignalCount,
|
||||||
missing_signal_families: missingSignalFamilies,
|
missing_signal_families: missingSignalFamilies,
|
||||||
missing_proof_families: missingProofFamilies,
|
missing_proof_families: missingProofFamilies,
|
||||||
inference_basis: hasBusinessOverviewProfileSignal || inventoryPosition || accountingFinancialResult
|
inference_basis: hasBusinessOverviewProfileSignal || inventoryPosition || inventoryQualityEvents || accountingFinancialResult
|
||||||
? "business_overview_from_confirmed_1c_multi_family_rows"
|
? "business_overview_from_confirmed_1c_multi_family_rows"
|
||||||
: debtOpenSettlementQuality || debtDueDateAging
|
: debtOpenSettlementQuality || debtDueDateAging
|
||||||
? "business_overview_from_confirmed_1c_multi_family_rows"
|
? "business_overview_from_confirmed_1c_multi_family_rows"
|
||||||
|
|
@ -3343,6 +3425,9 @@ function summarizeBusinessOverviewRows(input) {
|
||||||
if (input.inventoryAgingResult && !input.inventoryAgingResult.error) {
|
if (input.inventoryAgingResult && !input.inventoryAgingResult.error) {
|
||||||
parts.push(`${input.inventoryAgingResult.fetched_rows} inventory aging rows fetched, ${input.inventoryAgingResult.matched_rows} matched`);
|
parts.push(`${input.inventoryAgingResult.fetched_rows} inventory aging rows fetched, ${input.inventoryAgingResult.matched_rows} matched`);
|
||||||
}
|
}
|
||||||
|
if (input.inventoryQualityEventsResult && !input.inventoryQualityEventsResult.error) {
|
||||||
|
parts.push(`${input.inventoryQualityEventsResult.fetched_rows} inventory quality-event rows fetched, ${input.inventoryQualityEventsResult.matched_rows} matched`);
|
||||||
|
}
|
||||||
return parts.length > 0 ? parts.join("; ") : null;
|
return parts.length > 0 ? parts.join("; ") : null;
|
||||||
}
|
}
|
||||||
function buildBusinessOverviewConfirmedFacts(derived) {
|
function buildBusinessOverviewConfirmedFacts(derived) {
|
||||||
|
|
@ -3511,6 +3596,18 @@ function buildBusinessOverviewConfirmedFacts(derived) {
|
||||||
const proxy = derived.inventory_staleness_risk_proxy;
|
const proxy = derived.inventory_staleness_risk_proxy;
|
||||||
facts.push(`Staleness risk proxy склада на ${proxy.as_of_date}: самая ранняя дата закупочного сигнала ${proxy.oldest_purchase_date}, возраст ${proxy.max_purchase_age_days} дн., sales-to-stock ${proxy.sales_to_stock_amount_ratio}x, оценка ${inventoryStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`);
|
facts.push(`Staleness risk proxy склада на ${proxy.as_of_date}: самая ранняя дата закупочного сигнала ${proxy.oldest_purchase_date}, возраст ${proxy.max_purchase_age_days} дн., sales-to-stock ${proxy.sales_to_stock_amount_ratio}x, оценка ${inventoryStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`);
|
||||||
}
|
}
|
||||||
|
if (derived.inventory_quality_events) {
|
||||||
|
const quality = derived.inventory_quality_events;
|
||||||
|
const eventWindow = quality.first_event_date && quality.latest_event_date
|
||||||
|
? ` Окно найденных событий: ${quality.first_event_date} — ${quality.latest_event_date}.`
|
||||||
|
: "";
|
||||||
|
if (quality.evidence_status === "reviewed_no_quality_events_found") {
|
||||||
|
facts.push(`Reviewed inventory quality route проверил складские документы списания, оприходования, инвентаризации и переоценки${period}: подтвержденных событий не найдено. Это проверенный отрицательный результат по доступным документам, но не рыночная ликвидационная оценка и не управленческий резерв.`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
facts.push(`Reviewed inventory quality route проверил складские документы${period}: списаний ${quality.writeoff_rows} на ${quality.writeoff_amount_human_ru}, оприходований/корректировок ${quality.receipt_adjustment_rows} на ${quality.receipt_adjustment_amount_human_ru}, инвентаризаций ${quality.inventory_count_rows}, переоценок ${quality.revaluation_rows}.${eventWindow} Это подтвержденные документы 1С, но не самостоятельная рыночная ликвидационная стоимость.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
return facts;
|
return facts;
|
||||||
}
|
}
|
||||||
function buildBusinessOverviewInferredFacts(derived) {
|
function buildBusinessOverviewInferredFacts(derived) {
|
||||||
|
|
@ -4218,6 +4315,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||||
let contractUsageProfileResult = null;
|
let contractUsageProfileResult = null;
|
||||||
let inventoryOnHandResult = null;
|
let inventoryOnHandResult = null;
|
||||||
let inventoryAgingResult = null;
|
let inventoryAgingResult = null;
|
||||||
|
let inventoryQualityEventsResult = null;
|
||||||
const valueFilters = buildValueFlowFilters(planner);
|
const valueFilters = buildValueFlowFilters(planner);
|
||||||
const lifecycleFilters = buildLifecycleFilters(planner);
|
const lifecycleFilters = buildLifecycleFilters(planner);
|
||||||
const profileFilters = buildBusinessOverviewProfileFilters(planner);
|
const profileFilters = buildBusinessOverviewProfileFilters(planner);
|
||||||
|
|
@ -4227,6 +4325,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||||
const debtFilters = buildBusinessOverviewDebtFilters(planner);
|
const debtFilters = buildBusinessOverviewDebtFilters(planner);
|
||||||
const debtDueDateAgingProbeEnabled = shouldRunDebtDueDateAgingProbe(planner);
|
const debtDueDateAgingProbeEnabled = shouldRunDebtDueDateAgingProbe(planner);
|
||||||
const inventoryFilters = buildBusinessOverviewInventoryFilters(planner);
|
const inventoryFilters = buildBusinessOverviewInventoryFilters(planner);
|
||||||
|
const inventoryQualityEventsProbeEnabled = shouldRunInventoryQualityEventsProbe(planner);
|
||||||
const debtAsOfDate = toNonEmptyString(debtFilters?.as_of_date);
|
const debtAsOfDate = toNonEmptyString(debtFilters?.as_of_date);
|
||||||
const inventoryAsOfDate = toNonEmptyString(inventoryFilters?.as_of_date);
|
const inventoryAsOfDate = toNonEmptyString(inventoryFilters?.as_of_date);
|
||||||
const incomingSelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("customer_revenue_and_payments", valueFilters);
|
const incomingSelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("customer_revenue_and_payments", valueFilters);
|
||||||
|
|
@ -4262,6 +4361,9 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||||
const inventoryAgingSelection = inventoryFilters
|
const inventoryAgingSelection = inventoryFilters
|
||||||
? (0, addressRecipeCatalog_1.selectAddressRecipe)("inventory_aging_by_purchase_date", inventoryFilters)
|
? (0, addressRecipeCatalog_1.selectAddressRecipe)("inventory_aging_by_purchase_date", inventoryFilters)
|
||||||
: null;
|
: null;
|
||||||
|
const inventoryQualityEventsSelection = inventoryQualityEventsProbeEnabled
|
||||||
|
? (0, addressRecipeCatalog_1.selectAddressRecipe)("inventory_quality_events_for_organization", inventoryFilters ?? buildBusinessOverviewProfileFilters(planner))
|
||||||
|
: null;
|
||||||
if (!incomingSelection.selected_recipe || !outgoingSelection.selected_recipe || !lifecycleSelection.selected_recipe) {
|
if (!incomingSelection.selected_recipe || !outgoingSelection.selected_recipe || !lifecycleSelection.selected_recipe) {
|
||||||
pushReason(reasonCodes, "pilot_business_overview_recipe_not_available");
|
pushReason(reasonCodes, "pilot_business_overview_recipe_not_available");
|
||||||
const missing = [
|
const missing = [
|
||||||
|
|
@ -4389,6 +4491,16 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||||
pushReason(reasonCodes, "pilot_business_overview_inventory_recipe_not_available");
|
pushReason(reasonCodes, "pilot_business_overview_inventory_recipe_not_available");
|
||||||
pushUnique(queryLimitations, "Business overview inventory-position probe requires an executable inventory on-hand as-of-date recipe");
|
pushUnique(queryLimitations, "Business overview inventory-position probe requires an executable inventory on-hand as-of-date recipe");
|
||||||
}
|
}
|
||||||
|
if (inventoryQualityEventsSelection?.selected_recipe) {
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_recipe_selected");
|
||||||
|
}
|
||||||
|
else if (!inventoryQualityEventsProbeEnabled) {
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_probe_skipped_without_boundary_need");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_recipe_not_available");
|
||||||
|
pushUnique(queryLimitations, "Business overview inventory quality probe requires an executable inventory quality-events recipe");
|
||||||
|
}
|
||||||
for (const step of dryRun.execution_steps) {
|
for (const step of dryRun.execution_steps) {
|
||||||
if (step.primitive_id === "query_movements") {
|
if (step.primitive_id === "query_movements") {
|
||||||
const incomingExecution = await executeCoverageAwareValueFlowQuery({
|
const incomingExecution = await executeCoverageAwareValueFlowQuery({
|
||||||
|
|
@ -4622,6 +4734,16 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||||
});
|
});
|
||||||
probeResults.push(queryResultToProbeResult(step.primitive_id, contractUsageProfileResult));
|
probeResults.push(queryResultToProbeResult(step.primitive_id, contractUsageProfileResult));
|
||||||
}
|
}
|
||||||
|
if (inventoryQualityEventsSelection?.selected_recipe) {
|
||||||
|
const inventoryQualityEventsFilters = inventoryFilters ?? buildBusinessOverviewProfileFilters(planner);
|
||||||
|
const inventoryQualityEventsPlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(inventoryQualityEventsSelection.selected_recipe, inventoryQualityEventsFilters);
|
||||||
|
inventoryQualityEventsResult = await runtimeDeps.executeAddressMcpQuery({
|
||||||
|
query: inventoryQualityEventsPlan.query,
|
||||||
|
limit: inventoryQualityEventsPlan.limit,
|
||||||
|
account_scope: inventoryQualityEventsPlan.account_scope
|
||||||
|
});
|
||||||
|
probeResults.push(queryResultToProbeResult(step.primitive_id, inventoryQualityEventsResult));
|
||||||
|
}
|
||||||
if (lifecycleResult.error) {
|
if (lifecycleResult.error) {
|
||||||
pushUnique(queryLimitations, lifecycleResult.error);
|
pushUnique(queryLimitations, lifecycleResult.error);
|
||||||
pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_error");
|
pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_error");
|
||||||
|
|
@ -4657,6 +4779,13 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||||
else if (contractUsageProfileResult) {
|
else if (contractUsageProfileResult) {
|
||||||
pushReason(reasonCodes, "pilot_business_overview_contract_usage_profile_query_mcp_executed");
|
pushReason(reasonCodes, "pilot_business_overview_contract_usage_profile_query_mcp_executed");
|
||||||
}
|
}
|
||||||
|
if (inventoryQualityEventsResult?.error) {
|
||||||
|
pushUnique(queryLimitations, inventoryQualityEventsResult.error);
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_query_mcp_error");
|
||||||
|
}
|
||||||
|
else if (inventoryQualityEventsResult) {
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_query_mcp_executed");
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
skippedPrimitives.push(step.primitive_id);
|
skippedPrimitives.push(step.primitive_id);
|
||||||
|
|
@ -4679,6 +4808,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||||
debtAsOfDate,
|
debtAsOfDate,
|
||||||
inventoryOnHandResult,
|
inventoryOnHandResult,
|
||||||
inventoryAgingResult,
|
inventoryAgingResult,
|
||||||
|
inventoryQualityEventsResult,
|
||||||
inventoryAsOfDate,
|
inventoryAsOfDate,
|
||||||
organizationScope,
|
organizationScope,
|
||||||
periodScope: dateScope
|
periodScope: dateScope
|
||||||
|
|
@ -4744,6 +4874,10 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||||
if (derivedBusinessOverview.inventory_staleness_risk_proxy) {
|
if (derivedBusinessOverview.inventory_staleness_risk_proxy) {
|
||||||
pushReason(reasonCodes, "pilot_derived_business_overview_inventory_staleness_risk_proxy_from_confirmed_rows");
|
pushReason(reasonCodes, "pilot_derived_business_overview_inventory_staleness_risk_proxy_from_confirmed_rows");
|
||||||
}
|
}
|
||||||
|
if (derivedBusinessOverview.inventory_quality_events) {
|
||||||
|
pushReason(reasonCodes, "pilot_derived_business_overview_inventory_quality_events_from_reviewed_rows");
|
||||||
|
pushReason(reasonCodes, `pilot_derived_business_overview_inventory_quality_events_${derivedBusinessOverview.inventory_quality_events.evidence_status}`);
|
||||||
|
}
|
||||||
if (derivedBusinessOverview.missing_proof_families.length > 0) {
|
if (derivedBusinessOverview.missing_proof_families.length > 0) {
|
||||||
pushReason(reasonCodes, "pilot_business_overview_missing_proof_families_recorded");
|
pushReason(reasonCodes, "pilot_business_overview_missing_proof_families_recorded");
|
||||||
}
|
}
|
||||||
|
|
@ -4763,7 +4897,8 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||||
counterpartyProfileResult,
|
counterpartyProfileResult,
|
||||||
contractUsageProfileResult,
|
contractUsageProfileResult,
|
||||||
inventoryOnHandResult,
|
inventoryOnHandResult,
|
||||||
inventoryAgingResult
|
inventoryAgingResult,
|
||||||
|
inventoryQualityEventsResult
|
||||||
});
|
});
|
||||||
const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({
|
const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({
|
||||||
plan: planner.discovery_plan,
|
plan: planner.discovery_plan,
|
||||||
|
|
|
||||||
|
|
@ -830,10 +830,18 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
||||||
}
|
}
|
||||||
if (inventoryReserveBoundary) {
|
if (inventoryReserveBoundary) {
|
||||||
const headline = toNonEmptyString(draft.headline);
|
const headline = toNonEmptyString(draft.headline);
|
||||||
|
const inventoryQualityEvents = toRecordObject(overview.inventory_quality_events);
|
||||||
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
||||||
lines.push(cleanHeadline
|
lines.push(cleanHeadline
|
||||||
? `Коротко: ${localizeLine(cleanHeadline)}`
|
? `Коротко: ${localizeLine(cleanHeadline)}`
|
||||||
: "Коротко: точно подтвердить резерв под неликвиды по текущим данным нельзя.");
|
: "Коротко: точно подтвердить резерв под неликвиды по текущим данным нельзя.");
|
||||||
|
if (inventoryQualityEvents) {
|
||||||
|
if (limitLine) {
|
||||||
|
lines.push(limitLine);
|
||||||
|
}
|
||||||
|
const reply = lines.join("\n").trim();
|
||||||
|
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||||
|
}
|
||||||
const boundaryLines = userFacingLines([
|
const boundaryLines = userFacingLines([
|
||||||
...toStringList(draft.unknown_lines),
|
...toStringList(draft.unknown_lines),
|
||||||
...toStringList(draft.limitation_lines)
|
...toStringList(draft.limitation_lines)
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,62 @@ const INVENTORY_ON_HAND_AS_OF_QUERY_TEMPLATE = `
|
||||||
Количество __ORDER_DIRECTION__
|
Количество __ORDER_DIRECTION__
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const INVENTORY_QUALITY_EVENTS_QUERY_TEMPLATE = `
|
||||||
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
|
Списание.Дата КАК Период,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Списание.Ссылка) КАК Регистратор,
|
||||||
|
"Списание товаров" КАК ТипСобытия,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Списание.Организация) КАК Организация,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Списание.Склад) КАК Склад,
|
||||||
|
Списание.СуммаДокумента КАК Сумма,
|
||||||
|
Списание.Основание КАК Основание,
|
||||||
|
Списание.Комментарий КАК Комментарий
|
||||||
|
ИЗ
|
||||||
|
Документ.СписаниеТоваров КАК Списание
|
||||||
|
__WHERE_WRITE_OFF__
|
||||||
|
ОБЪЕДИНИТЬ ВСЕ
|
||||||
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
|
Оприходование.Дата КАК Период,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Оприходование.Ссылка) КАК Регистратор,
|
||||||
|
"Оприходование товаров" КАК ТипСобытия,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Оприходование.Организация) КАК Организация,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Оприходование.Склад) КАК Склад,
|
||||||
|
Оприходование.СуммаДокумента КАК Сумма,
|
||||||
|
Оприходование.Основание КАК Основание,
|
||||||
|
Оприходование.Комментарий КАК Комментарий
|
||||||
|
ИЗ
|
||||||
|
Документ.ОприходованиеТоваров КАК Оприходование
|
||||||
|
__WHERE_RECEIPT__
|
||||||
|
ОБЪЕДИНИТЬ ВСЕ
|
||||||
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
|
Инвентаризация.Дата КАК Период,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Инвентаризация.Ссылка) КАК Регистратор,
|
||||||
|
"Инвентаризация товаров на складе" КАК ТипСобытия,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Инвентаризация.Организация) КАК Организация,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Инвентаризация.Склад) КАК Склад,
|
||||||
|
0 КАК Сумма,
|
||||||
|
Инвентаризация.ПричинаПроведенияИнвентаризации КАК Основание,
|
||||||
|
Инвентаризация.Комментарий КАК Комментарий
|
||||||
|
ИЗ
|
||||||
|
Документ.ИнвентаризацияТоваровНаСкладе КАК Инвентаризация
|
||||||
|
__WHERE_INVENTORY_COUNT__
|
||||||
|
ОБЪЕДИНИТЬ ВСЕ
|
||||||
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
|
Переоценка.Дата КАК Период,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Переоценка.Ссылка) КАК Регистратор,
|
||||||
|
"Переоценка товаров в рознице" КАК ТипСобытия,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Переоценка.Организация) КАК Организация,
|
||||||
|
ПРЕДСТАВЛЕНИЕ(Переоценка.Склад) КАК Склад,
|
||||||
|
0 КАК Сумма,
|
||||||
|
"" КАК Основание,
|
||||||
|
Переоценка.Комментарий КАК Комментарий
|
||||||
|
ИЗ
|
||||||
|
Документ.ПереоценкаТоваровВРознице КАК Переоценка
|
||||||
|
__WHERE_REVALUATION__
|
||||||
|
УПОРЯДОЧИТЬ ПО
|
||||||
|
Период __ORDER_DIRECTION__
|
||||||
|
`;
|
||||||
|
|
||||||
const BANK_DOCS_QUERY_TEMPLATE = `
|
const BANK_DOCS_QUERY_TEMPLATE = `
|
||||||
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||||
БанкСписание.Дата КАК Период,
|
БанкСписание.Дата КАК Период,
|
||||||
|
|
@ -958,6 +1014,16 @@ const BASE_RECIPES: AddressRecipeDefinition[] = [
|
||||||
account_scope_mode: "strict",
|
account_scope_mode: "strict",
|
||||||
query_template: "inventory_aging_by_purchase_date_profile"
|
query_template: "inventory_aging_by_purchase_date_profile"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
recipe_id: "address_inventory_quality_events_for_organization_v1",
|
||||||
|
intent: "inventory_quality_events_for_organization",
|
||||||
|
purpose: "Check posted inventory quality event documents: write-offs, stocktaking, receipt adjustments, and retail revaluation",
|
||||||
|
required_filters: [],
|
||||||
|
optional_filters: ["as_of_date", "period_from", "period_to", "organization", "warehouse", "limit", "sort"],
|
||||||
|
default_limit: 400,
|
||||||
|
account_scope_mode: "preferred",
|
||||||
|
query_template: "inventory_quality_events_profile"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
recipe_id: "address_open_contracts_confirmed_as_of_date_v1",
|
recipe_id: "address_open_contracts_confirmed_as_of_date_v1",
|
||||||
intent: "open_contracts_confirmed_as_of_date",
|
intent: "open_contracts_confirmed_as_of_date",
|
||||||
|
|
@ -1432,6 +1498,77 @@ function buildInventoryMovementQuery(
|
||||||
.replaceAll("__ORDER_DIRECTION__", resolveOrderDirection(filters.sort));
|
.replaceAll("__ORDER_DIRECTION__", resolveOrderDirection(filters.sort));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildWarehouseReferenceCondition(filters: AddressFilterSet, fieldPaths: string[]): string | null {
|
||||||
|
const warehouse = typeof filters.warehouse === "string" ? filters.warehouse.trim() : "";
|
||||||
|
if (!warehouse) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const tokens = Array.from(
|
||||||
|
new Set(
|
||||||
|
warehouse
|
||||||
|
.split(/[^A-Za-zА-Яа-яЁё0-9]+/u)
|
||||||
|
.map((token) => token.trim())
|
||||||
|
.filter((token) => token.length >= 3)
|
||||||
|
.filter((token) => !["склад", "warehouse"].includes(token.toLowerCase()))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const effectiveTokens = tokens.length > 0 ? tokens : [warehouse];
|
||||||
|
const clauses = fieldPaths
|
||||||
|
.map((fieldPath) => String(fieldPath ?? "").trim())
|
||||||
|
.filter((fieldPath) => fieldPath.length > 0)
|
||||||
|
.map((fieldPath) => {
|
||||||
|
const tokenConditions = effectiveTokens.map((token) => {
|
||||||
|
const escapedToken = toQueryStringLiteral(token);
|
||||||
|
return `${fieldPath}.Наименование ПОДОБНО "%${escapedToken}%"`;
|
||||||
|
});
|
||||||
|
return tokenConditions.length === 1 ? tokenConditions[0] : `(${tokenConditions.join(" И ")})`;
|
||||||
|
});
|
||||||
|
if (clauses.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return clauses.length === 1 ? clauses[0] : `(${clauses.join(" ИЛИ ")})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildInventoryQualityDocumentWhereClause(
|
||||||
|
filters: AddressFilterSet,
|
||||||
|
dateFieldPath: string,
|
||||||
|
organizationFieldPath: string,
|
||||||
|
warehouseFieldPath: string
|
||||||
|
): string {
|
||||||
|
return buildWhereClause(filters, dateFieldPath, [
|
||||||
|
`${dateFieldPath.replace(/\.Дата$/u, ".Проведен")} = ИСТИНА`,
|
||||||
|
buildOrganizationReferenceCondition(filters, [organizationFieldPath]),
|
||||||
|
buildWarehouseReferenceCondition(filters, [warehouseFieldPath])
|
||||||
|
].filter((item): item is string => Boolean(item)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildInventoryQualityEventsQuery(filters: AddressFilterSet, resolvedLimit: number): string {
|
||||||
|
return INVENTORY_QUALITY_EVENTS_QUERY_TEMPLATE
|
||||||
|
.replaceAll("__LIMIT__", String(resolvedLimit))
|
||||||
|
.replace(
|
||||||
|
"__WHERE_WRITE_OFF__",
|
||||||
|
buildInventoryQualityDocumentWhereClause(filters, "Списание.Дата", "Списание.Организация", "Списание.Склад")
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
"__WHERE_RECEIPT__",
|
||||||
|
buildInventoryQualityDocumentWhereClause(filters, "Оприходование.Дата", "Оприходование.Организация", "Оприходование.Склад")
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
"__WHERE_INVENTORY_COUNT__",
|
||||||
|
buildInventoryQualityDocumentWhereClause(
|
||||||
|
filters,
|
||||||
|
"Инвентаризация.Дата",
|
||||||
|
"Инвентаризация.Организация",
|
||||||
|
"Инвентаризация.Склад"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
"__WHERE_REVALUATION__",
|
||||||
|
buildInventoryQualityDocumentWhereClause(filters, "Переоценка.Дата", "Переоценка.Организация", "Переоценка.Склад")
|
||||||
|
)
|
||||||
|
.replaceAll("__ORDER_DIRECTION__", resolveOrderDirection(filters.sort));
|
||||||
|
}
|
||||||
|
|
||||||
function buildInventoryItemReferenceCondition(filters: AddressFilterSet, fieldPaths: string[]): string | null {
|
function buildInventoryItemReferenceCondition(filters: AddressFilterSet, fieldPaths: string[]): string | null {
|
||||||
const item = typeof filters.item === "string" ? filters.item.trim() : "";
|
const item = typeof filters.item === "string" ? filters.item.trim() : "";
|
||||||
if (!item) {
|
if (!item) {
|
||||||
|
|
@ -1783,6 +1920,7 @@ function maxLimitForIntent(intent: AddressIntent): number {
|
||||||
intent === "inventory_profitability_for_item" ||
|
intent === "inventory_profitability_for_item" ||
|
||||||
intent === "inventory_purchase_to_sale_chain" ||
|
intent === "inventory_purchase_to_sale_chain" ||
|
||||||
intent === "inventory_aging_by_purchase_date" ||
|
intent === "inventory_aging_by_purchase_date" ||
|
||||||
|
intent === "inventory_quality_events_for_organization" ||
|
||||||
intent === "open_contracts_confirmed_as_of_date" ||
|
intent === "open_contracts_confirmed_as_of_date" ||
|
||||||
intent === "list_contracts_by_counterparty" ||
|
intent === "list_contracts_by_counterparty" ||
|
||||||
intent === "list_documents_by_counterparty" ||
|
intent === "list_documents_by_counterparty" ||
|
||||||
|
|
@ -2037,6 +2175,8 @@ export function buildAddressRecipePlan(
|
||||||
? buildInventoryPurchaseToSaleDocumentQuery(filters, resolvedLimit)
|
? buildInventoryPurchaseToSaleDocumentQuery(filters, resolvedLimit)
|
||||||
: recipe.query_template === "inventory_aging_by_purchase_date_profile"
|
: recipe.query_template === "inventory_aging_by_purchase_date_profile"
|
||||||
? buildInventoryMovementQuery(filters, resolvedLimit, "dt")
|
? buildInventoryMovementQuery(filters, resolvedLimit, "dt")
|
||||||
|
: recipe.query_template === "inventory_quality_events_profile"
|
||||||
|
? buildInventoryQualityEventsQuery(filters, resolvedLimit)
|
||||||
: recipe.query_template === "contracts_by_counterparty_profile"
|
: recipe.query_template === "contracts_by_counterparty_profile"
|
||||||
? CONTRACTS_BY_COUNTERPARTY_QUERY_TEMPLATE.replaceAll("__LIMIT__", String(resolvedLimit))
|
? CONTRACTS_BY_COUNTERPARTY_QUERY_TEMPLATE.replaceAll("__LIMIT__", String(resolvedLimit))
|
||||||
: recipe.query_template === "open_contracts_confirmed_as_of_balance_profile"
|
: recipe.query_template === "open_contracts_confirmed_as_of_balance_profile"
|
||||||
|
|
|
||||||
|
|
@ -510,6 +510,9 @@ function isVendorRiskBoundaryTurn(pilot: AssistantMcpDiscoveryPilotExecutionCont
|
||||||
}
|
}
|
||||||
|
|
||||||
function businessOverviewInventoryUnknownLabel(overview: BusinessOverview): string {
|
function businessOverviewInventoryUnknownLabel(overview: BusinessOverview): string {
|
||||||
|
if (overview.inventory_quality_events) {
|
||||||
|
return "рыночная ликвидационная стоимость и управленческий резерв склада";
|
||||||
|
}
|
||||||
if (overview.inventory_staleness_risk_proxy) {
|
if (overview.inventory_staleness_risk_proxy) {
|
||||||
return "резервы/списания/ликвидационная стоимость склада";
|
return "резервы/списания/ликвидационная стоимость склада";
|
||||||
}
|
}
|
||||||
|
|
@ -764,6 +767,26 @@ function businessOverviewVendorProcurementQualityText(overview: BusinessOverview
|
||||||
return `Procurement-concentration route за ${period} отработал по исходящим платежам на ${total}, но надежной небанковской концентрации поставщика по найденным строкам не хватает.${contractText} Полный vendor-risk аудит не подтвержден.`;
|
return `Procurement-concentration route за ${period} отработал по исходящим платежам на ${total}, но надежной небанковской концентрации поставщика по найденным строкам не хватает.${contractText} Полный vendor-risk аудит не подтвержден.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function businessOverviewInventoryQualityEventsText(overview: BusinessOverview): string | null {
|
||||||
|
const quality = overview.inventory_quality_events;
|
||||||
|
if (!quality) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const period = quality.period_scope ?? "проверенное окно";
|
||||||
|
const organization = overview.organization_scope ? ` по организации ${overview.organization_scope}` : "";
|
||||||
|
const eventWindow =
|
||||||
|
quality.first_event_date && quality.latest_event_date
|
||||||
|
? ` Окно найденных событий: ${quality.first_event_date} - ${quality.latest_event_date}.`
|
||||||
|
: "";
|
||||||
|
if (quality.evidence_status === "reviewed_no_quality_events_found") {
|
||||||
|
return `Коротко: проверил складские документы списания, оприходования, инвентаризации и переоценки${organization} за ${period}; подтвержденных событий списания/корректировки/инвентаризации/переоценки не найдено. Это сильный отрицательный сигнал по доступным документам 1С, но не рыночная ликвидационная стоимость и не управленческий резерв под неликвиды.`;
|
||||||
|
}
|
||||||
|
if (quality.evidence_status === "reviewed_inventory_control_events_only") {
|
||||||
|
return `Коротко: проверил складские quality-события${organization} за ${period}; списаний и оприходований/корректировок с суммой не найдено, но есть инвентаризации ${quality.inventory_count_rows} и переоценки ${quality.revaluation_rows}.${eventWindow} Это контрольные складские документы, а не подтвержденный резерв или рыночная ликвидационная оценка.`;
|
||||||
|
}
|
||||||
|
return `Коротко: проверил складские quality-события${organization} за ${period}; списаний ${quality.writeoff_rows} на ${quality.writeoff_amount_human_ru}, оприходований/корректировок ${quality.receipt_adjustment_rows} на ${quality.receipt_adjustment_amount_human_ru}, инвентаризаций ${quality.inventory_count_rows}, переоценок ${quality.revaluation_rows}.${eventWindow} Это подтвержденные документы 1С по складским событиям, но не самостоятельная рыночная ликвидационная стоимость и не расчет управленческого резерва.`;
|
||||||
|
}
|
||||||
|
|
||||||
function headlineFor(mode: AssistantMcpDiscoveryAnswerMode, pilot: AssistantMcpDiscoveryPilotExecutionContract): string {
|
function headlineFor(mode: AssistantMcpDiscoveryAnswerMode, pilot: AssistantMcpDiscoveryPilotExecutionContract): string {
|
||||||
const askedMonthlyBreakdown =
|
const askedMonthlyBreakdown =
|
||||||
pilot.derived_bidirectional_value_flow?.aggregation_axis === "month" ||
|
pilot.derived_bidirectional_value_flow?.aggregation_axis === "month" ||
|
||||||
|
|
@ -797,6 +820,10 @@ function headlineFor(mode: AssistantMcpDiscoveryAnswerMode, pilot: AssistantMcpD
|
||||||
return "Нельзя точно определить, какая дебиторка просрочена, по текущему срезу 1С; есть только debt-quality proxy, но нет проверенного due-date маршрута по договорам, срокам оплаты и погашению расчетов.";
|
return "Нельзя точно определить, какая дебиторка просрочена, по текущему срезу 1С; есть только debt-quality proxy, но нет проверенного due-date маршрута по договорам, срокам оплаты и погашению расчетов.";
|
||||||
}
|
}
|
||||||
if (isInventoryReserveBoundaryTurn(pilot)) {
|
if (isInventoryReserveBoundaryTurn(pilot)) {
|
||||||
|
const inventoryQualityEventsText = businessOverviewInventoryQualityEventsText(overview);
|
||||||
|
if (inventoryQualityEventsText) {
|
||||||
|
return inventoryQualityEventsText;
|
||||||
|
}
|
||||||
const inventoryBasis = overview.inventory_staleness_risk_proxy
|
const inventoryBasis = overview.inventory_staleness_risk_proxy
|
||||||
? "есть только складской staleness-risk proxy по найденным строкам"
|
? "есть только складской staleness-risk proxy по найденным строкам"
|
||||||
: overview.inventory_position || overview.inventory_turnover_proxy
|
: overview.inventory_position || overview.inventory_turnover_proxy
|
||||||
|
|
@ -870,6 +897,9 @@ function headlineFor(mode: AssistantMcpDiscoveryAnswerMode, pilot: AssistantMcpD
|
||||||
if (overview.inventory_staleness_risk_proxy) {
|
if (overview.inventory_staleness_risk_proxy) {
|
||||||
families.push("staleness risk proxy склада");
|
families.push("staleness risk proxy склада");
|
||||||
}
|
}
|
||||||
|
if (overview.inventory_quality_events) {
|
||||||
|
families.push("складские quality-события");
|
||||||
|
}
|
||||||
const unknownFamilies = overview.accounting_financial_result
|
const unknownFamilies = overview.accounting_financial_result
|
||||||
? ["аудированная/юридически подтвержденная прибыль"]
|
? ["аудированная/юридически подтвержденная прибыль"]
|
||||||
: [overview.trading_margin_proxy ? "чистая прибыль/точная маржа" : "прибыль/маржа"];
|
: [overview.trading_margin_proxy ? "чистая прибыль/точная маржа" : "прибыль/маржа"];
|
||||||
|
|
@ -1101,6 +1131,9 @@ function buildMustNotClaim(pilot: AssistantMcpDiscoveryPilotExecutionContract):
|
||||||
claims.push("Do not present an inventory snapshot or purchase-date aging signal as turnover, obsolescence, liquidation value, or full inventory health.");
|
claims.push("Do not present an inventory snapshot or purchase-date aging signal as turnover, obsolescence, liquidation value, or full inventory health.");
|
||||||
claims.push("Do not present business overview inventory turnover proxy as full inventory liquidity, FIFO turnover, obsolescence analysis, or liquidation value.");
|
claims.push("Do not present business overview inventory turnover proxy as full inventory liquidity, FIFO turnover, obsolescence analysis, or liquidation value.");
|
||||||
claims.push("Do not present business overview inventory staleness risk proxy as confirmed obsolete stock, reserve, write-off, or liquidation value.");
|
claims.push("Do not present business overview inventory staleness risk proxy as confirmed obsolete stock, reserve, write-off, or liquidation value.");
|
||||||
|
if (pilot.derived_business_overview?.inventory_quality_events) {
|
||||||
|
claims.push("Do not present reviewed inventory quality events as confirmed obsolete stock, reserve policy, market liquidation value, management reserve, or full inventory health.");
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
pilot.derived_business_overview?.top_customers?.some(isFinancialInstitutionBucket) ||
|
pilot.derived_business_overview?.top_customers?.some(isFinancialInstitutionBucket) ||
|
||||||
pilot.derived_business_overview?.top_suppliers?.some(isFinancialInstitutionBucket)
|
pilot.derived_business_overview?.top_suppliers?.some(isFinancialInstitutionBucket)
|
||||||
|
|
@ -1676,6 +1709,10 @@ function derivedBusinessOverviewConfirmedLines(pilot: AssistantMcpDiscoveryPilot
|
||||||
`Staleness risk proxy склада на ${proxy.as_of_date}: самая ранняя дата закупочного сигнала ${proxy.oldest_purchase_date}, возраст ${proxy.max_purchase_age_days} дн., sales-to-stock ${proxy.sales_to_stock_amount_ratio}x, оценка ${inventoryStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`
|
`Staleness risk proxy склада на ${proxy.as_of_date}: самая ранняя дата закупочного сигнала ${proxy.oldest_purchase_date}, возраст ${proxy.max_purchase_age_days} дн., sales-to-stock ${proxy.sales_to_stock_amount_ratio}x, оценка ${inventoryStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const inventoryQualityEventsText = businessOverviewInventoryQualityEventsText(overview);
|
||||||
|
if (inventoryQualityEventsText) {
|
||||||
|
lines.push(inventoryQualityEventsText.replace(/^Коротко:\s*/u, ""));
|
||||||
|
}
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1858,6 +1895,16 @@ function businessOverviewRiskSynthesisLine(overview: BusinessOverview): string |
|
||||||
`staleness risk proxy склада: ${inventoryStalenessRiskBandRu(overview.inventory_staleness_risk_proxy.risk_band)}, возраст ${overview.inventory_staleness_risk_proxy.max_purchase_age_days} дн.`
|
`staleness risk proxy склада: ${inventoryStalenessRiskBandRu(overview.inventory_staleness_risk_proxy.risk_band)}, возраст ${overview.inventory_staleness_risk_proxy.max_purchase_age_days} дн.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (overview.inventory_quality_events) {
|
||||||
|
const quality = overview.inventory_quality_events;
|
||||||
|
if (quality.evidence_status === "reviewed_no_quality_events_found") {
|
||||||
|
signals.push("складские quality-события: документы списания, оприходования, инвентаризации и переоценки проверены, подтвержденных событий не найдено");
|
||||||
|
} else {
|
||||||
|
signals.push(
|
||||||
|
`складские quality-события: списаний ${quality.writeoff_rows} на ${quality.writeoff_amount_human_ru}, оприходований/корректировок ${quality.receipt_adjustment_rows} на ${quality.receipt_adjustment_amount_human_ru}, инвентаризаций ${quality.inventory_count_rows}, переоценок ${quality.revaluation_rows}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
return signals.length > 0
|
return signals.length > 0
|
||||||
? `Риски и контуры внимания по подтвержденным данным: ${signals.join("; ")}.`
|
? `Риски и контуры внимания по подтвержденным данным: ${signals.join("; ")}.`
|
||||||
: null;
|
: null;
|
||||||
|
|
@ -1873,7 +1920,8 @@ function businessOverviewExecutiveVerdictLine(overview: BusinessOverview): strin
|
||||||
overview.debt_staleness_risk_proxy ||
|
overview.debt_staleness_risk_proxy ||
|
||||||
overview.inventory_position ||
|
overview.inventory_position ||
|
||||||
overview.inventory_turnover_proxy ||
|
overview.inventory_turnover_proxy ||
|
||||||
overview.inventory_staleness_risk_proxy
|
overview.inventory_staleness_risk_proxy ||
|
||||||
|
overview.inventory_quality_events
|
||||||
);
|
);
|
||||||
const hasOperationalProfileSignal = Boolean(
|
const hasOperationalProfileSignal = Boolean(
|
||||||
overview.document_activity_profile || overview.counterparty_profile || overview.contract_usage_profile
|
overview.document_activity_profile || overview.counterparty_profile || overview.contract_usage_profile
|
||||||
|
|
@ -2020,6 +2068,10 @@ export function buildAssistantMcpDiscoveryAnswerDraft(
|
||||||
if (pilot.derived_business_overview?.inventory_staleness_risk_proxy) {
|
if (pilot.derived_business_overview?.inventory_staleness_risk_proxy) {
|
||||||
pushReason(reasonCodes, "answer_contains_business_overview_inventory_staleness_risk_proxy");
|
pushReason(reasonCodes, "answer_contains_business_overview_inventory_staleness_risk_proxy");
|
||||||
}
|
}
|
||||||
|
if (pilot.derived_business_overview?.inventory_quality_events) {
|
||||||
|
pushReason(reasonCodes, "answer_contains_business_overview_inventory_quality_events");
|
||||||
|
pushReason(reasonCodes, `answer_contains_business_overview_inventory_quality_events_${pilot.derived_business_overview.inventory_quality_events.evidence_status}`);
|
||||||
|
}
|
||||||
if (pilot.derived_business_overview?.missing_proof_families?.length) {
|
if (pilot.derived_business_overview?.missing_proof_families?.length) {
|
||||||
pushReason(reasonCodes, "answer_contains_business_overview_missing_proof_ledger");
|
pushReason(reasonCodes, "answer_contains_business_overview_missing_proof_ledger");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,7 @@ export interface AssistantMcpDiscoveryDerivedBusinessOverview {
|
||||||
inventory_position: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryPosition | null;
|
inventory_position: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryPosition | null;
|
||||||
inventory_turnover_proxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryTurnoverProxy | null;
|
inventory_turnover_proxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryTurnoverProxy | null;
|
||||||
inventory_staleness_risk_proxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryStalenessRiskProxy | null;
|
inventory_staleness_risk_proxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryStalenessRiskProxy | null;
|
||||||
|
inventory_quality_events: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryQualityEvents | null;
|
||||||
document_activity_profile: AssistantMcpDiscoveryDerivedBusinessOverviewDocumentActivityProfile | null;
|
document_activity_profile: AssistantMcpDiscoveryDerivedBusinessOverviewDocumentActivityProfile | null;
|
||||||
counterparty_profile: AssistantMcpDiscoveryDerivedBusinessOverviewCounterpartyProfile | null;
|
counterparty_profile: AssistantMcpDiscoveryDerivedBusinessOverviewCounterpartyProfile | null;
|
||||||
contract_usage_profile: AssistantMcpDiscoveryDerivedBusinessOverviewContractUsageProfile | null;
|
contract_usage_profile: AssistantMcpDiscoveryDerivedBusinessOverviewContractUsageProfile | null;
|
||||||
|
|
@ -521,6 +522,26 @@ export interface AssistantMcpDiscoveryDerivedBusinessOverviewInventoryStalenessR
|
||||||
inference_basis: "purchase_date_age_and_sales_to_stock_proxy_confirmed_1c_rows";
|
inference_basis: "purchase_date_age_and_sales_to_stock_proxy_confirmed_1c_rows";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AssistantMcpDiscoveryDerivedBusinessOverviewInventoryQualityEvents {
|
||||||
|
period_scope: string | null;
|
||||||
|
rows_matched: number;
|
||||||
|
writeoff_rows: number;
|
||||||
|
writeoff_amount: number;
|
||||||
|
writeoff_amount_human_ru: string;
|
||||||
|
receipt_adjustment_rows: number;
|
||||||
|
receipt_adjustment_amount: number;
|
||||||
|
receipt_adjustment_amount_human_ru: string;
|
||||||
|
inventory_count_rows: number;
|
||||||
|
revaluation_rows: number;
|
||||||
|
first_event_date: string | null;
|
||||||
|
latest_event_date: string | null;
|
||||||
|
evidence_status:
|
||||||
|
| "reviewed_no_quality_events_found"
|
||||||
|
| "reviewed_writeoff_or_adjustment_events_found"
|
||||||
|
| "reviewed_inventory_control_events_only";
|
||||||
|
inference_basis: "inventory_quality_documents_confirmed_1c_rows";
|
||||||
|
}
|
||||||
|
|
||||||
export interface AssistantMcpDiscoveryDerivedMetadataSurface {
|
export interface AssistantMcpDiscoveryDerivedMetadataSurface {
|
||||||
metadata_scope: string | null;
|
metadata_scope: string | null;
|
||||||
requested_meta_types: string[];
|
requested_meta_types: string[];
|
||||||
|
|
@ -829,6 +850,17 @@ function shouldRunDebtDueDateAgingProbe(planner: AssistantMcpDiscoveryPlannerCon
|
||||||
return /(?:debt_due_date_boundary|due[-_ ]?date|overdue|aging|просроч|срок\s+оплат|дебиторк|кредиторск)/iu.test(combined);
|
return /(?:debt_due_date_boundary|due[-_ ]?date|overdue|aging|просроч|срок\s+оплат|дебиторк|кредиторск)/iu.test(combined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shouldRunInventoryQualityEventsProbe(planner: AssistantMcpDiscoveryPlannerContract): boolean {
|
||||||
|
const actionFamily = toNonEmptyString(planner.data_need_graph?.action_family);
|
||||||
|
const turnActionFamily = toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.asked_action_family);
|
||||||
|
const unsupportedFamily = toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.unsupported_but_understood_family);
|
||||||
|
const proofExpectation = toNonEmptyString(planner.data_need_graph?.proof_expectation);
|
||||||
|
const combined = [actionFamily, turnActionFamily, unsupportedFamily, proofExpectation]
|
||||||
|
.filter((item): item is string => Boolean(item))
|
||||||
|
.join(" ");
|
||||||
|
return /(?:inventory_reserve|reserve_liquidation|liquidation|write[-_ ]?off|obsolete|obsolescence|inventory_reserve_liquidation_quality|резерв|списан|ликвидац|неликвид|обесцен)/iu.test(combined);
|
||||||
|
}
|
||||||
|
|
||||||
function buildBusinessOverviewInventoryFilters(planner: AssistantMcpDiscoveryPlannerContract): AddressFilterSet | null {
|
function buildBusinessOverviewInventoryFilters(planner: AssistantMcpDiscoveryPlannerContract): AddressFilterSet | null {
|
||||||
const meaning = planner.discovery_plan.turn_meaning_ref;
|
const meaning = planner.discovery_plan.turn_meaning_ref;
|
||||||
const organization = toNonEmptyString(meaning?.explicit_organization_scope);
|
const organization = toNonEmptyString(meaning?.explicit_organization_scope);
|
||||||
|
|
@ -4148,6 +4180,79 @@ function deriveBusinessOverviewInventoryStalenessRiskProxy(input: {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rowInventoryQualityEventType(row: Record<string, unknown>): string {
|
||||||
|
return rowTextValue(row, ["ТипСобытия", "EventType", "event_type", "Регистратор", "Registrator", "registrator"]) ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function deriveBusinessOverviewInventoryQualityEvents(input: {
|
||||||
|
inventoryQualityEventsResult: AddressMcpQueryExecutorResult | null;
|
||||||
|
periodScope: string | null;
|
||||||
|
}): AssistantMcpDiscoveryDerivedBusinessOverviewInventoryQualityEvents | null {
|
||||||
|
const result = input.inventoryQualityEventsResult;
|
||||||
|
if (!result || result.error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let writeoffRows = 0;
|
||||||
|
let writeoffAmount = 0;
|
||||||
|
let receiptAdjustmentRows = 0;
|
||||||
|
let receiptAdjustmentAmount = 0;
|
||||||
|
let inventoryCountRows = 0;
|
||||||
|
let revaluationRows = 0;
|
||||||
|
const eventDates: string[] = [];
|
||||||
|
|
||||||
|
for (const row of result.rows) {
|
||||||
|
const eventType = rowInventoryQualityEventType(row);
|
||||||
|
const amount = rowAmountValue(row) ?? 0;
|
||||||
|
const date = rowDateValue(row);
|
||||||
|
if (date) {
|
||||||
|
eventDates.push(date);
|
||||||
|
}
|
||||||
|
if (/списан|write[-_ ]?off/iu.test(eventType)) {
|
||||||
|
writeoffRows += 1;
|
||||||
|
writeoffAmount += amount;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (/оприход|receipt|positive/i.test(eventType)) {
|
||||||
|
receiptAdjustmentRows += 1;
|
||||||
|
receiptAdjustmentAmount += amount;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (/инвентаризац|stocktaking|inventory count/i.test(eventType)) {
|
||||||
|
inventoryCountRows += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (/переоцен|revaluation/i.test(eventType)) {
|
||||||
|
revaluationRows += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortedDates = eventDates.sort((left, right) => left.localeCompare(right));
|
||||||
|
const evidenceStatus: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryQualityEvents["evidence_status"] =
|
||||||
|
writeoffRows > 0 || receiptAdjustmentRows > 0
|
||||||
|
? "reviewed_writeoff_or_adjustment_events_found"
|
||||||
|
: inventoryCountRows > 0 || revaluationRows > 0
|
||||||
|
? "reviewed_inventory_control_events_only"
|
||||||
|
: "reviewed_no_quality_events_found";
|
||||||
|
|
||||||
|
return {
|
||||||
|
period_scope: input.periodScope,
|
||||||
|
rows_matched: result.matched_rows,
|
||||||
|
writeoff_rows: writeoffRows,
|
||||||
|
writeoff_amount: writeoffAmount,
|
||||||
|
writeoff_amount_human_ru: formatAmountHumanRu(writeoffAmount),
|
||||||
|
receipt_adjustment_rows: receiptAdjustmentRows,
|
||||||
|
receipt_adjustment_amount: receiptAdjustmentAmount,
|
||||||
|
receipt_adjustment_amount_human_ru: formatAmountHumanRu(receiptAdjustmentAmount),
|
||||||
|
inventory_count_rows: inventoryCountRows,
|
||||||
|
revaluation_rows: revaluationRows,
|
||||||
|
first_event_date: sortedDates[0] ?? null,
|
||||||
|
latest_event_date: sortedDates[sortedDates.length - 1] ?? null,
|
||||||
|
evidence_status: evidenceStatus,
|
||||||
|
inference_basis: "inventory_quality_documents_confirmed_1c_rows"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function deriveBusinessOverviewVendorProcurementQuality(input: {
|
function deriveBusinessOverviewVendorProcurementQuality(input: {
|
||||||
rankedOutgoing: AssistantMcpDiscoveryDerivedRankedValueFlow | null;
|
rankedOutgoing: AssistantMcpDiscoveryDerivedRankedValueFlow | null;
|
||||||
outgoing: AssistantMcpDiscoveryValueFlowSideSummary;
|
outgoing: AssistantMcpDiscoveryValueFlowSideSummary;
|
||||||
|
|
@ -4226,6 +4331,7 @@ function buildBusinessOverviewMissingProofFamilies(input: {
|
||||||
inventoryPosition: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryPosition | null;
|
inventoryPosition: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryPosition | null;
|
||||||
inventoryTurnoverProxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryTurnoverProxy | null;
|
inventoryTurnoverProxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryTurnoverProxy | null;
|
||||||
inventoryStalenessRiskProxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryStalenessRiskProxy | null;
|
inventoryStalenessRiskProxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryStalenessRiskProxy | null;
|
||||||
|
inventoryQualityEvents: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryQualityEvents | null;
|
||||||
vendorProcurementQuality: AssistantMcpDiscoveryDerivedBusinessOverviewVendorProcurementQuality | null;
|
vendorProcurementQuality: AssistantMcpDiscoveryDerivedBusinessOverviewVendorProcurementQuality | null;
|
||||||
hasSupplierConcentrationSignal: boolean;
|
hasSupplierConcentrationSignal: boolean;
|
||||||
}): AssistantMcpDiscoveryBusinessOverviewMissingProofFamily[] {
|
}): AssistantMcpDiscoveryBusinessOverviewMissingProofFamily[] {
|
||||||
|
|
@ -4267,12 +4373,12 @@ function buildBusinessOverviewMissingProofFamilies(input: {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if ((
|
||||||
missing.has("inventory_position") ||
|
missing.has("inventory_position") ||
|
||||||
missing.has("inventory_turnover_quality") ||
|
missing.has("inventory_turnover_quality") ||
|
||||||
missing.has("inventory_liquidity_quality") ||
|
missing.has("inventory_liquidity_quality") ||
|
||||||
missing.has("inventory_reserve_liquidation_quality")
|
missing.has("inventory_reserve_liquidation_quality")
|
||||||
) {
|
) && !input.inventoryQualityEvents) {
|
||||||
pushUnique({
|
pushUnique({
|
||||||
family: "inventory_reserve_liquidation_quality",
|
family: "inventory_reserve_liquidation_quality",
|
||||||
current_status: input.inventoryStalenessRiskProxy
|
current_status: input.inventoryStalenessRiskProxy
|
||||||
|
|
@ -4322,6 +4428,7 @@ function deriveBusinessOverview(input: {
|
||||||
debtAsOfDate: string | null;
|
debtAsOfDate: string | null;
|
||||||
inventoryOnHandResult: AddressMcpQueryExecutorResult | null;
|
inventoryOnHandResult: AddressMcpQueryExecutorResult | null;
|
||||||
inventoryAgingResult: AddressMcpQueryExecutorResult | null;
|
inventoryAgingResult: AddressMcpQueryExecutorResult | null;
|
||||||
|
inventoryQualityEventsResult: AddressMcpQueryExecutorResult | null;
|
||||||
inventoryAsOfDate: string | null;
|
inventoryAsOfDate: string | null;
|
||||||
organizationScope: string | null;
|
organizationScope: string | null;
|
||||||
periodScope: string | null;
|
periodScope: string | null;
|
||||||
|
|
@ -4390,6 +4497,10 @@ function deriveBusinessOverview(input: {
|
||||||
inventoryPosition,
|
inventoryPosition,
|
||||||
inventoryTurnoverProxy
|
inventoryTurnoverProxy
|
||||||
});
|
});
|
||||||
|
const inventoryQualityEvents = deriveBusinessOverviewInventoryQualityEvents({
|
||||||
|
inventoryQualityEventsResult: input.inventoryQualityEventsResult,
|
||||||
|
periodScope: input.periodScope
|
||||||
|
});
|
||||||
const vendorProcurementQuality = deriveBusinessOverviewVendorProcurementQuality({
|
const vendorProcurementQuality = deriveBusinessOverviewVendorProcurementQuality({
|
||||||
rankedOutgoing,
|
rankedOutgoing,
|
||||||
outgoing,
|
outgoing,
|
||||||
|
|
@ -4414,6 +4525,7 @@ function deriveBusinessOverview(input: {
|
||||||
Boolean(inventoryPosition),
|
Boolean(inventoryPosition),
|
||||||
Boolean(inventoryTurnoverProxy),
|
Boolean(inventoryTurnoverProxy),
|
||||||
Boolean(inventoryStalenessRiskProxy),
|
Boolean(inventoryStalenessRiskProxy),
|
||||||
|
Boolean(inventoryQualityEvents),
|
||||||
Boolean(vendorProcurementQuality)
|
Boolean(vendorProcurementQuality)
|
||||||
].filter(Boolean).length;
|
].filter(Boolean).length;
|
||||||
if (checkedSignalCount <= 0) {
|
if (checkedSignalCount <= 0) {
|
||||||
|
|
@ -4430,7 +4542,9 @@ function deriveBusinessOverview(input: {
|
||||||
debtDueDateAging ? null : debtOpenSettlementQuality ? "debt_due_date_aging_quality" : "debt_open_settlement_quality",
|
debtDueDateAging ? null : debtOpenSettlementQuality ? "debt_due_date_aging_quality" : "debt_open_settlement_quality",
|
||||||
taxPosition ? null : "tax_position",
|
taxPosition ? null : "tax_position",
|
||||||
inventoryPosition
|
inventoryPosition
|
||||||
? inventoryStalenessRiskProxy
|
? inventoryQualityEvents
|
||||||
|
? null
|
||||||
|
: inventoryStalenessRiskProxy
|
||||||
? "inventory_reserve_liquidation_quality"
|
? "inventory_reserve_liquidation_quality"
|
||||||
: inventoryTurnoverProxy
|
: inventoryTurnoverProxy
|
||||||
? "inventory_liquidity_quality"
|
? "inventory_liquidity_quality"
|
||||||
|
|
@ -4448,6 +4562,7 @@ function deriveBusinessOverview(input: {
|
||||||
inventoryPosition,
|
inventoryPosition,
|
||||||
inventoryTurnoverProxy,
|
inventoryTurnoverProxy,
|
||||||
inventoryStalenessRiskProxy,
|
inventoryStalenessRiskProxy,
|
||||||
|
inventoryQualityEvents,
|
||||||
vendorProcurementQuality,
|
vendorProcurementQuality,
|
||||||
hasSupplierConcentrationSignal: (rankedOutgoing?.ranked_values.length ?? 0) > 0
|
hasSupplierConcentrationSignal: (rankedOutgoing?.ranked_values.length ?? 0) > 0
|
||||||
});
|
});
|
||||||
|
|
@ -4473,6 +4588,7 @@ function deriveBusinessOverview(input: {
|
||||||
inventory_position: inventoryPosition,
|
inventory_position: inventoryPosition,
|
||||||
inventory_turnover_proxy: inventoryTurnoverProxy,
|
inventory_turnover_proxy: inventoryTurnoverProxy,
|
||||||
inventory_staleness_risk_proxy: inventoryStalenessRiskProxy,
|
inventory_staleness_risk_proxy: inventoryStalenessRiskProxy,
|
||||||
|
inventory_quality_events: inventoryQualityEvents,
|
||||||
document_activity_profile: documentActivityProfile,
|
document_activity_profile: documentActivityProfile,
|
||||||
counterparty_profile: counterpartyProfile,
|
counterparty_profile: counterpartyProfile,
|
||||||
contract_usage_profile: contractUsageProfile,
|
contract_usage_profile: contractUsageProfile,
|
||||||
|
|
@ -4483,7 +4599,7 @@ function deriveBusinessOverview(input: {
|
||||||
missing_signal_families: missingSignalFamilies,
|
missing_signal_families: missingSignalFamilies,
|
||||||
missing_proof_families: missingProofFamilies,
|
missing_proof_families: missingProofFamilies,
|
||||||
inference_basis:
|
inference_basis:
|
||||||
hasBusinessOverviewProfileSignal || inventoryPosition || accountingFinancialResult
|
hasBusinessOverviewProfileSignal || inventoryPosition || inventoryQualityEvents || accountingFinancialResult
|
||||||
? "business_overview_from_confirmed_1c_multi_family_rows"
|
? "business_overview_from_confirmed_1c_multi_family_rows"
|
||||||
: debtOpenSettlementQuality || debtDueDateAging
|
: debtOpenSettlementQuality || debtDueDateAging
|
||||||
? "business_overview_from_confirmed_1c_multi_family_rows"
|
? "business_overview_from_confirmed_1c_multi_family_rows"
|
||||||
|
|
@ -4513,6 +4629,7 @@ function summarizeBusinessOverviewRows(input: {
|
||||||
contractUsageProfileResult: AddressMcpQueryExecutorResult | null;
|
contractUsageProfileResult: AddressMcpQueryExecutorResult | null;
|
||||||
inventoryOnHandResult: AddressMcpQueryExecutorResult | null;
|
inventoryOnHandResult: AddressMcpQueryExecutorResult | null;
|
||||||
inventoryAgingResult: AddressMcpQueryExecutorResult | null;
|
inventoryAgingResult: AddressMcpQueryExecutorResult | null;
|
||||||
|
inventoryQualityEventsResult: AddressMcpQueryExecutorResult | null;
|
||||||
}): string | null {
|
}): string | null {
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
if (input.incomingResult && !input.incomingResult.error) {
|
if (input.incomingResult && !input.incomingResult.error) {
|
||||||
|
|
@ -4560,6 +4677,9 @@ function summarizeBusinessOverviewRows(input: {
|
||||||
if (input.inventoryAgingResult && !input.inventoryAgingResult.error) {
|
if (input.inventoryAgingResult && !input.inventoryAgingResult.error) {
|
||||||
parts.push(`${input.inventoryAgingResult.fetched_rows} inventory aging rows fetched, ${input.inventoryAgingResult.matched_rows} matched`);
|
parts.push(`${input.inventoryAgingResult.fetched_rows} inventory aging rows fetched, ${input.inventoryAgingResult.matched_rows} matched`);
|
||||||
}
|
}
|
||||||
|
if (input.inventoryQualityEventsResult && !input.inventoryQualityEventsResult.error) {
|
||||||
|
parts.push(`${input.inventoryQualityEventsResult.fetched_rows} inventory quality-event rows fetched, ${input.inventoryQualityEventsResult.matched_rows} matched`);
|
||||||
|
}
|
||||||
return parts.length > 0 ? parts.join("; ") : null;
|
return parts.length > 0 ? parts.join("; ") : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4780,6 +4900,22 @@ function buildBusinessOverviewConfirmedFacts(derived: AssistantMcpDiscoveryDeriv
|
||||||
`Staleness risk proxy склада на ${proxy.as_of_date}: самая ранняя дата закупочного сигнала ${proxy.oldest_purchase_date}, возраст ${proxy.max_purchase_age_days} дн., sales-to-stock ${proxy.sales_to_stock_amount_ratio}x, оценка ${inventoryStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`
|
`Staleness risk proxy склада на ${proxy.as_of_date}: самая ранняя дата закупочного сигнала ${proxy.oldest_purchase_date}, возраст ${proxy.max_purchase_age_days} дн., sales-to-stock ${proxy.sales_to_stock_amount_ratio}x, оценка ${inventoryStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (derived.inventory_quality_events) {
|
||||||
|
const quality = derived.inventory_quality_events;
|
||||||
|
const eventWindow =
|
||||||
|
quality.first_event_date && quality.latest_event_date
|
||||||
|
? ` Окно найденных событий: ${quality.first_event_date} — ${quality.latest_event_date}.`
|
||||||
|
: "";
|
||||||
|
if (quality.evidence_status === "reviewed_no_quality_events_found") {
|
||||||
|
facts.push(
|
||||||
|
`Reviewed inventory quality route проверил складские документы списания, оприходования, инвентаризации и переоценки${period}: подтвержденных событий не найдено. Это проверенный отрицательный результат по доступным документам, но не рыночная ликвидационная оценка и не управленческий резерв.`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
facts.push(
|
||||||
|
`Reviewed inventory quality route проверил складские документы${period}: списаний ${quality.writeoff_rows} на ${quality.writeoff_amount_human_ru}, оприходований/корректировок ${quality.receipt_adjustment_rows} на ${quality.receipt_adjustment_amount_human_ru}, инвентаризаций ${quality.inventory_count_rows}, переоценок ${quality.revaluation_rows}.${eventWindow} Это подтвержденные документы 1С, но не самостоятельная рыночная ликвидационная стоимость.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
return facts;
|
return facts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5616,6 +5752,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||||
let contractUsageProfileResult: AddressMcpQueryExecutorResult | null = null;
|
let contractUsageProfileResult: AddressMcpQueryExecutorResult | null = null;
|
||||||
let inventoryOnHandResult: AddressMcpQueryExecutorResult | null = null;
|
let inventoryOnHandResult: AddressMcpQueryExecutorResult | null = null;
|
||||||
let inventoryAgingResult: AddressMcpQueryExecutorResult | null = null;
|
let inventoryAgingResult: AddressMcpQueryExecutorResult | null = null;
|
||||||
|
let inventoryQualityEventsResult: AddressMcpQueryExecutorResult | null = null;
|
||||||
const valueFilters = buildValueFlowFilters(planner);
|
const valueFilters = buildValueFlowFilters(planner);
|
||||||
const lifecycleFilters = buildLifecycleFilters(planner);
|
const lifecycleFilters = buildLifecycleFilters(planner);
|
||||||
const profileFilters = buildBusinessOverviewProfileFilters(planner);
|
const profileFilters = buildBusinessOverviewProfileFilters(planner);
|
||||||
|
|
@ -5625,6 +5762,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||||
const debtFilters = buildBusinessOverviewDebtFilters(planner);
|
const debtFilters = buildBusinessOverviewDebtFilters(planner);
|
||||||
const debtDueDateAgingProbeEnabled = shouldRunDebtDueDateAgingProbe(planner);
|
const debtDueDateAgingProbeEnabled = shouldRunDebtDueDateAgingProbe(planner);
|
||||||
const inventoryFilters = buildBusinessOverviewInventoryFilters(planner);
|
const inventoryFilters = buildBusinessOverviewInventoryFilters(planner);
|
||||||
|
const inventoryQualityEventsProbeEnabled = shouldRunInventoryQualityEventsProbe(planner);
|
||||||
const debtAsOfDate = toNonEmptyString(debtFilters?.as_of_date);
|
const debtAsOfDate = toNonEmptyString(debtFilters?.as_of_date);
|
||||||
const inventoryAsOfDate = toNonEmptyString(inventoryFilters?.as_of_date);
|
const inventoryAsOfDate = toNonEmptyString(inventoryFilters?.as_of_date);
|
||||||
const incomingSelection = selectAddressRecipe("customer_revenue_and_payments", valueFilters);
|
const incomingSelection = selectAddressRecipe("customer_revenue_and_payments", valueFilters);
|
||||||
|
|
@ -5660,6 +5798,9 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||||
const inventoryAgingSelection = inventoryFilters
|
const inventoryAgingSelection = inventoryFilters
|
||||||
? selectAddressRecipe("inventory_aging_by_purchase_date", inventoryFilters)
|
? selectAddressRecipe("inventory_aging_by_purchase_date", inventoryFilters)
|
||||||
: null;
|
: null;
|
||||||
|
const inventoryQualityEventsSelection = inventoryQualityEventsProbeEnabled
|
||||||
|
? selectAddressRecipe("inventory_quality_events_for_organization", inventoryFilters ?? buildBusinessOverviewProfileFilters(planner))
|
||||||
|
: null;
|
||||||
|
|
||||||
if (!incomingSelection.selected_recipe || !outgoingSelection.selected_recipe || !lifecycleSelection.selected_recipe) {
|
if (!incomingSelection.selected_recipe || !outgoingSelection.selected_recipe || !lifecycleSelection.selected_recipe) {
|
||||||
pushReason(reasonCodes, "pilot_business_overview_recipe_not_available");
|
pushReason(reasonCodes, "pilot_business_overview_recipe_not_available");
|
||||||
|
|
@ -5771,6 +5912,14 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||||
pushReason(reasonCodes, "pilot_business_overview_inventory_recipe_not_available");
|
pushReason(reasonCodes, "pilot_business_overview_inventory_recipe_not_available");
|
||||||
pushUnique(queryLimitations, "Business overview inventory-position probe requires an executable inventory on-hand as-of-date recipe");
|
pushUnique(queryLimitations, "Business overview inventory-position probe requires an executable inventory on-hand as-of-date recipe");
|
||||||
}
|
}
|
||||||
|
if (inventoryQualityEventsSelection?.selected_recipe) {
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_recipe_selected");
|
||||||
|
} else if (!inventoryQualityEventsProbeEnabled) {
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_probe_skipped_without_boundary_need");
|
||||||
|
} else {
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_recipe_not_available");
|
||||||
|
pushUnique(queryLimitations, "Business overview inventory quality probe requires an executable inventory quality-events recipe");
|
||||||
|
}
|
||||||
for (const step of dryRun.execution_steps) {
|
for (const step of dryRun.execution_steps) {
|
||||||
if (step.primitive_id === "query_movements") {
|
if (step.primitive_id === "query_movements") {
|
||||||
const incomingExecution = await executeCoverageAwareValueFlowQuery({
|
const incomingExecution = await executeCoverageAwareValueFlowQuery({
|
||||||
|
|
@ -6007,6 +6156,19 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||||
});
|
});
|
||||||
probeResults.push(queryResultToProbeResult(step.primitive_id, contractUsageProfileResult));
|
probeResults.push(queryResultToProbeResult(step.primitive_id, contractUsageProfileResult));
|
||||||
}
|
}
|
||||||
|
if (inventoryQualityEventsSelection?.selected_recipe) {
|
||||||
|
const inventoryQualityEventsFilters = inventoryFilters ?? buildBusinessOverviewProfileFilters(planner);
|
||||||
|
const inventoryQualityEventsPlan = buildAddressRecipePlan(
|
||||||
|
inventoryQualityEventsSelection.selected_recipe,
|
||||||
|
inventoryQualityEventsFilters
|
||||||
|
);
|
||||||
|
inventoryQualityEventsResult = await runtimeDeps.executeAddressMcpQuery({
|
||||||
|
query: inventoryQualityEventsPlan.query,
|
||||||
|
limit: inventoryQualityEventsPlan.limit,
|
||||||
|
account_scope: inventoryQualityEventsPlan.account_scope
|
||||||
|
});
|
||||||
|
probeResults.push(queryResultToProbeResult(step.primitive_id, inventoryQualityEventsResult));
|
||||||
|
}
|
||||||
if (lifecycleResult.error) {
|
if (lifecycleResult.error) {
|
||||||
pushUnique(queryLimitations, lifecycleResult.error);
|
pushUnique(queryLimitations, lifecycleResult.error);
|
||||||
pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_error");
|
pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_error");
|
||||||
|
|
@ -6037,6 +6199,12 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||||
} else if (contractUsageProfileResult) {
|
} else if (contractUsageProfileResult) {
|
||||||
pushReason(reasonCodes, "pilot_business_overview_contract_usage_profile_query_mcp_executed");
|
pushReason(reasonCodes, "pilot_business_overview_contract_usage_profile_query_mcp_executed");
|
||||||
}
|
}
|
||||||
|
if (inventoryQualityEventsResult?.error) {
|
||||||
|
pushUnique(queryLimitations, inventoryQualityEventsResult.error);
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_query_mcp_error");
|
||||||
|
} else if (inventoryQualityEventsResult) {
|
||||||
|
pushReason(reasonCodes, "pilot_business_overview_inventory_quality_events_query_mcp_executed");
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6061,6 +6229,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||||
debtAsOfDate,
|
debtAsOfDate,
|
||||||
inventoryOnHandResult,
|
inventoryOnHandResult,
|
||||||
inventoryAgingResult,
|
inventoryAgingResult,
|
||||||
|
inventoryQualityEventsResult,
|
||||||
inventoryAsOfDate,
|
inventoryAsOfDate,
|
||||||
organizationScope,
|
organizationScope,
|
||||||
periodScope: dateScope
|
periodScope: dateScope
|
||||||
|
|
@ -6126,6 +6295,10 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||||
if (derivedBusinessOverview.inventory_staleness_risk_proxy) {
|
if (derivedBusinessOverview.inventory_staleness_risk_proxy) {
|
||||||
pushReason(reasonCodes, "pilot_derived_business_overview_inventory_staleness_risk_proxy_from_confirmed_rows");
|
pushReason(reasonCodes, "pilot_derived_business_overview_inventory_staleness_risk_proxy_from_confirmed_rows");
|
||||||
}
|
}
|
||||||
|
if (derivedBusinessOverview.inventory_quality_events) {
|
||||||
|
pushReason(reasonCodes, "pilot_derived_business_overview_inventory_quality_events_from_reviewed_rows");
|
||||||
|
pushReason(reasonCodes, `pilot_derived_business_overview_inventory_quality_events_${derivedBusinessOverview.inventory_quality_events.evidence_status}`);
|
||||||
|
}
|
||||||
if (derivedBusinessOverview.missing_proof_families.length > 0) {
|
if (derivedBusinessOverview.missing_proof_families.length > 0) {
|
||||||
pushReason(reasonCodes, "pilot_business_overview_missing_proof_families_recorded");
|
pushReason(reasonCodes, "pilot_business_overview_missing_proof_families_recorded");
|
||||||
}
|
}
|
||||||
|
|
@ -6145,7 +6318,8 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||||
counterpartyProfileResult,
|
counterpartyProfileResult,
|
||||||
contractUsageProfileResult,
|
contractUsageProfileResult,
|
||||||
inventoryOnHandResult,
|
inventoryOnHandResult,
|
||||||
inventoryAgingResult
|
inventoryAgingResult,
|
||||||
|
inventoryQualityEventsResult
|
||||||
});
|
});
|
||||||
const evidence = resolveAssistantMcpDiscoveryEvidence({
|
const evidence = resolveAssistantMcpDiscoveryEvidence({
|
||||||
plan: planner.discovery_plan,
|
plan: planner.discovery_plan,
|
||||||
|
|
|
||||||
|
|
@ -997,12 +997,20 @@ function buildCompactBusinessOverviewReply(
|
||||||
|
|
||||||
if (inventoryReserveBoundary) {
|
if (inventoryReserveBoundary) {
|
||||||
const headline = toNonEmptyString(draft.headline);
|
const headline = toNonEmptyString(draft.headline);
|
||||||
|
const inventoryQualityEvents = toRecordObject(overview.inventory_quality_events);
|
||||||
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
||||||
lines.push(
|
lines.push(
|
||||||
cleanHeadline
|
cleanHeadline
|
||||||
? `Коротко: ${localizeLine(cleanHeadline)}`
|
? `Коротко: ${localizeLine(cleanHeadline)}`
|
||||||
: "Коротко: точно подтвердить резерв под неликвиды по текущим данным нельзя."
|
: "Коротко: точно подтвердить резерв под неликвиды по текущим данным нельзя."
|
||||||
);
|
);
|
||||||
|
if (inventoryQualityEvents) {
|
||||||
|
if (limitLine) {
|
||||||
|
lines.push(limitLine);
|
||||||
|
}
|
||||||
|
const reply = lines.join("\n").trim();
|
||||||
|
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||||
|
}
|
||||||
const boundaryLines = userFacingLines([
|
const boundaryLines = userFacingLines([
|
||||||
...toStringList(draft.unknown_lines),
|
...toStringList(draft.unknown_lines),
|
||||||
...toStringList(draft.limitation_lines)
|
...toStringList(draft.limitation_lines)
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ export type AddressIntent =
|
||||||
| "inventory_profitability_for_item"
|
| "inventory_profitability_for_item"
|
||||||
| "inventory_purchase_to_sale_chain"
|
| "inventory_purchase_to_sale_chain"
|
||||||
| "inventory_aging_by_purchase_date"
|
| "inventory_aging_by_purchase_date"
|
||||||
|
| "inventory_quality_events_for_organization"
|
||||||
| "account_balance_snapshot"
|
| "account_balance_snapshot"
|
||||||
| "open_items_by_counterparty_or_contract"
|
| "open_items_by_counterparty_or_contract"
|
||||||
| "list_documents_by_counterparty"
|
| "list_documents_by_counterparty"
|
||||||
|
|
@ -204,7 +205,8 @@ export interface AddressRecipeDefinition {
|
||||||
| "inventory_trading_margin_proxy_profile"
|
| "inventory_trading_margin_proxy_profile"
|
||||||
| "inventory_profitability_profile"
|
| "inventory_profitability_profile"
|
||||||
| "inventory_purchase_to_sale_chain_profile"
|
| "inventory_purchase_to_sale_chain_profile"
|
||||||
| "inventory_aging_by_purchase_date_profile";
|
| "inventory_aging_by_purchase_date_profile"
|
||||||
|
| "inventory_quality_events_profile";
|
||||||
required_filters: Array<keyof AddressFilterSet>;
|
required_filters: Array<keyof AddressFilterSet>;
|
||||||
optional_filters: Array<keyof AddressFilterSet>;
|
optional_filters: Array<keyof AddressFilterSet>;
|
||||||
default_limit: number;
|
default_limit: number;
|
||||||
|
|
|
||||||
|
|
@ -710,10 +710,14 @@ describe("assistant MCP discovery answer adapter", () => {
|
||||||
const draft = buildAssistantMcpDiscoveryAnswerDraft(pilot);
|
const draft = buildAssistantMcpDiscoveryAnswerDraft(pilot);
|
||||||
|
|
||||||
expect(draft.headline).toContain(
|
expect(draft.headline).toContain(
|
||||||
"\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c \u0440\u0435\u0437\u0435\u0440\u0432"
|
"\u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b \u0441\u043a\u043b\u0430\u0434\u0441\u043a\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b"
|
||||||
|
);
|
||||||
|
expect(draft.headline).toContain(
|
||||||
|
"\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439"
|
||||||
|
);
|
||||||
|
expect(draft.headline).toContain(
|
||||||
|
"\u043d\u0435 \u0440\u044b\u043d\u043e\u0447\u043d\u0430\u044f \u043b\u0438\u043a\u0432\u0438\u0434\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c"
|
||||||
);
|
);
|
||||||
expect(draft.headline).toContain("\u043d\u0435\u043b\u044c\u0437\u044f");
|
|
||||||
expect(draft.headline).toContain("staleness-risk proxy");
|
|
||||||
expect(draft.headline).not.toContain("бизнес-обзор");
|
expect(draft.headline).not.toContain("бизнес-обзор");
|
||||||
expect(draft.must_not_claim).toContain("Do not present business overview inventory staleness risk proxy as confirmed obsolete stock, reserve, write-off, or liquidation value.");
|
expect(draft.must_not_claim).toContain("Do not present business overview inventory staleness risk proxy as confirmed obsolete stock, reserve, write-off, or liquidation value.");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -475,7 +475,7 @@ describe("assistant MCP discovery runtime bridge", () => {
|
||||||
expect(userFacing).not.toContain("MCP discovery pilot");
|
expect(userFacing).not.toContain("MCP discovery pilot");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("marks exact business-overview proof gaps as route enablement instead of reviewed execution", async () => {
|
it("promotes inventory reserve boundary after reviewed quality-event route executes", async () => {
|
||||||
const deps = buildSequentialDeps([
|
const deps = buildSequentialDeps([
|
||||||
{ rows: [{ Period: "2020-01-15T00:00:00", Amount: 120000, Counterparty: "Client A" }] },
|
{ rows: [{ Period: "2020-01-15T00:00:00", Amount: 120000, Counterparty: "Client A" }] },
|
||||||
{ rows: [{ Period: "2020-01-20T00:00:00", Amount: 50000, Counterparty: "Supplier A" }] },
|
{ rows: [{ Period: "2020-01-20T00:00:00", Amount: 50000, Counterparty: "Supplier A" }] },
|
||||||
|
|
@ -548,20 +548,21 @@ describe("assistant MCP discovery runtime bridge", () => {
|
||||||
expect(result.bridge_status).toBe("answer_draft_ready");
|
expect(result.bridge_status).toBe("answer_draft_ready");
|
||||||
expect(result.business_fact_answer_allowed).toBe(true);
|
expect(result.business_fact_answer_allowed).toBe(true);
|
||||||
expect(result.route_candidate).toMatchObject({
|
expect(result.route_candidate).toMatchObject({
|
||||||
candidate_status: "needs_route_enablement",
|
candidate_status: "ready_for_reviewed_execution",
|
||||||
selected_chain_id: "business_overview",
|
selected_chain_id: "business_overview",
|
||||||
business_fact_family: "business_overview",
|
business_fact_family: "business_overview",
|
||||||
action_family: "inventory_reserve_boundary",
|
action_family: "inventory_reserve_boundary",
|
||||||
executable_now: false
|
executable_now: true,
|
||||||
|
enablement_reason: null
|
||||||
});
|
});
|
||||||
expect(result.route_candidate.enablement_reason).toContain("inventory_reserve_liquidation_quality");
|
expect(result.pilot.derived_business_overview?.inventory_quality_events?.evidence_status).toBe(
|
||||||
expect(result.route_candidate.enablement_reason).toContain(
|
"reviewed_no_quality_events_found"
|
||||||
"reviewed_inventory_quality_route_with_reserves_writeoffs_obsolescence_and_liquidation_value"
|
|
||||||
);
|
);
|
||||||
expect(result.route_candidate.forbidden_overclaim_flags).toContain(
|
expect(result.pilot.derived_business_overview?.missing_proof_families.map((item) => item.family)).not.toContain(
|
||||||
"confirmed_obsolete_stock_reserve_writeoff_or_liquidation_value"
|
"inventory_reserve_liquidation_quality"
|
||||||
);
|
);
|
||||||
expect(result.reason_codes).toContain("runtime_bridge_route_candidate_needs_route_enablement");
|
expect(result.answer_draft.reason_codes).toContain("answer_contains_business_overview_inventory_quality_events");
|
||||||
|
expect(result.reason_codes).toContain("runtime_bridge_route_candidate_ready_for_reviewed_execution");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("promotes profit-margin boundary when accounting 90/91/99 proof is available", async () => {
|
it("promotes profit-margin boundary when accounting 90/91/99 proof is available", async () => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,47 @@
|
||||||
[
|
[
|
||||||
|
{
|
||||||
|
"generation_id": "gen-ag05122057-c9786e",
|
||||||
|
"created_at": "2026-05-12T20:57:28+00:00",
|
||||||
|
"mode": "saved_user_sessions",
|
||||||
|
"title": "AGENT | Phase 96 inventory reserve/liquidation quality-events",
|
||||||
|
"count": 2,
|
||||||
|
"domain": "address_phase96_inventory_reserve_liquidation_quality",
|
||||||
|
"questions": [
|
||||||
|
"По ООО Альтернатива Плюс за 2020 год проверь склад: были ли списания товаров, оприходования/корректировки, инвентаризации, переоценки, резервы под неликвиды или ликвидационная стоимость? Скажи коротко и честно, что подтверждено 1С, а что нельзя утверждать.",
|
||||||
|
"А по этим же данным можно сказать, что склад ликвидный и неликвидов нет?"
|
||||||
|
],
|
||||||
|
"generated_by": "Codex",
|
||||||
|
"saved_case_set_file": "assistant_autogen_saved_user_sessions_20260512205728_gen-ag05122057-c9786e.json",
|
||||||
|
"context": {
|
||||||
|
"llm_provider": null,
|
||||||
|
"model": null,
|
||||||
|
"assistant_prompt_version": null,
|
||||||
|
"decomposition_prompt_version": null,
|
||||||
|
"prompt_fingerprint": null,
|
||||||
|
"autogen_personality_id": null,
|
||||||
|
"autogen_personality_prompt": null,
|
||||||
|
"source_session_id": null,
|
||||||
|
"saved_session_file": "assistant_saved_session_20260512205728_gen-ag05122057-c9786e.json",
|
||||||
|
"saved_case_set_kind": "agent_semantic_scenario",
|
||||||
|
"agent_run": true,
|
||||||
|
"agent_focus": "inventory_reserve_liquidation_quality",
|
||||||
|
"architecture_phase": "Route-Candidate-Driven Enablement Loop",
|
||||||
|
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\address_truth_harness_phase96_inventory_reserve_liquidation_quality.json",
|
||||||
|
"scenario_id": "address_truth_harness_phase96_inventory_reserve_liquidation_quality",
|
||||||
|
"semantic_tags": [
|
||||||
|
"direct_answer_first",
|
||||||
|
"followup_context_carryover",
|
||||||
|
"inventory_liquidity_boundary",
|
||||||
|
"inventory_reserve_liquidation_quality",
|
||||||
|
"no_inventory_health_overclaim",
|
||||||
|
"no_market_liquidation_overclaim",
|
||||||
|
"reviewed_inventory_quality_events"
|
||||||
|
],
|
||||||
|
"validation_status": "accepted_live_replay",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\phase96_inventory_reserve_liquidation_quality_rerun",
|
||||||
|
"saved_after_validated_replay": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"generation_id": "gen-ag05121628-50ea6c",
|
"generation_id": "gen-ag05121628-50ea6c",
|
||||||
"created_at": "2026-05-12T16:28:41+00:00",
|
"created_at": "2026-05-12T16:28:41+00:00",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
{
|
||||||
|
"saved_at": "2026-05-12T20:57:28+00:00",
|
||||||
|
"generation_id": "gen-ag05122057-c9786e",
|
||||||
|
"mode": "saved_user_sessions",
|
||||||
|
"title": "AGENT | Phase 96 inventory reserve/liquidation quality-events",
|
||||||
|
"agent_run": true,
|
||||||
|
"questions": [
|
||||||
|
"По ООО Альтернатива Плюс за 2020 год проверь склад: были ли списания товаров, оприходования/корректировки, инвентаризации, переоценки, резервы под неликвиды или ликвидационная стоимость? Скажи коротко и честно, что подтверждено 1С, а что нельзя утверждать.",
|
||||||
|
"А по этим же данным можно сказать, что склад ликвидный и неликвидов нет?"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"assistant_prompt_version": null,
|
||||||
|
"decomposition_prompt_version": null,
|
||||||
|
"prompt_fingerprint": null,
|
||||||
|
"agent_focus": "inventory_reserve_liquidation_quality",
|
||||||
|
"architecture_phase": "Route-Candidate-Driven Enablement Loop",
|
||||||
|
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\address_truth_harness_phase96_inventory_reserve_liquidation_quality.json",
|
||||||
|
"scenario_id": "address_truth_harness_phase96_inventory_reserve_liquidation_quality",
|
||||||
|
"semantic_tags": [
|
||||||
|
"direct_answer_first",
|
||||||
|
"followup_context_carryover",
|
||||||
|
"inventory_liquidity_boundary",
|
||||||
|
"inventory_reserve_liquidation_quality",
|
||||||
|
"no_inventory_health_overclaim",
|
||||||
|
"no_market_liquidation_overclaim",
|
||||||
|
"reviewed_inventory_quality_events"
|
||||||
|
],
|
||||||
|
"validation_status": "accepted_live_replay",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\phase96_inventory_reserve_liquidation_quality_rerun",
|
||||||
|
"saved_after_validated_replay": true,
|
||||||
|
"save_gate": {
|
||||||
|
"schema_version": "agent_semantic_save_gate_v1",
|
||||||
|
"validation_status": "accepted_live_replay",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\phase96_inventory_reserve_liquidation_quality_rerun",
|
||||||
|
"final_status": "accepted",
|
||||||
|
"review_overall_status": "pass",
|
||||||
|
"business_overall_status": "pass",
|
||||||
|
"steps_total": 2,
|
||||||
|
"steps_passed": 2,
|
||||||
|
"steps_failed": 0,
|
||||||
|
"steps_with_business_failures": 0,
|
||||||
|
"steps_with_business_warnings": 0,
|
||||||
|
"acceptance_gate_passed": true,
|
||||||
|
"saved_after_validated_replay": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source_session_id": null,
|
||||||
|
"session": {
|
||||||
|
"session_id": null,
|
||||||
|
"mode": "agent_semantic_run",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-001",
|
||||||
|
"role": "user",
|
||||||
|
"text": "По ООО Альтернатива Плюс за 2020 год проверь склад: были ли списания товаров, оприходования/корректировки, инвентаризации, переоценки, резервы под неликвиды или ликвидационная стоимость? Скажи коротко и честно, что подтверждено 1С, а что нельзя утверждать.",
|
||||||
|
"created_at": "2026-05-12T20:57:28+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-002",
|
||||||
|
"role": "user",
|
||||||
|
"text": "А по этим же данным можно сказать, что склад ликвидный и неликвидов нет?",
|
||||||
|
"created_at": "2026-05-12T20:57:28+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"agent_run": true,
|
||||||
|
"metadata": {
|
||||||
|
"assistant_prompt_version": null,
|
||||||
|
"decomposition_prompt_version": null,
|
||||||
|
"prompt_fingerprint": null,
|
||||||
|
"agent_focus": "inventory_reserve_liquidation_quality",
|
||||||
|
"architecture_phase": "Route-Candidate-Driven Enablement Loop",
|
||||||
|
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\address_truth_harness_phase96_inventory_reserve_liquidation_quality.json",
|
||||||
|
"scenario_id": "address_truth_harness_phase96_inventory_reserve_liquidation_quality",
|
||||||
|
"semantic_tags": [
|
||||||
|
"direct_answer_first",
|
||||||
|
"followup_context_carryover",
|
||||||
|
"inventory_liquidity_boundary",
|
||||||
|
"inventory_reserve_liquidation_quality",
|
||||||
|
"no_inventory_health_overclaim",
|
||||||
|
"no_market_liquidation_overclaim",
|
||||||
|
"reviewed_inventory_quality_events"
|
||||||
|
],
|
||||||
|
"validation_status": "accepted_live_replay",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\phase96_inventory_reserve_liquidation_quality_rerun",
|
||||||
|
"saved_after_validated_replay": true,
|
||||||
|
"save_gate": {
|
||||||
|
"schema_version": "agent_semantic_save_gate_v1",
|
||||||
|
"validation_status": "accepted_live_replay",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\phase96_inventory_reserve_liquidation_quality_rerun",
|
||||||
|
"final_status": "accepted",
|
||||||
|
"review_overall_status": "pass",
|
||||||
|
"business_overall_status": "pass",
|
||||||
|
"steps_total": 2,
|
||||||
|
"steps_passed": 2,
|
||||||
|
"steps_failed": 0,
|
||||||
|
"steps_with_business_failures": 0,
|
||||||
|
"steps_with_business_warnings": 0,
|
||||||
|
"acceptance_gate_passed": true,
|
||||||
|
"saved_after_validated_replay": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"suite_id": "assistant_saved_session_gen-ag05122057-c9786e",
|
||||||
|
"suite_version": "0.1.0",
|
||||||
|
"schema_version": "assistant_saved_session_suite_v0_1",
|
||||||
|
"generated_at": "2026-05-12T20:57:28+00:00",
|
||||||
|
"generation_id": "gen-ag05122057-c9786e",
|
||||||
|
"mode": "saved_user_sessions",
|
||||||
|
"title": "AGENT | Phase 96 inventory reserve/liquidation quality-events",
|
||||||
|
"domain": "address_phase96_inventory_reserve_liquidation_quality",
|
||||||
|
"scenario_count": 1,
|
||||||
|
"case_ids": [
|
||||||
|
"SAVED-001"
|
||||||
|
],
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"case_id": "SAVED-001",
|
||||||
|
"scenario_tag": "agent_saved_user_sessions",
|
||||||
|
"title": "AGENT | Phase 96 inventory reserve/liquidation quality-events",
|
||||||
|
"question_type": "followup",
|
||||||
|
"broadness_level": "medium",
|
||||||
|
"turns": [
|
||||||
|
{
|
||||||
|
"user_message": "По ООО Альтернатива Плюс за 2020 год проверь склад: были ли списания товаров, оприходования/корректировки, инвентаризации, переоценки, резервы под неликвиды или ликвидационная стоимость? Скажи коротко и честно, что подтверждено 1С, а что нельзя утверждать."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "А по этим же данным можно сказать, что склад ликвидный и неликвидов нет?"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue