Очистить бизнес-язык ответов phase98
This commit is contained in:
parent
0028ef24a0
commit
b1a5e4435d
|
|
@ -28,8 +28,8 @@ Current reporting baseline:
|
|||
- Planner Autonomy Consolidation: `100%` for the declared phase83 slice.
|
||||
- Open-World Business Overview implementation breadth: `~99%` through Slice 25.
|
||||
- Open-World Semantic Control Gate: accepted critical subset after EHMO/W5/W7 hardening; fat GUI pack review remains a broad human-pressure gate.
|
||||
- Route-Candidate-Driven Enablement Loop: `100%`, now regression-gated by phase91-phase97 canaries.
|
||||
- Open-World Schema/Primitive Discovery: `25%`, first financial-counterparty slice accepted live at `4/4`; next schema/primitive candidate should come from real live/manual replay evidence.
|
||||
- Route-Candidate-Driven Enablement Loop: `100%`, now regression-gated by phase91-phase98 canaries.
|
||||
- Open-World Schema/Primitive Discovery: `38%`, financial-counterparty slice accepted live at `4/4` and limit-honesty/business-language gate accepted live at `6/6`; next schema/primitive candidate should come from real live/manual replay evidence.
|
||||
|
||||
## Archived Execution Snapshot (2026-04-17)
|
||||
|
||||
|
|
|
|||
|
|
@ -86,11 +86,12 @@ Fresh validation cut:
|
|||
- Completed autonomy slice inside that loop: `Vendor/Procurement Quality Reviewed Route`: `vendor_risk_procurement_quality` now promotes to reviewed procurement-concentration evidence when confirmed outgoing payment, bank-like recipient segregation, non-financial recipient, counterparty-role, and contract-usage signals are reachable; phase95 live replay is accepted.
|
||||
- Completed autonomy slice inside that loop: `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.
|
||||
- Completed broader schema/primitive discovery slice: `Financial Counterparty Flow Hints`: bank-document money-flow recipes expose operation/purpose/comment fields, ranked value-flow buckets carry `financial_flow_hint`, explicit `СБЕРБАНК` wording is not swallowed by supplier/customer tails, and bank-like leaders are bounded away from ordinary supplier/customer overclaim; phase97 live replay is accepted.
|
||||
- Current live canary: `phase97_financial_counterparty_flow_hints_live4` accepted `4/4`.
|
||||
- Current accepted autorun: `AGENT | Phase 97 financial counterparty flow hints replay` (`gen-ag05122250-4451a8`).
|
||||
- Completed broader schema/primitive discovery support slice: `Limit Honesty And Business Language Gate`: compact business-overview replies sanitize route/proxy/MCP-style wording, keep row-limit disclosure relevant to the asked contour, and preserve debt/VAT/bank/inventory/supplier canaries; phase98 live replay is accepted.
|
||||
- Current live canary: `phase98_limit_honesty_business_language_live3` accepted `6/6`.
|
||||
- Current accepted autorun: `AGENT | Phase 98 limit honesty and business-language replay` (`gen-ag05122315-f1e27c`).
|
||||
- Implementation breadth: `~99% (Open-World Bounded Autonomy Breadth through Slice 25)`.
|
||||
- Active broader autonomy module: `Open-World Schema/Primitive Discovery`, with the first `Financial Counterparty Flow Hints` slice accepted and saved.
|
||||
- Next active slice: select the next unfamiliar 1C ask from live/manual replay evidence, then continue broader schema/primitive discovery while using phase91-phase97 as regression canaries.
|
||||
- Active broader autonomy module: `Open-World Schema/Primitive Discovery`, with `Financial Counterparty Flow Hints` and `Limit Honesty And Business Language Gate` accepted and saved.
|
||||
- Next active slice: select the next unfamiliar 1C ask from live/manual replay evidence, then continue broader schema/primitive discovery while using phase91-phase98 as regression canaries.
|
||||
- Operating-layer progress: `~99% (Agentic Semantic Development Loop, accepted dogfood loop + autorun hygiene; manual GUI confirmation still required)`.
|
||||
|
||||
## Reporting Rule
|
||||
|
|
@ -103,7 +104,7 @@ Use these labels when reporting progress:
|
|||
- `Прогресс модуля: 99% (Agentic Semantic Development Loop, accepted dogfood loop + autorun hygiene; manual GUI confirmation still required)` when discussing the current development-loop operating layer.
|
||||
- `Прогресс модуля: 100% (Open-World Route Candidate Promotion, declared phase90 slice accepted)` when discussing the route-candidate handoff slice itself.
|
||||
- `Прогресс модуля: 100% (Route-Candidate-Driven Enablement Loop, final reviewed proof-family route accepted; use as regression gate)` when discussing the current candidate-driven enablement loop.
|
||||
- `Прогресс модуля: 25% (Open-World Schema/Primitive Discovery, first financial-counterparty slice accepted; next schema/primitive candidate pending)` when discussing the current broader schema/primitive discovery module.
|
||||
- `Прогресс модуля: 38% (Open-World Schema/Primitive Discovery, phase97 financial-counterparty slice and phase98 business-language gate accepted; next schema/primitive candidate pending)` when discussing the current broader schema/primitive discovery module.
|
||||
- `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.
|
||||
|
||||
|
|
@ -139,7 +140,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 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, bank-like financial counterparty role/purpose hints, 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-phase97 reviewed/canary routes;
|
||||
- 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, bank-like financial counterparty role/purpose hints, business-language/limit-honesty gating, 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-phase98 reviewed/canary 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;
|
||||
|
|
@ -161,19 +162,20 @@ For current planning, read:
|
|||
1. `README.md`
|
||||
2. this document
|
||||
3. `31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md`
|
||||
4. `32 - financial_counterparty_flow_hints_2026-05-13.md`
|
||||
5. `30 - vendor_procurement_quality_reviewed_route_2026-05-12.md`
|
||||
6. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
||||
7. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
||||
8. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
||||
9. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
||||
10. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
||||
11. `24 - agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md`
|
||||
12. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md`
|
||||
13. `22 - open_world_bounded_autonomy_breadth_2026-05-01.md`
|
||||
14. `20 - planner_autonomy_consolidation_2026-05-01.md`
|
||||
15. `19 - inventory_stock_open_world_breadth_proof_2026-05-01.md`
|
||||
16. `17 - post_f_semantic_integrity_hardening_2026-04-23.md`
|
||||
17. `16 - data_need_graph_and_open_world_mcp_plan_2026-04-22.md`
|
||||
4. `33 - limit_honesty_business_language_2026-05-13.md`
|
||||
5. `32 - financial_counterparty_flow_hints_2026-05-13.md`
|
||||
6. `30 - vendor_procurement_quality_reviewed_route_2026-05-12.md`
|
||||
7. `29 - debt_due_date_aging_reviewed_route_2026-05-10.md`
|
||||
8. `28 - accounting_profit_margin_reviewed_route_2026-05-10.md`
|
||||
9. `27 - proof_family_enablement_candidates_2026-05-10.md`
|
||||
10. `26 - route_candidate_driven_enablement_loop_2026-05-10.md`
|
||||
11. `25 - open_world_route_candidate_promotion_2026-05-10.md`
|
||||
12. `24 - agentic_semantic_development_loop_and_autorun_hygiene_2026-05-10.md`
|
||||
13. `23 - current_execution_spine_and_semantic_control_gate_2026-05-05.md`
|
||||
14. `22 - open_world_bounded_autonomy_breadth_2026-05-01.md`
|
||||
15. `20 - planner_autonomy_consolidation_2026-05-01.md`
|
||||
16. `19 - inventory_stock_open_world_breadth_proof_2026-05-01.md`
|
||||
17. `17 - post_f_semantic_integrity_hardening_2026-04-23.md`
|
||||
18. `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.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
# 33 - Limit Honesty And Business Language Gate (2026-05-13)
|
||||
|
||||
This note records the second accepted cut in the broader `Open-World Schema/Primitive Discovery` module.
|
||||
|
||||
The trigger came from the real GUI review `assistant-stage1-v2qsm_R0fF`: several answers were factually bounded, but still felt like technical artifacts because they leaked `MCP`, `route`, `proxy`, or irrelevant row-limit wording into user-facing business answers.
|
||||
|
||||
## Scope
|
||||
|
||||
This cut keeps the data and routes unchanged, but hardens the answer surface:
|
||||
|
||||
- compact business-overview replies now pass through a shared business-language sanitizer before they are returned;
|
||||
- `procurement-concentration route`, `vendor-risk route`, `due-date route`, and `proxy` phrases are converted into business-readable wording;
|
||||
- debt due-date boundary answers keep the organization in the direct line and explain missing payment terms without route jargon;
|
||||
- inventory reserve answers no longer pull unrelated incoming/outgoing money-flow limit lines into a warehouse reserve question;
|
||||
- supplier dependency answers distinguish "checked concentration of outgoing payments" from a complete supplier-risk audit without naming it as a route;
|
||||
- accepted replay keeps VAT and bank-like counterparty boundary canaries in the same scenario.
|
||||
|
||||
## Validation
|
||||
|
||||
Local checks:
|
||||
|
||||
- `npm.cmd test -- assistantMcpDiscoveryResponseCandidate.test.ts`: `26/26` passed;
|
||||
- `npm.cmd test -- assistantMcpDiscoveryResponseCandidate.test.ts assistantMcpDiscoveryAnswerAdapter.test.ts assistantMcpDiscoveryPilotExecutor.test.ts addressQueryRuntimeM23.test.ts`: `519/519` passed, `1` skipped;
|
||||
- `npm.cmd run build`: passed;
|
||||
- graphify rebuild: `6484` nodes, `14385` edges, `142` communities.
|
||||
|
||||
Live semantic replay:
|
||||
|
||||
- spec: `docs/orchestration/address_truth_harness_phase98_limit_honesty_business_language.json`;
|
||||
- accepted run: `artifacts/domain_runs/phase98_limit_honesty_business_language_live3`;
|
||||
- final status: `accepted`, `6/6` passed, `0` warnings, `0` failures;
|
||||
- accepted user-runnable autorun: `AGENT | Phase 98 limit honesty and business-language replay` (`gen-ag05122315-f1e27c`).
|
||||
|
||||
The accepted replay proves:
|
||||
|
||||
- overdue receivables answers state the organization, date, checked open-settlement amount, and missing payment-term basis in business language;
|
||||
- short follow-up questions remain short and do not repeat technical limit text;
|
||||
- VAT remains direct and debug-free;
|
||||
- top incoming money keeps the bank boundary and does not overclaim bank inflows as ordinary customer revenue;
|
||||
- inventory reserve answers say the reserve cannot be confirmed exactly and do not drag unrelated money-flow limit warnings into the warehouse answer;
|
||||
- supplier dependency answers state that exact supplier-risk is not fully confirmed, show the checked concentration leader, and list what remains unproven.
|
||||
|
||||
## Status
|
||||
|
||||
Current module wording:
|
||||
|
||||
`Open-World Schema/Primitive Discovery, completed slice: limit honesty and business-language gate`
|
||||
|
||||
Slice progress: `100%`.
|
||||
|
||||
Broader module progress: `38%`.
|
||||
|
||||
This is not a new 1C primitive by itself. It is a necessary semantic gate for the broader primitive-discovery module: as coverage grows, bounded answers must stay business-readable and must not expose internal route/proxy/debug mechanics.
|
||||
|
||||
## Next Work
|
||||
|
||||
1. Treat phase98 as a regression canary together with phase91-phase97.
|
||||
2. Pick the next unfamiliar 1C ask from live/manual replay evidence.
|
||||
3. Prefer the same loop: business meaning -> route candidate/schema surface -> minimal reviewed primitive or answer-shape fix -> live replay -> save autorun only after accepted replay.
|
||||
4. Keep watching for cases where a technically correct bounded answer still feels like a system artifact rather than a competent business analyst.
|
||||
|
||||
See also:
|
||||
|
||||
- [21 - current_status_canon_2026-05-01.md](./21%20-%20current_status_canon_2026-05-01.md)
|
||||
- [32 - financial_counterparty_flow_hints_2026-05-13.md](./32%20-%20financial_counterparty_flow_hints_2026-05-13.md)
|
||||
|
|
@ -50,6 +50,7 @@ This package answers the next question:
|
|||
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)
|
||||
32. [32 - financial_counterparty_flow_hints_2026-05-13.md](./32%20-%20financial_counterparty_flow_hints_2026-05-13.md)
|
||||
33. [33 - limit_honesty_business_language_2026-05-13.md](./33%20-%20limit_honesty_business_language_2026-05-13.md)
|
||||
|
||||
## Current Status Snapshot (2026-05-13)
|
||||
|
||||
|
|
@ -109,6 +110,8 @@ Status canon for planning:
|
|||
- The accepted user-runnable autorun for that slice is `AGENT | Phase 96 inventory reserve/liquidation quality-events` (`gen-ag05122057-c9786e`).
|
||||
- The first broader schema/primitive discovery slice is now accepted: `financial counterparty flow hints` adds bank-document purpose/operation/comment hints, protects bank-like counterparties from ordinary supplier/customer overclaim, and keeps normal counterparty net-flow canaries healthy; `phase97_financial_counterparty_flow_hints_live4` passed `4/4`.
|
||||
- The accepted user-runnable autorun for that slice is `AGENT | Phase 97 financial counterparty flow hints replay` (`gen-ag05122250-4451a8`).
|
||||
- The second broader schema/primitive discovery support slice is now accepted: `limit honesty and business-language gate` sanitizes route/proxy/MCP-style answer wording, keeps row-limit disclosure relevant to the asked business contour, and preserves debt/VAT/bank/inventory/supplier canaries; `phase98_limit_honesty_business_language_live3` passed `6/6`.
|
||||
- The accepted user-runnable autorun for that slice is `AGENT | Phase 98 limit honesty and business-language replay` (`gen-ag05122315-f1e27c`).
|
||||
- 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).
|
||||
|
|
@ -121,6 +124,7 @@ Status canon for planning:
|
|||
- 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).
|
||||
- The first broader schema/primitive discovery slice is [32 - financial_counterparty_flow_hints_2026-05-13.md](./32%20-%20financial_counterparty_flow_hints_2026-05-13.md), now accepted live and saved as a user-runnable AGENT autorun.
|
||||
- The second broader schema/primitive discovery support slice is [33 - limit_honesty_business_language_2026-05-13.md](./33%20-%20limit_honesty_business_language_2026-05-13.md), now accepted live and saved as a user-runnable AGENT autorun.
|
||||
|
||||
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:
|
||||
|
||||
|
|
@ -191,7 +195,7 @@ Current honest status:
|
|||
- 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: `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
|
||||
- Open-World Schema/Primitive Discovery progress: `25%`, first slice `financial counterparty flow hints` accepted live at `4/4`; bank-document money-flow recipes expose operation/purpose/comment fields, ranked value-flow buckets carry `financial_flow_hint`, Sberbank-like leaders are bounded away from name-only supplier/customer overclaim, and the next slice should be selected from real unfamiliar 1C asks rather than synthetic domain wish lists.
|
||||
- Open-World Schema/Primitive Discovery progress: `38%`, with `financial counterparty flow hints` accepted live at `4/4` and `limit honesty/business language` accepted live at `6/6`; bank-document money-flow recipes expose operation/purpose/comment fields, ranked value-flow buckets carry `financial_flow_hint`, Sberbank-like leaders are bounded away from name-only supplier/customer overclaim, route/proxy/MCP-style answer wording is sanitized, and the next slice should be selected from real unfamiliar 1C asks rather than synthetic domain wish lists.
|
||||
- graph snapshot after latest rebuild: see `graphify-out/GRAPH_REPORT.md`
|
||||
- current regression-gate breakpoint:
|
||||
- the validated hot paths are no longer structurally broken;
|
||||
|
|
@ -283,6 +287,7 @@ Latest live proof now includes:
|
|||
- 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`).
|
||||
- financial counterparty flow hints accepted locally/live: targeted bank-flow/intent/turn-input/answer tests passed `554/554` with `7` skipped, build passed, graphify rebuilt to `6483` nodes, `14382` edges, `143` communities; `phase97_financial_counterparty_flow_hints_live4` accepted `4/4`, proving explicit `СБЕРБАНК` wording, bank-operation purpose/direction disclosure, incoming-bank no-overclaim, business-overview bank boundaries, and `Группа СВК` net-flow canary continuity; the accepted autorun is `AGENT | Phase 97 financial counterparty flow hints replay` (`gen-ag05122250-4451a8`).
|
||||
- limit honesty and business-language gate accepted locally/live: response-candidate/answer-adapter/pilot-executor/M23 tests passed `519/519` with `1` skipped, build passed, graphify rebuilt to `6484` nodes, `14385` edges, `142` communities; `phase98_limit_honesty_business_language_live3` accepted `6/6`, proving debt due-date boundary, short follow-up directness, VAT debug hygiene, top incoming bank boundary, inventory reserve boundary language, and supplier dependency language together; the accepted autorun is `AGENT | Phase 98 limit honesty and business-language replay` (`gen-ag05122315-f1e27c`).
|
||||
|
||||
Current architectural reading:
|
||||
|
||||
|
|
@ -364,6 +369,7 @@ Read in this order:
|
|||
31. `30 - vendor_procurement_quality_reviewed_route_2026-05-12.md`
|
||||
32. `31 - inventory_reserve_liquidation_quality_reviewed_route_2026-05-12.md`
|
||||
33. `32 - financial_counterparty_flow_hints_2026-05-13.md`
|
||||
34. `33 - limit_honesty_business_language_2026-05-13.md`
|
||||
|
||||
## Planning Rules
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,205 @@
|
|||
{
|
||||
"schema_version": "domain_truth_harness_spec_v1",
|
||||
"scenario_id": "address_truth_harness_phase98_limit_honesty_business_language",
|
||||
"domain": "address_phase98_limit_honesty_business_language",
|
||||
"title": "Phase 98 limit honesty and business-language replay",
|
||||
"description": "Focused semantic replay from assistant-stage1-v2qsm_R0fF: answers may be bounded, but they must stay business-readable, direct-first, and must not leak MCP/proxy/route/debug wording when explaining row limits, incomplete coverage, debt due-date proof, inventory reserve proof, supplier dependency, VAT, or bank-like counterparties.",
|
||||
"bindings": {},
|
||||
"steps": [
|
||||
{
|
||||
"step_id": "step_01_debt_overdue_exactness_boundary",
|
||||
"title": "Overdue receivables answer explains exactness boundary in business language",
|
||||
"question": "По ООО Альтернатива Плюс на конец 2020 можно точно понять, какая дебиторка просрочена?",
|
||||
"allowed_reply_types": [
|
||||
"factual",
|
||||
"factual_with_explanation",
|
||||
"partial_coverage"
|
||||
],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)альтернатива",
|
||||
"(?i)2020|31\\.12\\.2020|конец 2020",
|
||||
"(?i)дебитор|расчет|долг",
|
||||
"(?i)срок оплат|просроч|не подтвержд|нельзя точно"
|
||||
],
|
||||
"forbidden_answer_patterns": [
|
||||
"(?i)\\bMCP\\b",
|
||||
"(?i)proxy",
|
||||
"(?i)route_candidate",
|
||||
"(?i)primitive",
|
||||
"(?i)planner_",
|
||||
"(?i)catalog_",
|
||||
"(?i)уперл.*лимит",
|
||||
"(?i)лимит выборки"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": [
|
||||
"debt_due_date_aging_quality",
|
||||
"limit_honesty",
|
||||
"business_language"
|
||||
]
|
||||
},
|
||||
{
|
||||
"step_id": "step_02_short_followup_keeps_short_business_answer",
|
||||
"title": "Short why follow-up stays short and avoids repeated technical limitation text",
|
||||
"question": "То есть просрочку доказать нельзя, коротко почему?",
|
||||
"allowed_reply_types": [
|
||||
"factual",
|
||||
"factual_with_explanation",
|
||||
"partial_coverage"
|
||||
],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)коротко|нельзя|не подтвержд|не доказ",
|
||||
"(?i)срок оплат|дата оплат|услови",
|
||||
"(?i)просроч"
|
||||
],
|
||||
"forbidden_answer_patterns": [
|
||||
"(?i)\\bMCP\\b",
|
||||
"(?i)proxy",
|
||||
"(?i)route_candidate",
|
||||
"(?i)primitive",
|
||||
"(?i)planner_",
|
||||
"(?i)catalog_",
|
||||
"(?i)уперл.*лимит",
|
||||
"(?i)лимит выборки"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": [
|
||||
"followup_directness",
|
||||
"debt_due_date_aging_quality",
|
||||
"business_language"
|
||||
]
|
||||
},
|
||||
{
|
||||
"step_id": "step_03_vat_direct_answer_without_debug_leak",
|
||||
"title": "VAT answer remains direct and does not leak debug mechanics",
|
||||
"question": "НДС за 2020 по ООО Альтернатива Плюс какой?",
|
||||
"allowed_reply_types": [
|
||||
"factual",
|
||||
"factual_with_explanation",
|
||||
"partial_coverage"
|
||||
],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)ндс",
|
||||
"(?i)2020",
|
||||
"(?i)альтернатива",
|
||||
"(?i)к уплат|нетто|книга продаж|книга покупок|вычет"
|
||||
],
|
||||
"forbidden_answer_patterns": [
|
||||
"(?i)\\bMCP\\b",
|
||||
"(?i)proxy",
|
||||
"(?i)route_candidate",
|
||||
"(?i)primitive",
|
||||
"(?i)planner_",
|
||||
"(?i)catalog_",
|
||||
"(?i)snapshot_items",
|
||||
"(?i)answer_object"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": [
|
||||
"vat",
|
||||
"business_language",
|
||||
"debug_leak_guard"
|
||||
]
|
||||
},
|
||||
{
|
||||
"step_id": "step_04_top_incoming_money_keeps_bank_boundary",
|
||||
"title": "Top incoming money answer keeps bank boundary and avoids ordinary-customer overclaim",
|
||||
"question": "А кто принес больше всего денег за 2020?",
|
||||
"allowed_reply_types": [
|
||||
"factual",
|
||||
"factual_with_explanation",
|
||||
"partial_coverage"
|
||||
],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)2020",
|
||||
"(?i)деньг|поступлен|входящ",
|
||||
"(?i)сбербанк|свк|контрагент",
|
||||
"(?i)банк|не.*обычн|не.*клиент|финансов|провер"
|
||||
],
|
||||
"forbidden_answer_patterns": [
|
||||
"(?i)сбербанк.*обычн.*клиент",
|
||||
"(?i)сбербанк.*главн.*клиент",
|
||||
"(?i)\\bMCP\\b",
|
||||
"(?i)proxy",
|
||||
"(?i)route_candidate",
|
||||
"(?i)primitive",
|
||||
"(?i)planner_",
|
||||
"(?i)catalog_",
|
||||
"(?i)уперл.*лимит",
|
||||
"(?i)лимит выборки"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": [
|
||||
"financial_counterparty_flow_hint",
|
||||
"customer_revenue_and_payments",
|
||||
"limit_honesty"
|
||||
]
|
||||
},
|
||||
{
|
||||
"step_id": "step_05_inventory_reserve_boundary_business_language",
|
||||
"title": "Inventory reserve boundary uses business terms, not proxy jargon",
|
||||
"question": "По ООО Альтернатива Плюс на конец 2020 можно точно подтвердить резерв под неликвиды на складе?",
|
||||
"allowed_reply_types": [
|
||||
"factual",
|
||||
"factual_with_explanation",
|
||||
"partial_coverage"
|
||||
],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)резерв|неликвид|склад",
|
||||
"(?i)не подтвержд|нельзя точно|точно.*нельзя|нет подтвержден",
|
||||
"(?i)списан|резерв|ликвидац|залежал|стар"
|
||||
],
|
||||
"forbidden_answer_patterns": [
|
||||
"(?i)\\bMCP\\b",
|
||||
"(?i)proxy",
|
||||
"(?i)route_candidate",
|
||||
"(?i)primitive",
|
||||
"(?i)planner_",
|
||||
"(?i)catalog_",
|
||||
"(?i)уперл.*лимит",
|
||||
"(?i)лимит выборки"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": [
|
||||
"inventory_reserve_liquidation_quality",
|
||||
"business_language",
|
||||
"limit_honesty"
|
||||
]
|
||||
},
|
||||
{
|
||||
"step_id": "step_06_supplier_dependency_bank_boundary",
|
||||
"title": "Supplier dependency answer separates bank-like recipient from supplier dependency",
|
||||
"question": "А зависимость от одного поставщика за 2020 можно точно оценить?",
|
||||
"allowed_reply_types": [
|
||||
"factual",
|
||||
"factual_with_explanation",
|
||||
"partial_coverage"
|
||||
],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)поставщик|зависим|закуп|исходящ",
|
||||
"(?i)2020",
|
||||
"(?i)крупнейш|получател|концентрац",
|
||||
"(?i)точн|не подтвержд|не доказ|не полностью",
|
||||
"(?i)надежност|качество|договор|полная структура"
|
||||
],
|
||||
"forbidden_answer_patterns": [
|
||||
"(?i)сбербанк.*обычн.*поставщик",
|
||||
"(?i)сбербанк.*главн.*поставщик",
|
||||
"(?i)\\bMCP\\b",
|
||||
"(?i)proxy",
|
||||
"(?i)route_candidate",
|
||||
"(?i)primitive",
|
||||
"(?i)planner_",
|
||||
"(?i)catalog_",
|
||||
"(?i)уперл.*лимит",
|
||||
"(?i)лимит выборки"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": [
|
||||
"vendor_risk_procurement_quality",
|
||||
"financial_counterparty_flow_hint",
|
||||
"business_language"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ function userFacingLines(values) {
|
|||
return uniqueStrings(values).filter((line) => !hasInternalMechanics(line));
|
||||
}
|
||||
function sanitizeUserFacingMechanics(value) {
|
||||
return String(value ?? "").replace(/MCP-срез(?:ом|у|е|а)?/giu, (match) => {
|
||||
let text = String(value ?? "").replace(/MCP-срез(?:ом|у|е|а)?/giu, (match) => {
|
||||
const normalized = match.toLowerCase();
|
||||
if (normalized.endsWith("ом")) {
|
||||
return "срезом 1С";
|
||||
|
|
@ -102,6 +102,28 @@ function sanitizeUserFacingMechanics(value) {
|
|||
}
|
||||
return "срез 1С";
|
||||
});
|
||||
const replacements = [
|
||||
[/\bprocurement-concentration route\b/giu, "проверка концентрации закупок/исходящих платежей"],
|
||||
[/\breviewed vendor-risk route\b/giu, "отдельная проверка поставщицкого риска"],
|
||||
[/\bvendor-risk route\b/giu, "проверка поставщицкого риска"],
|
||||
[/\bdue-date route\b/giu, "проверка просрочки по срокам оплаты"],
|
||||
[/\bdebt-quality proxy\b/giu, "ограниченный долговой сигнал"],
|
||||
[/\bstaleness-risk proxy\b/giu, "косвенный признак залежалости"],
|
||||
[/\bstaleness risk proxy\b/giu, "косвенный признак залежалости"],
|
||||
[/\boperating-flow proxy\b/giu, "денежный операционный показатель"],
|
||||
[/\btrading-margin proxy\b/giu, "товарная маржинальность по проверенным документам"],
|
||||
[/\bprocurement concentration proxy\b/giu, "сигнал концентрации закупок/исходящих платежей"],
|
||||
[/\boutgoing cash concentration proxy\b/giu, "сигнал концентрации исходящих денег"],
|
||||
[/\bproxy-сигналы\b/giu, "косвенные признаки"],
|
||||
[/\bproxy\b/giu, "косвенный показатель"],
|
||||
[/\bsales-to-stock\b/giu, "отношение продаж к остатку"],
|
||||
[/\boverdue\/due-date aging\b/giu, "просрочку по договорным срокам"],
|
||||
[/\bP&L\b/gu, "полный отчет о прибылях и убытках"]
|
||||
];
|
||||
for (const [pattern, replacement] of replacements) {
|
||||
text = text.replace(pattern, replacement);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
function localizeLine(value) {
|
||||
const sanitizedValue = sanitizeUserFacingMechanics(value);
|
||||
|
|
@ -385,6 +407,10 @@ function businessOverviewCoverageLimitLine(overview) {
|
|||
? `Важно: по направлению ${limited.join(" и ")} проверка достигла лимита строк; это расширенный проверенный срез найденных строк, но не гарантия полного бухгалтерского оборота без отдельной полной выгрузки.`
|
||||
: null;
|
||||
}
|
||||
function joinBusinessReplyLines(lines) {
|
||||
const reply = userFacingLines(lines.map(localizeLine)).join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
}
|
||||
function businessOverviewYearRowsLine(overview) {
|
||||
const years = Array.isArray(overview.yearly_breakdown) ? overview.yearly_breakdown : [];
|
||||
const values = years
|
||||
|
|
@ -577,8 +603,7 @@ function buildCompactBidirectionalValueFlowReply(entryPoint, draft) {
|
|||
if (fallbackNextStep) {
|
||||
lines.push(`Следующий шаг: ${localizeLine(fallbackNextStep)}`);
|
||||
}
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
function compactComparable(value) {
|
||||
return String(value ?? "")
|
||||
|
|
@ -748,8 +773,7 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
: "сумма не распознана";
|
||||
lines.push(`Коротко: по бухгалтерскому маршруту 90/91/99 за ${periodScope} подтвержден ${directionText}: ${amountText}${marginPct ? `; маржа к выручке 90.01 ${marginPct}` : "; маржа к выручке 90.01 не рассчитана"}.`);
|
||||
lines.push("Это учетный финрезультат по найденным строкам закрытия периода в 1С, а не внешний аудит и не юридически подтвержденная отчетность.");
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
const headline = toNonEmptyString(draft.headline);
|
||||
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
||||
|
|
@ -770,8 +794,7 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
if (limitLine) {
|
||||
lines.push(limitLine);
|
||||
}
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
if (debtDueDateBoundary) {
|
||||
const dueDateAging = toRecordObject(overview.debt_due_date_aging);
|
||||
|
|
@ -786,36 +809,35 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
const rowsWithAmount = typeof dueDateAging.rows_with_amount === "number" && Number.isFinite(dueDateAging.rows_with_amount)
|
||||
? dueDateAging.rows_with_amount
|
||||
: null;
|
||||
const dueDateScopePrefix = organizationScope ? `по компании ${organizationScope} ` : "";
|
||||
if (status === "confirmed_overdue") {
|
||||
lines.push(`Коротко: на ${asOfDate} подтвержденная просрочка есть: ${overdueAmount ?? "сумма не распознана"} по ${dueDateAging.overdue_rows ?? "найденным"} строкам.`);
|
||||
lines.push("Основа ответа: открытые расчеты 60/62/76, договорный срок оплаты и дата расчетного документа; это уже due-date route, не старение договора как proxy.");
|
||||
lines.push(`Коротко: ${dueDateScopePrefix}на ${asOfDate} подтвержденная просрочка есть: ${overdueAmount ?? "сумма не распознана"} по ${dueDateAging.overdue_rows ?? "найденным"} строкам.`);
|
||||
lines.push("Основа ответа: открытые расчеты 60/62/76, договорный срок оплаты и дата расчетного документа; это проверка просрочки по срокам оплаты, а не просто возраст договора.");
|
||||
}
|
||||
else if (status === "no_payment_terms_configured") {
|
||||
lines.push(`Коротко: на ${asOfDate} подтвержденной просрочки нет: открытые расчеты проверены${grossAmount ? ` на ${grossAmount}` : ""}, но в найденных договорах срок оплаты не установлен.`);
|
||||
lines.push(`Коротко: ${dueDateScopePrefix}на ${asOfDate} подтвержденной просрочки нет: открытые расчеты проверены${grossAmount ? ` на ${grossAmount}` : ""}, но в найденных договорах срок оплаты не установлен.`);
|
||||
lines.push(rowsWithAmount !== null
|
||||
? `Проверено строк с суммой: ${rowsWithAmount}. Без установленного срока оплаты нельзя честно назвать эти остатки просрочкой.`
|
||||
: "Без установленного срока оплаты нельзя честно назвать эти остатки просрочкой.");
|
||||
}
|
||||
else if (status === "insufficient_due_date_basis") {
|
||||
lines.push(`Коротко: due-date route запущен на ${asOfDate}, но просрочка не подтверждена: по строкам с установленным сроком оплаты не хватило даты расчетного документа.`);
|
||||
lines.push(`Коротко: ${dueDateScopePrefix}на ${asOfDate} просрочка не подтверждена: по строкам с установленным сроком оплаты не хватило даты расчетного документа.`);
|
||||
if (rowsWithPaymentTerms !== null) {
|
||||
lines.push(`Строк с установленным сроком оплаты: ${rowsWithPaymentTerms}; нужен документ-основание с датой для расчета due date.`);
|
||||
lines.push(`Строк с установленным сроком оплаты: ${rowsWithPaymentTerms}; нужен документ-основание с датой, чтобы посчитать договорный срок оплаты.`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lines.push(`Коротко: due-date route на ${asOfDate} проверен, подтвержденной просрочки не найдено${rowsWithPaymentTerms !== null ? `; строк с установленным сроком оплаты ${rowsWithPaymentTerms}` : ""}.`);
|
||||
lines.push(`Коротко: ${dueDateScopePrefix}на ${asOfDate} проверка просрочки по срокам оплаты выполнена, подтвержденной просрочки не найдено${rowsWithPaymentTerms !== null ? `; строк с установленным сроком оплаты ${rowsWithPaymentTerms}` : ""}.`);
|
||||
}
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
const headline = toNonEmptyString(draft.headline);
|
||||
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
||||
lines.push(cleanHeadline
|
||||
? `Коротко: ${localizeLine(cleanHeadline)}`
|
||||
: "Коротко: нельзя точно определить, какая дебиторка просрочена, по текущему срезу 1С; есть только debt-quality proxy, но нет проверенного due-date маршрута.");
|
||||
lines.push("Проверить нужно отдельно: договоры, сроки оплаты, погашение и закрытие задолженности; без этого нельзя доказать overdue/due-date aging.");
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
: "Коротко: нельзя точно определить, какая дебиторка просрочена, по текущему срезу 1С; есть только ограниченный долговой сигнал, но нет проверки договорных сроков оплаты.");
|
||||
lines.push("Проверить нужно отдельно: договоры, сроки оплаты, погашение и закрытие задолженности; без этого нельзя доказать просрочку по договорным срокам.");
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
if (vendorRiskBoundary) {
|
||||
const vendorProcurementQuality = toRecordObject(overview.vendor_procurement_quality);
|
||||
|
|
@ -839,7 +861,7 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
const periodScope = toNonEmptyString(vendorProcurementQuality.period_scope) ?? period;
|
||||
const totalText = totalOutgoing ? `; всего исходящих платежей в проверенном срезе ${totalOutgoing}` : "";
|
||||
if (status === "financial_institution_leads_outgoing_cash") {
|
||||
lines.push(`Коротко: проверенный procurement-concentration route за ${periodScope} не подтверждает зависимость от обычного поставщика: крупнейший получатель исходящих денег ${topOutgoingName ?? "не распознан"}${topOutgoingShare ? ` держит около ${topOutgoingShare}` : ""}${topOutgoingAmount ? ` (${topOutgoingAmount})` : ""}, но по названию это банк/финансовая организация${totalText}.`);
|
||||
lines.push(`Коротко: проверка концентрации закупок/исходящих платежей за ${periodScope} не подтверждает зависимость от обычного поставщика: крупнейший получатель исходящих денег ${topOutgoingName ?? "не распознан"}${topOutgoingShare ? ` держит около ${topOutgoingShare}` : ""}${topOutgoingAmount ? ` (${topOutgoingAmount})` : ""}, но по названию это банк/финансовая организация${totalText}.`);
|
||||
const financialHintText = financialFlowHintTextRuFromRecord(topOutgoingRecord);
|
||||
if (financialHintText) {
|
||||
lines.push(financialHintText);
|
||||
|
|
@ -849,19 +871,18 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
}
|
||||
}
|
||||
else if (status === "reviewed_procurement_concentration") {
|
||||
lines.push(`Коротко: проверенный procurement-concentration route за ${periodScope} нашел основную зависимость исходящего потока: ${topOutgoingName ?? nonFinancialName ?? "получатель не распознан"}${topOutgoingShare ? ` держит около ${topOutgoingShare}` : nonFinancialShare ? ` держит около ${nonFinancialShare}` : ""}${topOutgoingAmount ? ` (${topOutgoingAmount})` : nonFinancialAmount ? ` (${nonFinancialAmount})` : ""}${totalText}.`);
|
||||
lines.push(`Коротко: точный риск зависимости от одного поставщика не подтвержден полностью; проверка концентрации закупок/исходящих платежей за ${periodScope} нашла крупнейшего получателя исходящего потока: ${topOutgoingName ?? nonFinancialName ?? "получатель не распознан"}${topOutgoingShare ? ` держит около ${topOutgoingShare}` : nonFinancialShare ? ` держит около ${nonFinancialShare}` : ""}${topOutgoingAmount ? ` (${topOutgoingAmount})` : nonFinancialAmount ? ` (${nonFinancialAmount})` : ""}${totalText}.`);
|
||||
}
|
||||
else {
|
||||
lines.push(`Коротко: procurement-concentration route за ${periodScope} отработал, но надежной небанковской концентрации поставщика по найденным исходящим платежам не хватает${totalText}.`);
|
||||
lines.push(`Коротко: проверка концентрации закупок/исходящих платежей за ${periodScope} выполнена, но надежной небанковской концентрации поставщика по найденным исходящим платежам не хватает${totalText}.`);
|
||||
}
|
||||
const contractText = typeof vendorProcurementQuality.used_contracts === "number" && Number.isFinite(vendorProcurementQuality.used_contracts)
|
||||
? typeof vendorProcurementQuality.total_contracts === "number" && Number.isFinite(vendorProcurementQuality.total_contracts)
|
||||
? ` Договорный профиль: используется ${vendorProcurementQuality.used_contracts}/${vendorProcurementQuality.total_contracts} договоров${typeof vendorProcurementQuality.used_contract_share_pct === "number" && Number.isFinite(vendorProcurementQuality.used_contract_share_pct) ? ` (${vendorProcurementQuality.used_contract_share_pct}%)` : ""}.`
|
||||
: ` Договорный профиль: используется ${vendorProcurementQuality.used_contracts} договоров.`
|
||||
: "";
|
||||
lines.push(`Что не доказано этим маршрутом: надежность поставщика, качество поставок, договорные условия, назначение каждого платежа и полная структура всех расходов.${contractText}`);
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
lines.push(`Что не доказано этим срезом: надежность поставщика, качество поставок, договорные условия, назначение каждого платежа и полная структура всех расходов.${contractText}`);
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
const supplierBasis = topSupplier
|
||||
? topSupplierLooksFinancial
|
||||
|
|
@ -870,26 +891,24 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
: outgoingAmount
|
||||
? `исходящие платежи/закупочный поток в проверенном срезе: ${outgoingAmount}`
|
||||
: "есть только ограниченный срез исходящих платежей без полного vendor-risk профиля";
|
||||
const proxyLabel = topSupplierLooksFinancial ? "outgoing cash concentration proxy" : "procurement concentration proxy";
|
||||
const proxyLabel = topSupplierLooksFinancial
|
||||
? "сигнал концентрации исходящих денег"
|
||||
: "сигнал концентрации закупок/исходящих платежей";
|
||||
lines.push(`Коротко: точный риск зависимости от одного поставщика по текущим данным не подтвержден; есть только ${proxyLabel}: ${supplierBasis}.`);
|
||||
lines.push("Это сигнал концентрации закупок/исходящих платежей, а не полный аудит надежности поставщиков, условий, качества и структуры всех расходов.");
|
||||
lines.push("Для точного вывода нужен отдельный reviewed vendor-risk route: поставщики, договорные условия, качество поставок, сроки, доля в закупках и полная структура расходов.");
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
lines.push("Для точного вывода нужна отдельная проверка поставщицкого риска: поставщики, договорные условия, качество поставок, сроки, доля в закупках и полная структура расходов.");
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
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)}`
|
||||
const reserveBasis = cleanHeadline ? localizeLine(cleanHeadline).replace(/^проверил/iu, "Проверены") : null;
|
||||
lines.push(reserveBasis
|
||||
? `Коротко: точно подтвердить резерв под неликвиды нельзя. ${reserveBasis}`
|
||||
: "Коротко: точно подтвердить резерв под неликвиды по текущим данным нельзя.");
|
||||
if (inventoryQualityEvents) {
|
||||
if (limitLine) {
|
||||
lines.push(limitLine);
|
||||
}
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
const boundaryLines = userFacingLines([
|
||||
...toStringList(draft.unknown_lines),
|
||||
|
|
@ -900,9 +919,8 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
if (boundaryLines.length > 0) {
|
||||
lines.push(...boundaryLines.map(localizeLine));
|
||||
}
|
||||
lines.push("Проверить нужно отдельно: складской срез на дату, учетную политику резервов, списания и ликвидационную стоимость; proxy-сигналы нельзя выдавать за доказанный факт резерва.");
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
lines.push("Проверить нужно отдельно: складской срез на дату, учетную политику резервов, списания и ликвидационную стоимость; косвенные признаки нельзя выдавать за доказанный факт резерва.");
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
if (crossScopeExecutiveSummary && separateSubject && previousCounterpartySummary && (incomingAmount || outgoingAmount || netAmount)) {
|
||||
lines.push(`Коротко: по компании ${organizationScope ?? "в выбранном контуре"} ${period} подтвержден денежный срез: получили ${incomingAmount ?? "0 руб."}, исходящие платежи/списания ${outgoingAmount ?? "0 руб."}, ${netDirection} ${sentenceAmount(netAmount) ?? netAmount ?? "0 руб."}${previousCounterpartySummary.lead}; можно утверждать только эти подтвержденные срезы, нельзя называть это чистой прибылью, полным оборотом или доказанной ролью главного клиента/поставщика.`);
|
||||
|
|
@ -912,8 +930,7 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
if (limitLine) {
|
||||
lines.push(limitLine);
|
||||
}
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
if (rankingNeed) {
|
||||
const incomingLeader = strongestIncomingYear(overview);
|
||||
|
|
@ -1005,8 +1022,7 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
|||
lines.push(limitLine);
|
||||
}
|
||||
lines.push("Для ответа именно про чистую прибыль нужно отдельно считать себестоимость, расходы и закрытие периода.");
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
function statusFrom(entryPoint) {
|
||||
if (!entryPoint || entryPoint.entry_status === "skipped_not_applicable") {
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ function userFacingLines(values: string[]): string[] {
|
|||
}
|
||||
|
||||
function sanitizeUserFacingMechanics(value: string): string {
|
||||
return String(value ?? "").replace(/MCP-срез(?:ом|у|е|а)?/giu, (match) => {
|
||||
let text = String(value ?? "").replace(/MCP-срез(?:ом|у|е|а)?/giu, (match) => {
|
||||
const normalized = match.toLowerCase();
|
||||
if (normalized.endsWith("ом")) {
|
||||
return "срезом 1С";
|
||||
|
|
@ -136,6 +136,28 @@ function sanitizeUserFacingMechanics(value: string): string {
|
|||
}
|
||||
return "срез 1С";
|
||||
});
|
||||
const replacements: Array<[RegExp, string]> = [
|
||||
[/\bprocurement-concentration route\b/giu, "проверка концентрации закупок/исходящих платежей"],
|
||||
[/\breviewed vendor-risk route\b/giu, "отдельная проверка поставщицкого риска"],
|
||||
[/\bvendor-risk route\b/giu, "проверка поставщицкого риска"],
|
||||
[/\bdue-date route\b/giu, "проверка просрочки по срокам оплаты"],
|
||||
[/\bdebt-quality proxy\b/giu, "ограниченный долговой сигнал"],
|
||||
[/\bstaleness-risk proxy\b/giu, "косвенный признак залежалости"],
|
||||
[/\bstaleness risk proxy\b/giu, "косвенный признак залежалости"],
|
||||
[/\boperating-flow proxy\b/giu, "денежный операционный показатель"],
|
||||
[/\btrading-margin proxy\b/giu, "товарная маржинальность по проверенным документам"],
|
||||
[/\bprocurement concentration proxy\b/giu, "сигнал концентрации закупок/исходящих платежей"],
|
||||
[/\boutgoing cash concentration proxy\b/giu, "сигнал концентрации исходящих денег"],
|
||||
[/\bproxy-сигналы\b/giu, "косвенные признаки"],
|
||||
[/\bproxy\b/giu, "косвенный показатель"],
|
||||
[/\bsales-to-stock\b/giu, "отношение продаж к остатку"],
|
||||
[/\boverdue\/due-date aging\b/giu, "просрочку по договорным срокам"],
|
||||
[/\bP&L\b/gu, "полный отчет о прибылях и убытках"]
|
||||
];
|
||||
for (const [pattern, replacement] of replacements) {
|
||||
text = text.replace(pattern, replacement);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function localizeLine(value: string): string {
|
||||
|
|
@ -454,6 +476,11 @@ function businessOverviewCoverageLimitLine(overview: Record<string, unknown>): s
|
|||
: null;
|
||||
}
|
||||
|
||||
function joinBusinessReplyLines(lines: string[]): string | null {
|
||||
const reply = userFacingLines(lines.map(localizeLine)).join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
}
|
||||
|
||||
function businessOverviewYearRowsLine(overview: Record<string, unknown>): string | null {
|
||||
const years = Array.isArray(overview.yearly_breakdown) ? overview.yearly_breakdown : [];
|
||||
const values = years
|
||||
|
|
@ -670,8 +697,7 @@ function buildCompactBidirectionalValueFlowReply(
|
|||
lines.push(`Следующий шаг: ${localizeLine(fallbackNextStep)}`);
|
||||
}
|
||||
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
|
||||
function compactComparable(value: string | null): string {
|
||||
|
|
@ -883,8 +909,7 @@ function buildCompactBusinessOverviewReply(
|
|||
lines.push(
|
||||
"Это учетный финрезультат по найденным строкам закрытия периода в 1С, а не внешний аудит и не юридически подтвержденная отчетность."
|
||||
);
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
const headline = toNonEmptyString(draft.headline);
|
||||
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
||||
|
|
@ -909,8 +934,7 @@ function buildCompactBusinessOverviewReply(
|
|||
if (limitLine) {
|
||||
lines.push(limitLine);
|
||||
}
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
|
||||
if (debtDueDateBoundary) {
|
||||
|
|
@ -928,14 +952,15 @@ function buildCompactBusinessOverviewReply(
|
|||
typeof dueDateAging.rows_with_amount === "number" && Number.isFinite(dueDateAging.rows_with_amount)
|
||||
? dueDateAging.rows_with_amount
|
||||
: null;
|
||||
const dueDateScopePrefix = organizationScope ? `по компании ${organizationScope} ` : "";
|
||||
if (status === "confirmed_overdue") {
|
||||
lines.push(
|
||||
`Коротко: на ${asOfDate} подтвержденная просрочка есть: ${overdueAmount ?? "сумма не распознана"} по ${dueDateAging.overdue_rows ?? "найденным"} строкам.`
|
||||
`Коротко: ${dueDateScopePrefix}на ${asOfDate} подтвержденная просрочка есть: ${overdueAmount ?? "сумма не распознана"} по ${dueDateAging.overdue_rows ?? "найденным"} строкам.`
|
||||
);
|
||||
lines.push("Основа ответа: открытые расчеты 60/62/76, договорный срок оплаты и дата расчетного документа; это уже due-date route, не старение договора как proxy.");
|
||||
lines.push("Основа ответа: открытые расчеты 60/62/76, договорный срок оплаты и дата расчетного документа; это проверка просрочки по срокам оплаты, а не просто возраст договора.");
|
||||
} else if (status === "no_payment_terms_configured") {
|
||||
lines.push(
|
||||
`Коротко: на ${asOfDate} подтвержденной просрочки нет: открытые расчеты проверены${grossAmount ? ` на ${grossAmount}` : ""}, но в найденных договорах срок оплаты не установлен.`
|
||||
`Коротко: ${dueDateScopePrefix}на ${asOfDate} подтвержденной просрочки нет: открытые расчеты проверены${grossAmount ? ` на ${grossAmount}` : ""}, но в найденных договорах срок оплаты не установлен.`
|
||||
);
|
||||
lines.push(
|
||||
rowsWithAmount !== null
|
||||
|
|
@ -944,31 +969,29 @@ function buildCompactBusinessOverviewReply(
|
|||
);
|
||||
} else if (status === "insufficient_due_date_basis") {
|
||||
lines.push(
|
||||
`Коротко: due-date route запущен на ${asOfDate}, но просрочка не подтверждена: по строкам с установленным сроком оплаты не хватило даты расчетного документа.`
|
||||
`Коротко: ${dueDateScopePrefix}на ${asOfDate} просрочка не подтверждена: по строкам с установленным сроком оплаты не хватило даты расчетного документа.`
|
||||
);
|
||||
if (rowsWithPaymentTerms !== null) {
|
||||
lines.push(`Строк с установленным сроком оплаты: ${rowsWithPaymentTerms}; нужен документ-основание с датой для расчета due date.`);
|
||||
lines.push(`Строк с установленным сроком оплаты: ${rowsWithPaymentTerms}; нужен документ-основание с датой, чтобы посчитать договорный срок оплаты.`);
|
||||
}
|
||||
} else {
|
||||
lines.push(
|
||||
`Коротко: due-date route на ${asOfDate} проверен, подтвержденной просрочки не найдено${rowsWithPaymentTerms !== null ? `; строк с установленным сроком оплаты ${rowsWithPaymentTerms}` : ""}.`
|
||||
`Коротко: ${dueDateScopePrefix}на ${asOfDate} проверка просрочки по срокам оплаты выполнена, подтвержденной просрочки не найдено${rowsWithPaymentTerms !== null ? `; строк с установленным сроком оплаты ${rowsWithPaymentTerms}` : ""}.`
|
||||
);
|
||||
}
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
const headline = toNonEmptyString(draft.headline);
|
||||
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
||||
lines.push(
|
||||
cleanHeadline
|
||||
? `Коротко: ${localizeLine(cleanHeadline)}`
|
||||
: "Коротко: нельзя точно определить, какая дебиторка просрочена, по текущему срезу 1С; есть только debt-quality proxy, но нет проверенного due-date маршрута."
|
||||
: "Коротко: нельзя точно определить, какая дебиторка просрочена, по текущему срезу 1С; есть только ограниченный долговой сигнал, но нет проверки договорных сроков оплаты."
|
||||
);
|
||||
lines.push(
|
||||
"Проверить нужно отдельно: договоры, сроки оплаты, погашение и закрытие задолженности; без этого нельзя доказать overdue/due-date aging."
|
||||
"Проверить нужно отдельно: договоры, сроки оплаты, погашение и закрытие задолженности; без этого нельзя доказать просрочку по договорным срокам."
|
||||
);
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
|
||||
if (vendorRiskBoundary) {
|
||||
|
|
@ -996,7 +1019,7 @@ function buildCompactBusinessOverviewReply(
|
|||
const totalText = totalOutgoing ? `; всего исходящих платежей в проверенном срезе ${totalOutgoing}` : "";
|
||||
if (status === "financial_institution_leads_outgoing_cash") {
|
||||
lines.push(
|
||||
`Коротко: проверенный procurement-concentration route за ${periodScope} не подтверждает зависимость от обычного поставщика: крупнейший получатель исходящих денег ${topOutgoingName ?? "не распознан"}${topOutgoingShare ? ` держит около ${topOutgoingShare}` : ""}${topOutgoingAmount ? ` (${topOutgoingAmount})` : ""}, но по названию это банк/финансовая организация${totalText}.`
|
||||
`Коротко: проверка концентрации закупок/исходящих платежей за ${periodScope} не подтверждает зависимость от обычного поставщика: крупнейший получатель исходящих денег ${topOutgoingName ?? "не распознан"}${topOutgoingShare ? ` держит около ${topOutgoingShare}` : ""}${topOutgoingAmount ? ` (${topOutgoingAmount})` : ""}, но по названию это банк/финансовая организация${totalText}.`
|
||||
);
|
||||
const financialHintText = financialFlowHintTextRuFromRecord(topOutgoingRecord);
|
||||
if (financialHintText) {
|
||||
|
|
@ -1009,11 +1032,11 @@ function buildCompactBusinessOverviewReply(
|
|||
}
|
||||
} else if (status === "reviewed_procurement_concentration") {
|
||||
lines.push(
|
||||
`Коротко: проверенный procurement-concentration route за ${periodScope} нашел основную зависимость исходящего потока: ${topOutgoingName ?? nonFinancialName ?? "получатель не распознан"}${topOutgoingShare ? ` держит около ${topOutgoingShare}` : nonFinancialShare ? ` держит около ${nonFinancialShare}` : ""}${topOutgoingAmount ? ` (${topOutgoingAmount})` : nonFinancialAmount ? ` (${nonFinancialAmount})` : ""}${totalText}.`
|
||||
`Коротко: точный риск зависимости от одного поставщика не подтвержден полностью; проверка концентрации закупок/исходящих платежей за ${periodScope} нашла крупнейшего получателя исходящего потока: ${topOutgoingName ?? nonFinancialName ?? "получатель не распознан"}${topOutgoingShare ? ` держит около ${topOutgoingShare}` : nonFinancialShare ? ` держит около ${nonFinancialShare}` : ""}${topOutgoingAmount ? ` (${topOutgoingAmount})` : nonFinancialAmount ? ` (${nonFinancialAmount})` : ""}${totalText}.`
|
||||
);
|
||||
} else {
|
||||
lines.push(
|
||||
`Коротко: procurement-concentration route за ${periodScope} отработал, но надежной небанковской концентрации поставщика по найденным исходящим платежам не хватает${totalText}.`
|
||||
`Коротко: проверка концентрации закупок/исходящих платежей за ${periodScope} выполнена, но надежной небанковской концентрации поставщика по найденным исходящим платежам не хватает${totalText}.`
|
||||
);
|
||||
}
|
||||
const contractText =
|
||||
|
|
@ -1023,10 +1046,9 @@ function buildCompactBusinessOverviewReply(
|
|||
: ` Договорный профиль: используется ${vendorProcurementQuality.used_contracts} договоров.`
|
||||
: "";
|
||||
lines.push(
|
||||
`Что не доказано этим маршрутом: надежность поставщика, качество поставок, договорные условия, назначение каждого платежа и полная структура всех расходов.${contractText}`
|
||||
`Что не доказано этим срезом: надежность поставщика, качество поставок, договорные условия, назначение каждого платежа и полная структура всех расходов.${contractText}`
|
||||
);
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
const supplierBasis = topSupplier
|
||||
? topSupplierLooksFinancial
|
||||
|
|
@ -1035,7 +1057,9 @@ function buildCompactBusinessOverviewReply(
|
|||
: outgoingAmount
|
||||
? `исходящие платежи/закупочный поток в проверенном срезе: ${outgoingAmount}`
|
||||
: "есть только ограниченный срез исходящих платежей без полного vendor-risk профиля";
|
||||
const proxyLabel = topSupplierLooksFinancial ? "outgoing cash concentration proxy" : "procurement concentration proxy";
|
||||
const proxyLabel = topSupplierLooksFinancial
|
||||
? "сигнал концентрации исходящих денег"
|
||||
: "сигнал концентрации закупок/исходящих платежей";
|
||||
lines.push(
|
||||
`Коротко: точный риск зависимости от одного поставщика по текущим данным не подтвержден; есть только ${proxyLabel}: ${supplierBasis}.`
|
||||
);
|
||||
|
|
@ -1043,27 +1067,23 @@ function buildCompactBusinessOverviewReply(
|
|||
"Это сигнал концентрации закупок/исходящих платежей, а не полный аудит надежности поставщиков, условий, качества и структуры всех расходов."
|
||||
);
|
||||
lines.push(
|
||||
"Для точного вывода нужен отдельный reviewed vendor-risk route: поставщики, договорные условия, качество поставок, сроки, доля в закупках и полная структура расходов."
|
||||
"Для точного вывода нужна отдельная проверка поставщицкого риска: поставщики, договорные условия, качество поставок, сроки, доля в закупках и полная структура расходов."
|
||||
);
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
|
||||
if (inventoryReserveBoundary) {
|
||||
const headline = toNonEmptyString(draft.headline);
|
||||
const inventoryQualityEvents = toRecordObject(overview.inventory_quality_events);
|
||||
const cleanHeadline = headline?.replace(/^Коротко:\s*/iu, "").trim();
|
||||
const reserveBasis = cleanHeadline ? localizeLine(cleanHeadline).replace(/^проверил/iu, "Проверены") : null;
|
||||
lines.push(
|
||||
cleanHeadline
|
||||
? `Коротко: ${localizeLine(cleanHeadline)}`
|
||||
reserveBasis
|
||||
? `Коротко: точно подтвердить резерв под неликвиды нельзя. ${reserveBasis}`
|
||||
: "Коротко: точно подтвердить резерв под неликвиды по текущим данным нельзя."
|
||||
);
|
||||
if (inventoryQualityEvents) {
|
||||
if (limitLine) {
|
||||
lines.push(limitLine);
|
||||
}
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
const boundaryLines = userFacingLines([
|
||||
...toStringList(draft.unknown_lines),
|
||||
|
|
@ -1075,10 +1095,9 @@ function buildCompactBusinessOverviewReply(
|
|||
lines.push(...boundaryLines.map(localizeLine));
|
||||
}
|
||||
lines.push(
|
||||
"Проверить нужно отдельно: складской срез на дату, учетную политику резервов, списания и ликвидационную стоимость; proxy-сигналы нельзя выдавать за доказанный факт резерва."
|
||||
"Проверить нужно отдельно: складской срез на дату, учетную политику резервов, списания и ликвидационную стоимость; косвенные признаки нельзя выдавать за доказанный факт резерва."
|
||||
);
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
|
||||
if (crossScopeExecutiveSummary && separateSubject && previousCounterpartySummary && (incomingAmount || outgoingAmount || netAmount)) {
|
||||
|
|
@ -1095,8 +1114,7 @@ function buildCompactBusinessOverviewReply(
|
|||
if (limitLine) {
|
||||
lines.push(limitLine);
|
||||
}
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
|
||||
if (rankingNeed) {
|
||||
|
|
@ -1205,8 +1223,7 @@ function buildCompactBusinessOverviewReply(
|
|||
lines.push(limitLine);
|
||||
}
|
||||
lines.push("Для ответа именно про чистую прибыль нужно отдельно считать себестоимость, расходы и закрытие периода.");
|
||||
const reply = lines.join("\n").trim();
|
||||
return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null;
|
||||
return joinBusinessReplyLines(lines);
|
||||
}
|
||||
|
||||
function statusFrom(entryPoint: AssistantMcpDiscoveryRuntimeEntryPointContract | null): AssistantMcpDiscoveryResponseCandidateStatus {
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ describe("assistant MCP discovery response candidate", () => {
|
|||
);
|
||||
|
||||
expect(candidate.reply_text).toContain("нельзя точно подтвердить чистую прибыль");
|
||||
expect(candidate.reply_text).toContain("P&L");
|
||||
expect(candidate.reply_text).toContain("полный отчет о прибылях и убытках");
|
||||
expect(candidate.reply_text).toContain("себестоимости");
|
||||
expect(candidate.reply_text).not.toContain("47 628 853");
|
||||
});
|
||||
|
|
@ -208,7 +208,7 @@ describe("assistant MCP discovery response candidate", () => {
|
|||
);
|
||||
|
||||
expect(candidate.reply_text).toContain("риск зависимости");
|
||||
expect(candidate.reply_text).toContain("outgoing cash concentration proxy");
|
||||
expect(candidate.reply_text).toContain("сигнал концентрации исходящих денег");
|
||||
expect(candidate.reply_text).toContain("банк/финансовая организация");
|
||||
expect(candidate.reply_text).toContain("не доказанная зависимость от обычного поставщика");
|
||||
expect(candidate.reply_text).not.toContain("крупнейший подтвержденный поставщик/получатель исходящих платежей: СБЕРБАНК");
|
||||
|
|
@ -296,11 +296,12 @@ describe("assistant MCP discovery response candidate", () => {
|
|||
})
|
||||
);
|
||||
|
||||
expect(candidate.reply_text).toContain("procurement-concentration route");
|
||||
expect(candidate.reply_text).toContain("проверка концентрации закупок/исходящих платежей");
|
||||
expect(candidate.reply_text).toContain("банк/финансовая организация");
|
||||
expect(candidate.reply_text).toContain("Поставщик А");
|
||||
expect(candidate.reply_text).toContain("надежность поставщика");
|
||||
expect(candidate.reply_text).not.toContain("outgoing cash concentration proxy");
|
||||
expect(candidate.reply_text).not.toContain("procurement-concentration route");
|
||||
expect(candidate.reply_text).not.toContain("business_overview_route_template_v1");
|
||||
});
|
||||
|
||||
|
|
@ -464,7 +465,7 @@ describe("assistant MCP discovery response candidate", () => {
|
|||
expect(candidate.reply_text).toContain("12 474 036,91 руб");
|
||||
expect(candidate.reply_text?.split("\n")[0]).toContain("крупнейший источник входящих денег: ГКУ УКРиС");
|
||||
expect(candidate.reply_text?.split("\n")[0]).toContain("крупнейший получатель исходящих денег: ООО Поставщик");
|
||||
expect(candidate.reply_text).toContain("денежный operating-flow proxy");
|
||||
expect(candidate.reply_text).toContain("денежный операционный показатель");
|
||||
expect(candidate.reply_text).not.toContain("Что можно сказать только как вывод:");
|
||||
expect(candidate.reply_text).not.toContain("Складской срез");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,54 @@
|
|||
[
|
||||
{
|
||||
"generation_id": "gen-ag05122315-f1e27c",
|
||||
"created_at": "2026-05-12T23:15:48+00:00",
|
||||
"mode": "saved_user_sessions",
|
||||
"title": "AGENT | Phase 98 limit honesty and business-language replay",
|
||||
"count": 6,
|
||||
"domain": "address_phase98_limit_honesty_business_language",
|
||||
"questions": [
|
||||
"По ООО Альтернатива Плюс на конец 2020 можно точно понять, какая дебиторка просрочена?",
|
||||
"То есть просрочку доказать нельзя, коротко почему?",
|
||||
"НДС за 2020 по ООО Альтернатива Плюс какой?",
|
||||
"А кто принес больше всего денег за 2020?",
|
||||
"По ООО Альтернатива Плюс на конец 2020 можно точно подтвердить резерв под неликвиды на складе?",
|
||||
"А зависимость от одного поставщика за 2020 можно точно оценить?"
|
||||
],
|
||||
"generated_by": "codex_agent",
|
||||
"saved_case_set_file": "assistant_autogen_saved_user_sessions_20260512231548_gen-ag05122315-f1e27c.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_20260512231548_gen-ag05122315-f1e27c.json",
|
||||
"saved_case_set_kind": "agent_semantic_scenario",
|
||||
"agent_run": true,
|
||||
"agent_focus": "Focused semantic replay from assistant-stage1-v2qsm_R0fF: answers may be bounded, but they must stay business-readable, direct-first, and must not leak MCP/proxy/route/debug wording when explaining row limits, incomplete coverage, debt due-date proof, inventory reserve proof, supplier dependency, VAT, or bank-like counterparties.",
|
||||
"architecture_phase": "turnaround_11",
|
||||
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\address_truth_harness_phase98_limit_honesty_business_language.json",
|
||||
"scenario_id": "address_truth_harness_phase98_limit_honesty_business_language",
|
||||
"semantic_tags": [
|
||||
"business_language",
|
||||
"customer_revenue_and_payments",
|
||||
"debt_due_date_aging_quality",
|
||||
"debug_leak_guard",
|
||||
"financial_counterparty_flow_hint",
|
||||
"followup_directness",
|
||||
"inventory_reserve_liquidation_quality",
|
||||
"limit_honesty",
|
||||
"vat",
|
||||
"vendor_risk_procurement_quality"
|
||||
],
|
||||
"validation_status": "accepted_live_replay",
|
||||
"validated_run_dir": "artifacts\\domain_runs\\phase98_limit_honesty_business_language_live3",
|
||||
"saved_after_validated_replay": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"generation_id": "gen-ag05122250-4451a8",
|
||||
"created_at": "2026-05-12T22:50:23+00:00",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
{
|
||||
"saved_at": "2026-05-12T23:15:48+00:00",
|
||||
"generation_id": "gen-ag05122315-f1e27c",
|
||||
"mode": "saved_user_sessions",
|
||||
"title": "AGENT | Phase 98 limit honesty and business-language replay",
|
||||
"agent_run": true,
|
||||
"questions": [
|
||||
"По ООО Альтернатива Плюс на конец 2020 можно точно понять, какая дебиторка просрочена?",
|
||||
"То есть просрочку доказать нельзя, коротко почему?",
|
||||
"НДС за 2020 по ООО Альтернатива Плюс какой?",
|
||||
"А кто принес больше всего денег за 2020?",
|
||||
"По ООО Альтернатива Плюс на конец 2020 можно точно подтвердить резерв под неликвиды на складе?",
|
||||
"А зависимость от одного поставщика за 2020 можно точно оценить?"
|
||||
],
|
||||
"metadata": {
|
||||
"assistant_prompt_version": null,
|
||||
"decomposition_prompt_version": null,
|
||||
"prompt_fingerprint": null,
|
||||
"agent_focus": "Focused semantic replay from assistant-stage1-v2qsm_R0fF: answers may be bounded, but they must stay business-readable, direct-first, and must not leak MCP/proxy/route/debug wording when explaining row limits, incomplete coverage, debt due-date proof, inventory reserve proof, supplier dependency, VAT, or bank-like counterparties.",
|
||||
"architecture_phase": "turnaround_11",
|
||||
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\address_truth_harness_phase98_limit_honesty_business_language.json",
|
||||
"scenario_id": "address_truth_harness_phase98_limit_honesty_business_language",
|
||||
"semantic_tags": [
|
||||
"business_language",
|
||||
"customer_revenue_and_payments",
|
||||
"debt_due_date_aging_quality",
|
||||
"debug_leak_guard",
|
||||
"financial_counterparty_flow_hint",
|
||||
"followup_directness",
|
||||
"inventory_reserve_liquidation_quality",
|
||||
"limit_honesty",
|
||||
"vat",
|
||||
"vendor_risk_procurement_quality"
|
||||
],
|
||||
"validation_status": "accepted_live_replay",
|
||||
"validated_run_dir": "artifacts\\domain_runs\\phase98_limit_honesty_business_language_live3",
|
||||
"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\\phase98_limit_honesty_business_language_live3",
|
||||
"final_status": "accepted",
|
||||
"review_overall_status": "pass",
|
||||
"business_overall_status": "pass",
|
||||
"steps_total": 6,
|
||||
"steps_passed": 6,
|
||||
"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 можно точно понять, какая дебиторка просрочена?",
|
||||
"created_at": "2026-05-12T23:15:48+00:00",
|
||||
"reply_type": null,
|
||||
"trace_id": null,
|
||||
"debug": null
|
||||
},
|
||||
{
|
||||
"message_id": "agent-user-002",
|
||||
"role": "user",
|
||||
"text": "То есть просрочку доказать нельзя, коротко почему?",
|
||||
"created_at": "2026-05-12T23:15:48+00:00",
|
||||
"reply_type": null,
|
||||
"trace_id": null,
|
||||
"debug": null
|
||||
},
|
||||
{
|
||||
"message_id": "agent-user-003",
|
||||
"role": "user",
|
||||
"text": "НДС за 2020 по ООО Альтернатива Плюс какой?",
|
||||
"created_at": "2026-05-12T23:15:48+00:00",
|
||||
"reply_type": null,
|
||||
"trace_id": null,
|
||||
"debug": null
|
||||
},
|
||||
{
|
||||
"message_id": "agent-user-004",
|
||||
"role": "user",
|
||||
"text": "А кто принес больше всего денег за 2020?",
|
||||
"created_at": "2026-05-12T23:15:48+00:00",
|
||||
"reply_type": null,
|
||||
"trace_id": null,
|
||||
"debug": null
|
||||
},
|
||||
{
|
||||
"message_id": "agent-user-005",
|
||||
"role": "user",
|
||||
"text": "По ООО Альтернатива Плюс на конец 2020 можно точно подтвердить резерв под неликвиды на складе?",
|
||||
"created_at": "2026-05-12T23:15:48+00:00",
|
||||
"reply_type": null,
|
||||
"trace_id": null,
|
||||
"debug": null
|
||||
},
|
||||
{
|
||||
"message_id": "agent-user-006",
|
||||
"role": "user",
|
||||
"text": "А зависимость от одного поставщика за 2020 можно точно оценить?",
|
||||
"created_at": "2026-05-12T23:15:48+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": "Focused semantic replay from assistant-stage1-v2qsm_R0fF: answers may be bounded, but they must stay business-readable, direct-first, and must not leak MCP/proxy/route/debug wording when explaining row limits, incomplete coverage, debt due-date proof, inventory reserve proof, supplier dependency, VAT, or bank-like counterparties.",
|
||||
"architecture_phase": "turnaround_11",
|
||||
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\address_truth_harness_phase98_limit_honesty_business_language.json",
|
||||
"scenario_id": "address_truth_harness_phase98_limit_honesty_business_language",
|
||||
"semantic_tags": [
|
||||
"business_language",
|
||||
"customer_revenue_and_payments",
|
||||
"debt_due_date_aging_quality",
|
||||
"debug_leak_guard",
|
||||
"financial_counterparty_flow_hint",
|
||||
"followup_directness",
|
||||
"inventory_reserve_liquidation_quality",
|
||||
"limit_honesty",
|
||||
"vat",
|
||||
"vendor_risk_procurement_quality"
|
||||
],
|
||||
"validation_status": "accepted_live_replay",
|
||||
"validated_run_dir": "artifacts\\domain_runs\\phase98_limit_honesty_business_language_live3",
|
||||
"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\\phase98_limit_honesty_business_language_live3",
|
||||
"final_status": "accepted",
|
||||
"review_overall_status": "pass",
|
||||
"business_overall_status": "pass",
|
||||
"steps_total": 6,
|
||||
"steps_passed": 6,
|
||||
"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,43 @@
|
|||
{
|
||||
"suite_id": "assistant_saved_session_gen-ag05122315-f1e27c",
|
||||
"suite_version": "0.1.0",
|
||||
"schema_version": "assistant_saved_session_suite_v0_1",
|
||||
"generated_at": "2026-05-12T23:15:48+00:00",
|
||||
"generation_id": "gen-ag05122315-f1e27c",
|
||||
"mode": "saved_user_sessions",
|
||||
"title": "AGENT | Phase 98 limit honesty and business-language replay",
|
||||
"domain": "address_phase98_limit_honesty_business_language",
|
||||
"scenario_count": 1,
|
||||
"case_ids": [
|
||||
"SAVED-001"
|
||||
],
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "SAVED-001",
|
||||
"scenario_tag": "agent_saved_user_sessions",
|
||||
"title": "AGENT | Phase 98 limit honesty and business-language replay",
|
||||
"question_type": "followup",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "По ООО Альтернатива Плюс на конец 2020 можно точно понять, какая дебиторка просрочена?"
|
||||
},
|
||||
{
|
||||
"user_message": "То есть просрочку доказать нельзя, коротко почему?"
|
||||
},
|
||||
{
|
||||
"user_message": "НДС за 2020 по ООО Альтернатива Плюс какой?"
|
||||
},
|
||||
{
|
||||
"user_message": "А кто принес больше всего денег за 2020?"
|
||||
},
|
||||
{
|
||||
"user_message": "По ООО Альтернатива Плюс на конец 2020 можно точно подтвердить резерв под неликвиды на складе?"
|
||||
},
|
||||
{
|
||||
"user_message": "А зависимость от одного поставщика за 2020 можно точно оценить?"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue