Закрыть 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: `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.
|
||||
- Current live canary: `phase95_vendor_procurement_quality_reviewed_route_live2` accepted `7/7`.
|
||||
- Current accepted autorun: `AGENT | Phase 95 vendor/procurement quality reviewed route` (`gen-ag05121357-9ea5d6`).
|
||||
- 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 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)`.
|
||||
- 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)`.
|
||||
|
||||
## 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% (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.
|
||||
- `Прогресс модуля: 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.
|
||||
- `Прогресс модуля: 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;
|
||||
- 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;
|
||||
- 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;
|
||||
- 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;
|
||||
|
|
@ -156,17 +157,19 @@ For current planning, read:
|
|||
|
||||
1. `README.md`
|
||||
2. this document
|
||||
3. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
||||
4. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
||||
5. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
||||
6. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
||||
7. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
||||
8. `24 - agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md`
|
||||
9. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md`
|
||||
10. `22 - open_world_bounded_autonomy_breadth_2026-05-01.md`
|
||||
11. `20 - planner_autonomy_consolidation_2026-05-01.md`
|
||||
12. `19 - inventory_stock_open_world_breadth_proof_2026-05-01.md`
|
||||
13. `17 - post_f_semantic_integrity_hardening_2026-04-23.md`
|
||||
14. `16 - data_need_graph_and_open_world_mcp_plan_2026-04-22.md`
|
||||
3. `31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md`
|
||||
4. `30 - vendor_procurement_quality_reviewed_route_2026-05-12.md`
|
||||
5. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
||||
6. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
||||
7. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
||||
8. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
||||
9. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
||||
10. `24 - agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md`
|
||||
11. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md`
|
||||
12. `22 - open_world_bounded_autonomy_breadth_2026-05-01.md`
|
||||
13. `20 - planner_autonomy_consolidation_2026-05-01.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.
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ Status:
|
|||
- 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;
|
||||
- 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.
|
||||
|
||||
Recommended reporting line:
|
||||
|
|
@ -113,16 +113,16 @@ Still open:
|
|||
- 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;
|
||||
- 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.
|
||||
|
||||
## Next Work
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## Canonical Reading Order Update
|
||||
|
|
@ -131,13 +131,15 @@ For current planning, read:
|
|||
|
||||
1. `README.md`
|
||||
2. `21 - current_status_canon_2026-05-01.md`
|
||||
3. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
||||
4. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
||||
5. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
||||
6. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
||||
7. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
||||
8. this document
|
||||
9. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md`
|
||||
10. `22 - open_world_bounded_autonomy_breadth_2026-05-01.md`
|
||||
11. `20 - planner_autonomy_consolidation_2026-05-01.md`
|
||||
12. `17 - post_f_semantic_integrity_hardening_2026-04-23.md`
|
||||
3. `31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md`
|
||||
4. `30 - vendor_procurement_quality_reviewed_route_2026-05-12.md`
|
||||
5. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
||||
6. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
||||
7. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
||||
8. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
||||
9. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
||||
10. this document
|
||||
11. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.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`).
|
||||
- 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`).
|
||||
- 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:
|
||||
|
||||
|
|
@ -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 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 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
|
||||
|
||||
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 slices:
|
||||
|
||||
1. Pick the final phase92 proof family: `inventory_reserve_liquidation_quality`.
|
||||
2. Implement or explicitly bound that final family only if reliable 1C evidence is reachable.
|
||||
3. Rerun phase95 as a canary plus the focused inventory route-specific pack.
|
||||
4. Save the accepted pack into autoruns only after live replay and semantic review pass.
|
||||
1. Treat this module as closed and keep phase91/92/93/94/95/96 as regression canaries.
|
||||
2. Start the next broader open-world autonomy slice: schema/primitive discovery beyond the selected phase92 proof families.
|
||||
3. Keep save-after-acceptance discipline for any new AGENT packs.
|
||||
|
||||
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)
|
||||
- [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)
|
||||
- [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:
|
||||
|
||||
`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 slices:
|
||||
|
||||
1. Wire or explicitly bound the final remaining family: `inventory_reserve_liquidation_quality`.
|
||||
2. Keep proxy-only inventory reserve/liquidation wording bounded until reviewed evidence exists.
|
||||
3. Rerun phase95 as a canary plus the focused inventory route-specific pack.
|
||||
4. Save the next AGENT autorun only after live replay and semantic review pass.
|
||||
1. Use phase91-phase96 as regression canaries.
|
||||
2. Start the next broader open-world schema/primitive discovery module.
|
||||
3. Keep saving AGENT autoruns only after live replay and semantic review pass.
|
||||
|
||||
See also:
|
||||
|
||||
- [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)
|
||||
- [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:
|
||||
|
||||
`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 slices:
|
||||
|
||||
1. Select the remaining proof family: `inventory_reserve_liquidation_quality`.
|
||||
2. Wire only the smallest reliable reviewed route, not a broad heuristic.
|
||||
3. Keep proxy-only reserve/liquidation wording bounded until the route is accepted.
|
||||
1. Use this route as a regression canary during broader autonomy work.
|
||||
2. Continue the next module through open-world schema/primitive discovery rather than more phase92 proof-family closure.
|
||||
3. Keep proof-specific wording bounded unless a reviewed route has live evidence.
|
||||
|
|
|
|||
|
|
@ -77,17 +77,16 @@ The accepted replay proves:
|
|||
|
||||
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 slices:
|
||||
|
||||
1. Identify whether reliable 1C evidence exists for `inventory_reserve_liquidation_quality`.
|
||||
2. Wire the smallest reviewed route only if it can prove the inventory business claim without overreach.
|
||||
3. Keep proxy-only evidence bounded if exact proof is not reachable.
|
||||
4. Rerun phase95 as a canary plus the focused inventory route-specific pack.
|
||||
1. Use phase94, phase95, and phase96 as canaries for due-date, vendor, and inventory-quality continuity.
|
||||
2. Move the active plan to broader open-world schema/primitive discovery.
|
||||
3. Keep proxy-only evidence bounded when a reviewed route is not available.
|
||||
|
|
|
|||
|
|
@ -62,29 +62,29 @@ Semantic/live replay:
|
|||
|
||||
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;
|
||||
- `debt_due_date_aging_quality` accepted live by phase94;
|
||||
- `vendor_risk_procurement_quality` accepted live through procurement-concentration evidence by phase95.
|
||||
|
||||
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.
|
||||
- `inventory_reserve_liquidation_quality` accepted live through inventory quality-event evidence by phase96.
|
||||
|
||||
## Next Work
|
||||
|
||||
Next slices:
|
||||
|
||||
1. Select the final remaining phase92 family: `inventory_reserve_liquidation_quality`.
|
||||
2. Determine whether reachable 1C evidence can prove reserve/write-off/liquidation quality without overreach.
|
||||
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.
|
||||
1. Use phase95 as a vendor/procurement regression canary during broader autonomy work.
|
||||
2. See phase96 for the final inventory reserve/liquidation route and module closure.
|
||||
|
||||
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)
|
||||
- [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)
|
||||
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)
|
||||
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.
|
||||
|
||||
|
|
@ -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 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 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 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 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 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 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 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 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 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 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 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 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 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 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:
|
||||
|
||||
|
|
@ -176,13 +180,13 @@ Current honest status:
|
|||
- pre-multidomain readiness: `~90%`
|
||||
- bounded-autonomy foundation readiness: `~89%`
|
||||
- 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
|
||||
- Post-F semantic integrity module progress: `~99%` operationally closed, with remaining risk now treated as next-slice discovery rather than an open blocker inside the closed slice
|
||||
- active inventory-stock breadth slice progress: `100%` for the declared scenario pack, not for arbitrary inventory questions
|
||||
- Planner Autonomy Consolidation progress: `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
|
||||
- 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`
|
||||
- current regression-gate breakpoint:
|
||||
- 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`).
|
||||
- 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`).
|
||||
- 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:
|
||||
|
||||
|
|
@ -351,6 +356,7 @@ Read in this order:
|
|||
29. `28 - accounting_profit_margin_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`
|
||||
32. `31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md`
|
||||
|
||||
## 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__
|
||||
`;
|
||||
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 = `
|
||||
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||
БанкСписание.Дата КАК Период,
|
||||
|
|
@ -933,6 +988,16 @@ const BASE_RECIPES = [
|
|||
account_scope_mode: "strict",
|
||||
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",
|
||||
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))))
|
||||
.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) {
|
||||
const item = typeof filters.item === "string" ? filters.item.trim() : "";
|
||||
if (!item) {
|
||||
|
|
@ -1599,6 +1706,7 @@ function maxLimitForIntent(intent) {
|
|||
intent === "inventory_profitability_for_item" ||
|
||||
intent === "inventory_purchase_to_sale_chain" ||
|
||||
intent === "inventory_aging_by_purchase_date" ||
|
||||
intent === "inventory_quality_events_for_organization" ||
|
||||
intent === "open_contracts_confirmed_as_of_date" ||
|
||||
intent === "list_contracts_by_counterparty" ||
|
||||
intent === "list_documents_by_counterparty" ||
|
||||
|
|
@ -1790,6 +1898,8 @@ function buildAddressRecipePlan(recipe, filters) {
|
|||
? buildInventoryPurchaseToSaleDocumentQuery(filters, resolvedLimit)
|
||||
: recipe.query_template === "inventory_aging_by_purchase_date_profile"
|
||||
? buildInventoryMovementQuery(filters, resolvedLimit, "dt")
|
||||
: recipe.query_template === "inventory_quality_events_profile"
|
||||
? buildInventoryQualityEventsQuery(filters, resolvedLimit)
|
||||
: recipe.query_template === "contracts_by_counterparty_profile"
|
||||
? CONTRACTS_BY_COUNTERPARTY_QUERY_TEMPLATE.replaceAll("__LIMIT__", String(resolvedLimit))
|
||||
: 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";
|
||||
}
|
||||
function businessOverviewInventoryUnknownLabel(overview) {
|
||||
if (overview.inventory_quality_events) {
|
||||
return "рыночная ликвидационная стоимость и управленческий резерв склада";
|
||||
}
|
||||
if (overview.inventory_staleness_risk_proxy) {
|
||||
return "резервы/списания/ликвидационная стоимость склада";
|
||||
}
|
||||
|
|
@ -621,6 +624,24 @@ function businessOverviewVendorProcurementQualityText(overview) {
|
|||
}
|
||||
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) {
|
||||
const askedMonthlyBreakdown = pilot.derived_bidirectional_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 маршрута по договорам, срокам оплаты и погашению расчетов.";
|
||||
}
|
||||
if (isInventoryReserveBoundaryTurn(pilot)) {
|
||||
const inventoryQualityEventsText = businessOverviewInventoryQualityEventsText(overview);
|
||||
if (inventoryQualityEventsText) {
|
||||
return inventoryQualityEventsText;
|
||||
}
|
||||
const inventoryBasis = overview.inventory_staleness_risk_proxy
|
||||
? "есть только складской staleness-risk proxy по найденным строкам"
|
||||
: overview.inventory_position || overview.inventory_turnover_proxy
|
||||
|
|
@ -724,6 +749,9 @@ function headlineFor(mode, pilot) {
|
|||
if (overview.inventory_staleness_risk_proxy) {
|
||||
families.push("staleness risk proxy склада");
|
||||
}
|
||||
if (overview.inventory_quality_events) {
|
||||
families.push("складские quality-события");
|
||||
}
|
||||
const unknownFamilies = overview.accounting_financial_result
|
||||
? ["аудированная/юридически подтвержденная прибыль"]
|
||||
: [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 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.");
|
||||
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) ||
|
||||
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.");
|
||||
|
|
@ -1436,6 +1467,10 @@ function derivedBusinessOverviewConfirmedLines(pilot) {
|
|||
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)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`);
|
||||
}
|
||||
const inventoryQualityEventsText = businessOverviewInventoryQualityEventsText(overview);
|
||||
if (inventoryQualityEventsText) {
|
||||
lines.push(inventoryQualityEventsText.replace(/^Коротко:\s*/u, ""));
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
function businessOverviewCashSynthesisLine(overview) {
|
||||
|
|
@ -1603,6 +1638,15 @@ function businessOverviewRiskSynthesisLine(overview) {
|
|||
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} дн.`);
|
||||
}
|
||||
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
|
||||
? `Риски и контуры внимания по подтвержденным данным: ${signals.join("; ")}.`
|
||||
: null;
|
||||
|
|
@ -1616,7 +1660,8 @@ function businessOverviewExecutiveVerdictLine(overview) {
|
|||
overview.debt_staleness_risk_proxy ||
|
||||
overview.inventory_position ||
|
||||
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 hasExtraSignals = hasTaxDebtInventorySignals || hasOperationalProfileSignal;
|
||||
if (!hasCash && !hasExtraSignals) {
|
||||
|
|
@ -1750,6 +1795,10 @@ function buildAssistantMcpDiscoveryAnswerDraft(pilot) {
|
|||
if (pilot.derived_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) {
|
||||
pushReason(reasonCodes, "answer_contains_business_overview_missing_proof_ledger");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,6 +211,16 @@ function shouldRunDebtDueDateAgingProbe(planner) {
|
|||
.join(" ");
|
||||
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) {
|
||||
const meaning = planner.discovery_plan.turn_meaning_ref;
|
||||
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"
|
||||
};
|
||||
}
|
||||
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) {
|
||||
if (!input.rankedOutgoing ||
|
||||
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"
|
||||
});
|
||||
}
|
||||
if (missing.has("inventory_position") ||
|
||||
if ((missing.has("inventory_position") ||
|
||||
missing.has("inventory_turnover_quality") ||
|
||||
missing.has("inventory_liquidity_quality") ||
|
||||
missing.has("inventory_reserve_liquidation_quality")) {
|
||||
missing.has("inventory_reserve_liquidation_quality")) && !input.inventoryQualityEvents) {
|
||||
pushUnique({
|
||||
family: "inventory_reserve_liquidation_quality",
|
||||
current_status: input.inventoryStalenessRiskProxy
|
||||
|
|
@ -3195,6 +3268,10 @@ function deriveBusinessOverview(input) {
|
|||
inventoryPosition,
|
||||
inventoryTurnoverProxy
|
||||
});
|
||||
const inventoryQualityEvents = deriveBusinessOverviewInventoryQualityEvents({
|
||||
inventoryQualityEventsResult: input.inventoryQualityEventsResult,
|
||||
periodScope: input.periodScope
|
||||
});
|
||||
const vendorProcurementQuality = deriveBusinessOverviewVendorProcurementQuality({
|
||||
rankedOutgoing,
|
||||
outgoing,
|
||||
|
|
@ -3219,6 +3296,7 @@ function deriveBusinessOverview(input) {
|
|||
Boolean(inventoryPosition),
|
||||
Boolean(inventoryTurnoverProxy),
|
||||
Boolean(inventoryStalenessRiskProxy),
|
||||
Boolean(inventoryQualityEvents),
|
||||
Boolean(vendorProcurementQuality)
|
||||
].filter(Boolean).length;
|
||||
if (checkedSignalCount <= 0) {
|
||||
|
|
@ -3232,7 +3310,9 @@ function deriveBusinessOverview(input) {
|
|||
debtDueDateAging ? null : debtOpenSettlementQuality ? "debt_due_date_aging_quality" : "debt_open_settlement_quality",
|
||||
taxPosition ? null : "tax_position",
|
||||
inventoryPosition
|
||||
? inventoryStalenessRiskProxy
|
||||
? inventoryQualityEvents
|
||||
? null
|
||||
: inventoryStalenessRiskProxy
|
||||
? "inventory_reserve_liquidation_quality"
|
||||
: inventoryTurnoverProxy
|
||||
? "inventory_liquidity_quality"
|
||||
|
|
@ -3250,6 +3330,7 @@ function deriveBusinessOverview(input) {
|
|||
inventoryPosition,
|
||||
inventoryTurnoverProxy,
|
||||
inventoryStalenessRiskProxy,
|
||||
inventoryQualityEvents,
|
||||
vendorProcurementQuality,
|
||||
hasSupplierConcentrationSignal: (rankedOutgoing?.ranked_values.length ?? 0) > 0
|
||||
});
|
||||
|
|
@ -3275,6 +3356,7 @@ function deriveBusinessOverview(input) {
|
|||
inventory_position: inventoryPosition,
|
||||
inventory_turnover_proxy: inventoryTurnoverProxy,
|
||||
inventory_staleness_risk_proxy: inventoryStalenessRiskProxy,
|
||||
inventory_quality_events: inventoryQualityEvents,
|
||||
document_activity_profile: documentActivityProfile,
|
||||
counterparty_profile: counterpartyProfile,
|
||||
contract_usage_profile: contractUsageProfile,
|
||||
|
|
@ -3283,7 +3365,7 @@ function deriveBusinessOverview(input) {
|
|||
checked_signal_count: checkedSignalCount,
|
||||
missing_signal_families: missingSignalFamilies,
|
||||
missing_proof_families: missingProofFamilies,
|
||||
inference_basis: hasBusinessOverviewProfileSignal || inventoryPosition || accountingFinancialResult
|
||||
inference_basis: hasBusinessOverviewProfileSignal || inventoryPosition || inventoryQualityEvents || accountingFinancialResult
|
||||
? "business_overview_from_confirmed_1c_multi_family_rows"
|
||||
: debtOpenSettlementQuality || debtDueDateAging
|
||||
? "business_overview_from_confirmed_1c_multi_family_rows"
|
||||
|
|
@ -3343,6 +3425,9 @@ function summarizeBusinessOverviewRows(input) {
|
|||
if (input.inventoryAgingResult && !input.inventoryAgingResult.error) {
|
||||
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;
|
||||
}
|
||||
function buildBusinessOverviewConfirmedFacts(derived) {
|
||||
|
|
@ -3511,6 +3596,18 @@ function buildBusinessOverviewConfirmedFacts(derived) {
|
|||
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)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`);
|
||||
}
|
||||
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;
|
||||
}
|
||||
function buildBusinessOverviewInferredFacts(derived) {
|
||||
|
|
@ -4218,6 +4315,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
|||
let contractUsageProfileResult = null;
|
||||
let inventoryOnHandResult = null;
|
||||
let inventoryAgingResult = null;
|
||||
let inventoryQualityEventsResult = null;
|
||||
const valueFilters = buildValueFlowFilters(planner);
|
||||
const lifecycleFilters = buildLifecycleFilters(planner);
|
||||
const profileFilters = buildBusinessOverviewProfileFilters(planner);
|
||||
|
|
@ -4227,6 +4325,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
|||
const debtFilters = buildBusinessOverviewDebtFilters(planner);
|
||||
const debtDueDateAgingProbeEnabled = shouldRunDebtDueDateAgingProbe(planner);
|
||||
const inventoryFilters = buildBusinessOverviewInventoryFilters(planner);
|
||||
const inventoryQualityEventsProbeEnabled = shouldRunInventoryQualityEventsProbe(planner);
|
||||
const debtAsOfDate = toNonEmptyString(debtFilters?.as_of_date);
|
||||
const inventoryAsOfDate = toNonEmptyString(inventoryFilters?.as_of_date);
|
||||
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
|
||||
? (0, addressRecipeCatalog_1.selectAddressRecipe)("inventory_aging_by_purchase_date", inventoryFilters)
|
||||
: 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) {
|
||||
pushReason(reasonCodes, "pilot_business_overview_recipe_not_available");
|
||||
const missing = [
|
||||
|
|
@ -4389,6 +4491,16 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
|||
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");
|
||||
}
|
||||
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) {
|
||||
if (step.primitive_id === "query_movements") {
|
||||
const incomingExecution = await executeCoverageAwareValueFlowQuery({
|
||||
|
|
@ -4622,6 +4734,16 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
|||
});
|
||||
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) {
|
||||
pushUnique(queryLimitations, lifecycleResult.error);
|
||||
pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_error");
|
||||
|
|
@ -4657,6 +4779,13 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
|||
else if (contractUsageProfileResult) {
|
||||
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;
|
||||
}
|
||||
skippedPrimitives.push(step.primitive_id);
|
||||
|
|
@ -4679,6 +4808,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
|||
debtAsOfDate,
|
||||
inventoryOnHandResult,
|
||||
inventoryAgingResult,
|
||||
inventoryQualityEventsResult,
|
||||
inventoryAsOfDate,
|
||||
organizationScope,
|
||||
periodScope: dateScope
|
||||
|
|
@ -4744,6 +4874,10 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
|||
if (derivedBusinessOverview.inventory_staleness_risk_proxy) {
|
||||
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) {
|
||||
pushReason(reasonCodes, "pilot_business_overview_missing_proof_families_recorded");
|
||||
}
|
||||
|
|
@ -4763,7 +4897,8 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
|||
counterpartyProfileResult,
|
||||
contractUsageProfileResult,
|
||||
inventoryOnHandResult,
|
||||
inventoryAgingResult
|
||||
inventoryAgingResult,
|
||||
inventoryQualityEventsResult
|
||||
});
|
||||
const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({
|
||||
plan: planner.discovery_plan,
|
||||
|
|
|
|||
|
|
@ -830,10 +830,18 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
}
|
||||
if (inventoryReserveBoundary) {
|
||||
const headline = toNonEmptyString(draft.headline);
|
||||
const inventoryQualityEvents = toRecordObject(overview.inventory_quality_events);
|
||||
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
||||
lines.push(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([
|
||||
...toStringList(draft.unknown_lines),
|
||||
...toStringList(draft.limitation_lines)
|
||||
|
|
|
|||
|
|
@ -296,6 +296,62 @@ const INVENTORY_ON_HAND_AS_OF_QUERY_TEMPLATE = `
|
|||
Количество __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 = `
|
||||
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||
БанкСписание.Дата КАК Период,
|
||||
|
|
@ -958,6 +1014,16 @@ const BASE_RECIPES: AddressRecipeDefinition[] = [
|
|||
account_scope_mode: "strict",
|
||||
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",
|
||||
intent: "open_contracts_confirmed_as_of_date",
|
||||
|
|
@ -1432,6 +1498,77 @@ function buildInventoryMovementQuery(
|
|||
.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 {
|
||||
const item = typeof filters.item === "string" ? filters.item.trim() : "";
|
||||
if (!item) {
|
||||
|
|
@ -1783,6 +1920,7 @@ function maxLimitForIntent(intent: AddressIntent): number {
|
|||
intent === "inventory_profitability_for_item" ||
|
||||
intent === "inventory_purchase_to_sale_chain" ||
|
||||
intent === "inventory_aging_by_purchase_date" ||
|
||||
intent === "inventory_quality_events_for_organization" ||
|
||||
intent === "open_contracts_confirmed_as_of_date" ||
|
||||
intent === "list_contracts_by_counterparty" ||
|
||||
intent === "list_documents_by_counterparty" ||
|
||||
|
|
@ -2037,6 +2175,8 @@ export function buildAddressRecipePlan(
|
|||
? buildInventoryPurchaseToSaleDocumentQuery(filters, resolvedLimit)
|
||||
: recipe.query_template === "inventory_aging_by_purchase_date_profile"
|
||||
? buildInventoryMovementQuery(filters, resolvedLimit, "dt")
|
||||
: recipe.query_template === "inventory_quality_events_profile"
|
||||
? buildInventoryQualityEventsQuery(filters, resolvedLimit)
|
||||
: recipe.query_template === "contracts_by_counterparty_profile"
|
||||
? CONTRACTS_BY_COUNTERPARTY_QUERY_TEMPLATE.replaceAll("__LIMIT__", String(resolvedLimit))
|
||||
: recipe.query_template === "open_contracts_confirmed_as_of_balance_profile"
|
||||
|
|
|
|||
|
|
@ -510,6 +510,9 @@ function isVendorRiskBoundaryTurn(pilot: AssistantMcpDiscoveryPilotExecutionCont
|
|||
}
|
||||
|
||||
function businessOverviewInventoryUnknownLabel(overview: BusinessOverview): string {
|
||||
if (overview.inventory_quality_events) {
|
||||
return "рыночная ликвидационная стоимость и управленческий резерв склада";
|
||||
}
|
||||
if (overview.inventory_staleness_risk_proxy) {
|
||||
return "резервы/списания/ликвидационная стоимость склада";
|
||||
}
|
||||
|
|
@ -764,6 +767,26 @@ function businessOverviewVendorProcurementQualityText(overview: BusinessOverview
|
|||
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 {
|
||||
const askedMonthlyBreakdown =
|
||||
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 маршрута по договорам, срокам оплаты и погашению расчетов.";
|
||||
}
|
||||
if (isInventoryReserveBoundaryTurn(pilot)) {
|
||||
const inventoryQualityEventsText = businessOverviewInventoryQualityEventsText(overview);
|
||||
if (inventoryQualityEventsText) {
|
||||
return inventoryQualityEventsText;
|
||||
}
|
||||
const inventoryBasis = overview.inventory_staleness_risk_proxy
|
||||
? "есть только складской staleness-risk proxy по найденным строкам"
|
||||
: overview.inventory_position || overview.inventory_turnover_proxy
|
||||
|
|
@ -870,6 +897,9 @@ function headlineFor(mode: AssistantMcpDiscoveryAnswerMode, pilot: AssistantMcpD
|
|||
if (overview.inventory_staleness_risk_proxy) {
|
||||
families.push("staleness risk proxy склада");
|
||||
}
|
||||
if (overview.inventory_quality_events) {
|
||||
families.push("складские quality-события");
|
||||
}
|
||||
const unknownFamilies = overview.accounting_financial_result
|
||||
? ["аудированная/юридически подтвержденная прибыль"]
|
||||
: [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 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.");
|
||||
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) ||
|
||||
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)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`
|
||||
);
|
||||
}
|
||||
const inventoryQualityEventsText = businessOverviewInventoryQualityEventsText(overview);
|
||||
if (inventoryQualityEventsText) {
|
||||
lines.push(inventoryQualityEventsText.replace(/^Коротко:\s*/u, ""));
|
||||
}
|
||||
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} дн.`
|
||||
);
|
||||
}
|
||||
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
|
||||
? `Риски и контуры внимания по подтвержденным данным: ${signals.join("; ")}.`
|
||||
: null;
|
||||
|
|
@ -1873,7 +1920,8 @@ function businessOverviewExecutiveVerdictLine(overview: BusinessOverview): strin
|
|||
overview.debt_staleness_risk_proxy ||
|
||||
overview.inventory_position ||
|
||||
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
|
||||
|
|
@ -2020,6 +2068,10 @@ export function buildAssistantMcpDiscoveryAnswerDraft(
|
|||
if (pilot.derived_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) {
|
||||
pushReason(reasonCodes, "answer_contains_business_overview_missing_proof_ledger");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ export interface AssistantMcpDiscoveryDerivedBusinessOverview {
|
|||
inventory_position: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryPosition | null;
|
||||
inventory_turnover_proxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryTurnoverProxy | null;
|
||||
inventory_staleness_risk_proxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryStalenessRiskProxy | null;
|
||||
inventory_quality_events: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryQualityEvents | null;
|
||||
document_activity_profile: AssistantMcpDiscoveryDerivedBusinessOverviewDocumentActivityProfile | null;
|
||||
counterparty_profile: AssistantMcpDiscoveryDerivedBusinessOverviewCounterpartyProfile | 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";
|
||||
}
|
||||
|
||||
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 {
|
||||
metadata_scope: string | null;
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
const meaning = planner.discovery_plan.turn_meaning_ref;
|
||||
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: {
|
||||
rankedOutgoing: AssistantMcpDiscoveryDerivedRankedValueFlow | null;
|
||||
outgoing: AssistantMcpDiscoveryValueFlowSideSummary;
|
||||
|
|
@ -4226,6 +4331,7 @@ function buildBusinessOverviewMissingProofFamilies(input: {
|
|||
inventoryPosition: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryPosition | null;
|
||||
inventoryTurnoverProxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryTurnoverProxy | null;
|
||||
inventoryStalenessRiskProxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryStalenessRiskProxy | null;
|
||||
inventoryQualityEvents: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryQualityEvents | null;
|
||||
vendorProcurementQuality: AssistantMcpDiscoveryDerivedBusinessOverviewVendorProcurementQuality | null;
|
||||
hasSupplierConcentrationSignal: boolean;
|
||||
}): AssistantMcpDiscoveryBusinessOverviewMissingProofFamily[] {
|
||||
|
|
@ -4267,12 +4373,12 @@ function buildBusinessOverviewMissingProofFamilies(input: {
|
|||
});
|
||||
}
|
||||
|
||||
if (
|
||||
if ((
|
||||
missing.has("inventory_position") ||
|
||||
missing.has("inventory_turnover_quality") ||
|
||||
missing.has("inventory_liquidity_quality") ||
|
||||
missing.has("inventory_reserve_liquidation_quality")
|
||||
) {
|
||||
) && !input.inventoryQualityEvents) {
|
||||
pushUnique({
|
||||
family: "inventory_reserve_liquidation_quality",
|
||||
current_status: input.inventoryStalenessRiskProxy
|
||||
|
|
@ -4322,6 +4428,7 @@ function deriveBusinessOverview(input: {
|
|||
debtAsOfDate: string | null;
|
||||
inventoryOnHandResult: AddressMcpQueryExecutorResult | null;
|
||||
inventoryAgingResult: AddressMcpQueryExecutorResult | null;
|
||||
inventoryQualityEventsResult: AddressMcpQueryExecutorResult | null;
|
||||
inventoryAsOfDate: string | null;
|
||||
organizationScope: string | null;
|
||||
periodScope: string | null;
|
||||
|
|
@ -4390,6 +4497,10 @@ function deriveBusinessOverview(input: {
|
|||
inventoryPosition,
|
||||
inventoryTurnoverProxy
|
||||
});
|
||||
const inventoryQualityEvents = deriveBusinessOverviewInventoryQualityEvents({
|
||||
inventoryQualityEventsResult: input.inventoryQualityEventsResult,
|
||||
periodScope: input.periodScope
|
||||
});
|
||||
const vendorProcurementQuality = deriveBusinessOverviewVendorProcurementQuality({
|
||||
rankedOutgoing,
|
||||
outgoing,
|
||||
|
|
@ -4414,6 +4525,7 @@ function deriveBusinessOverview(input: {
|
|||
Boolean(inventoryPosition),
|
||||
Boolean(inventoryTurnoverProxy),
|
||||
Boolean(inventoryStalenessRiskProxy),
|
||||
Boolean(inventoryQualityEvents),
|
||||
Boolean(vendorProcurementQuality)
|
||||
].filter(Boolean).length;
|
||||
if (checkedSignalCount <= 0) {
|
||||
|
|
@ -4430,7 +4542,9 @@ function deriveBusinessOverview(input: {
|
|||
debtDueDateAging ? null : debtOpenSettlementQuality ? "debt_due_date_aging_quality" : "debt_open_settlement_quality",
|
||||
taxPosition ? null : "tax_position",
|
||||
inventoryPosition
|
||||
? inventoryStalenessRiskProxy
|
||||
? inventoryQualityEvents
|
||||
? null
|
||||
: inventoryStalenessRiskProxy
|
||||
? "inventory_reserve_liquidation_quality"
|
||||
: inventoryTurnoverProxy
|
||||
? "inventory_liquidity_quality"
|
||||
|
|
@ -4448,6 +4562,7 @@ function deriveBusinessOverview(input: {
|
|||
inventoryPosition,
|
||||
inventoryTurnoverProxy,
|
||||
inventoryStalenessRiskProxy,
|
||||
inventoryQualityEvents,
|
||||
vendorProcurementQuality,
|
||||
hasSupplierConcentrationSignal: (rankedOutgoing?.ranked_values.length ?? 0) > 0
|
||||
});
|
||||
|
|
@ -4473,6 +4588,7 @@ function deriveBusinessOverview(input: {
|
|||
inventory_position: inventoryPosition,
|
||||
inventory_turnover_proxy: inventoryTurnoverProxy,
|
||||
inventory_staleness_risk_proxy: inventoryStalenessRiskProxy,
|
||||
inventory_quality_events: inventoryQualityEvents,
|
||||
document_activity_profile: documentActivityProfile,
|
||||
counterparty_profile: counterpartyProfile,
|
||||
contract_usage_profile: contractUsageProfile,
|
||||
|
|
@ -4483,7 +4599,7 @@ function deriveBusinessOverview(input: {
|
|||
missing_signal_families: missingSignalFamilies,
|
||||
missing_proof_families: missingProofFamilies,
|
||||
inference_basis:
|
||||
hasBusinessOverviewProfileSignal || inventoryPosition || accountingFinancialResult
|
||||
hasBusinessOverviewProfileSignal || inventoryPosition || inventoryQualityEvents || accountingFinancialResult
|
||||
? "business_overview_from_confirmed_1c_multi_family_rows"
|
||||
: debtOpenSettlementQuality || debtDueDateAging
|
||||
? "business_overview_from_confirmed_1c_multi_family_rows"
|
||||
|
|
@ -4513,6 +4629,7 @@ function summarizeBusinessOverviewRows(input: {
|
|||
contractUsageProfileResult: AddressMcpQueryExecutorResult | null;
|
||||
inventoryOnHandResult: AddressMcpQueryExecutorResult | null;
|
||||
inventoryAgingResult: AddressMcpQueryExecutorResult | null;
|
||||
inventoryQualityEventsResult: AddressMcpQueryExecutorResult | null;
|
||||
}): string | null {
|
||||
const parts: string[] = [];
|
||||
if (input.incomingResult && !input.incomingResult.error) {
|
||||
|
|
@ -4560,6 +4677,9 @@ function summarizeBusinessOverviewRows(input: {
|
|||
if (input.inventoryAgingResult && !input.inventoryAgingResult.error) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -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)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`
|
||||
);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -5616,6 +5752,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
|||
let contractUsageProfileResult: AddressMcpQueryExecutorResult | null = null;
|
||||
let inventoryOnHandResult: AddressMcpQueryExecutorResult | null = null;
|
||||
let inventoryAgingResult: AddressMcpQueryExecutorResult | null = null;
|
||||
let inventoryQualityEventsResult: AddressMcpQueryExecutorResult | null = null;
|
||||
const valueFilters = buildValueFlowFilters(planner);
|
||||
const lifecycleFilters = buildLifecycleFilters(planner);
|
||||
const profileFilters = buildBusinessOverviewProfileFilters(planner);
|
||||
|
|
@ -5625,6 +5762,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
|||
const debtFilters = buildBusinessOverviewDebtFilters(planner);
|
||||
const debtDueDateAgingProbeEnabled = shouldRunDebtDueDateAgingProbe(planner);
|
||||
const inventoryFilters = buildBusinessOverviewInventoryFilters(planner);
|
||||
const inventoryQualityEventsProbeEnabled = shouldRunInventoryQualityEventsProbe(planner);
|
||||
const debtAsOfDate = toNonEmptyString(debtFilters?.as_of_date);
|
||||
const inventoryAsOfDate = toNonEmptyString(inventoryFilters?.as_of_date);
|
||||
const incomingSelection = selectAddressRecipe("customer_revenue_and_payments", valueFilters);
|
||||
|
|
@ -5660,6 +5798,9 @@ export async function executeAssistantMcpDiscoveryPilot(
|
|||
const inventoryAgingSelection = inventoryFilters
|
||||
? selectAddressRecipe("inventory_aging_by_purchase_date", inventoryFilters)
|
||||
: null;
|
||||
const inventoryQualityEventsSelection = inventoryQualityEventsProbeEnabled
|
||||
? selectAddressRecipe("inventory_quality_events_for_organization", inventoryFilters ?? buildBusinessOverviewProfileFilters(planner))
|
||||
: null;
|
||||
|
||||
if (!incomingSelection.selected_recipe || !outgoingSelection.selected_recipe || !lifecycleSelection.selected_recipe) {
|
||||
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");
|
||||
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) {
|
||||
if (step.primitive_id === "query_movements") {
|
||||
const incomingExecution = await executeCoverageAwareValueFlowQuery({
|
||||
|
|
@ -6007,6 +6156,19 @@ export async function executeAssistantMcpDiscoveryPilot(
|
|||
});
|
||||
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) {
|
||||
pushUnique(queryLimitations, lifecycleResult.error);
|
||||
pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_error");
|
||||
|
|
@ -6037,6 +6199,12 @@ export async function executeAssistantMcpDiscoveryPilot(
|
|||
} else if (contractUsageProfileResult) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -6061,6 +6229,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
|||
debtAsOfDate,
|
||||
inventoryOnHandResult,
|
||||
inventoryAgingResult,
|
||||
inventoryQualityEventsResult,
|
||||
inventoryAsOfDate,
|
||||
organizationScope,
|
||||
periodScope: dateScope
|
||||
|
|
@ -6126,6 +6295,10 @@ export async function executeAssistantMcpDiscoveryPilot(
|
|||
if (derivedBusinessOverview.inventory_staleness_risk_proxy) {
|
||||
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) {
|
||||
pushReason(reasonCodes, "pilot_business_overview_missing_proof_families_recorded");
|
||||
}
|
||||
|
|
@ -6145,7 +6318,8 @@ export async function executeAssistantMcpDiscoveryPilot(
|
|||
counterpartyProfileResult,
|
||||
contractUsageProfileResult,
|
||||
inventoryOnHandResult,
|
||||
inventoryAgingResult
|
||||
inventoryAgingResult,
|
||||
inventoryQualityEventsResult
|
||||
});
|
||||
const evidence = resolveAssistantMcpDiscoveryEvidence({
|
||||
plan: planner.discovery_plan,
|
||||
|
|
|
|||
|
|
@ -997,12 +997,20 @@ function buildCompactBusinessOverviewReply(
|
|||
|
||||
if (inventoryReserveBoundary) {
|
||||
const headline = toNonEmptyString(draft.headline);
|
||||
const inventoryQualityEvents = toRecordObject(overview.inventory_quality_events);
|
||||
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
||||
lines.push(
|
||||
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([
|
||||
...toStringList(draft.unknown_lines),
|
||||
...toStringList(draft.limitation_lines)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ export type AddressIntent =
|
|||
| "inventory_profitability_for_item"
|
||||
| "inventory_purchase_to_sale_chain"
|
||||
| "inventory_aging_by_purchase_date"
|
||||
| "inventory_quality_events_for_organization"
|
||||
| "account_balance_snapshot"
|
||||
| "open_items_by_counterparty_or_contract"
|
||||
| "list_documents_by_counterparty"
|
||||
|
|
@ -204,7 +205,8 @@ export interface AddressRecipeDefinition {
|
|||
| "inventory_trading_margin_proxy_profile"
|
||||
| "inventory_profitability_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>;
|
||||
optional_filters: Array<keyof AddressFilterSet>;
|
||||
default_limit: number;
|
||||
|
|
|
|||
|
|
@ -710,10 +710,14 @@ describe("assistant MCP discovery answer adapter", () => {
|
|||
const draft = buildAssistantMcpDiscoveryAnswerDraft(pilot);
|
||||
|
||||
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.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");
|
||||
});
|
||||
|
||||
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([
|
||||
{ rows: [{ Period: "2020-01-15T00:00:00", Amount: 120000, Counterparty: "Client 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.business_fact_answer_allowed).toBe(true);
|
||||
expect(result.route_candidate).toMatchObject({
|
||||
candidate_status: "needs_route_enablement",
|
||||
candidate_status: "ready_for_reviewed_execution",
|
||||
selected_chain_id: "business_overview",
|
||||
business_fact_family: "business_overview",
|
||||
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.route_candidate.enablement_reason).toContain(
|
||||
"reviewed_inventory_quality_route_with_reserves_writeoffs_obsolescence_and_liquidation_value"
|
||||
expect(result.pilot.derived_business_overview?.inventory_quality_events?.evidence_status).toBe(
|
||||
"reviewed_no_quality_events_found"
|
||||
);
|
||||
expect(result.route_candidate.forbidden_overclaim_flags).toContain(
|
||||
"confirmed_obsolete_stock_reserve_writeoff_or_liquidation_value"
|
||||
expect(result.pilot.derived_business_overview?.missing_proof_families.map((item) => item.family)).not.toContain(
|
||||
"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 () => {
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
"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