АРЧ АП11 - Commit title: Добавить контрактный слой переходов и capability-деклараций ассистента
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
# 01 - Project Architecture Baseline Map
|
||||
|
||||
## Purpose
|
||||
|
||||
This note is the compact execution-oriented map of the current project.
|
||||
|
||||
It is not a market review and not a historical report. It answers:
|
||||
|
||||
- what the main subsystems are;
|
||||
- where the assistant runtime really starts and ends;
|
||||
- what already acts as architecture, not as incidental code;
|
||||
- where the main structural debt sits.
|
||||
|
||||
## System Map
|
||||
|
||||
### 1. 1C Acquisition And Probe Layer
|
||||
|
||||
Main areas:
|
||||
|
||||
- `odata_probe/`
|
||||
- `scripts/*` probe and verification scripts
|
||||
|
||||
Role:
|
||||
|
||||
- verify read-only access viability;
|
||||
- inspect published 1C entity sets and links;
|
||||
- produce source-level readiness for higher layers.
|
||||
|
||||
This is a prerequisite layer, not the assistant runtime itself.
|
||||
|
||||
### 2. Canonical And Analytical Data Layer
|
||||
|
||||
Main areas:
|
||||
|
||||
- `canonical_layer/`
|
||||
- `data/`
|
||||
- `logs/`
|
||||
|
||||
Current runtime entry:
|
||||
|
||||
- [canonical_layer/app.py](/x:/1C/NDC_1C/canonical_layer/app.py:1)
|
||||
|
||||
Role:
|
||||
|
||||
- expose normalized read-only data services;
|
||||
- refresh and maintain the canonical store;
|
||||
- run feature engine;
|
||||
- run risk engine.
|
||||
|
||||
This layer is the project's data foundation.
|
||||
|
||||
### 3. LLM Backend And Assistant Runtime
|
||||
|
||||
Main area:
|
||||
|
||||
- `llm_normalizer/backend/`
|
||||
|
||||
Current server entry:
|
||||
|
||||
- [server.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/server.ts:1)
|
||||
|
||||
Role:
|
||||
|
||||
- provider gateway;
|
||||
- normalizer runtime;
|
||||
- assistant runtime;
|
||||
- eval runtime;
|
||||
- autorun runtime;
|
||||
- session persistence.
|
||||
|
||||
This is the architectural center of the interactive product.
|
||||
|
||||
### 4. Domain Orchestration And Acceptance Loop
|
||||
|
||||
Main areas:
|
||||
|
||||
- `.codex/`
|
||||
- `docs/orchestration/active_domain_contract.json`
|
||||
- `artifacts/domain_runs/`
|
||||
|
||||
Role:
|
||||
|
||||
- define the current active domain pack;
|
||||
- execute scenario-based hardening;
|
||||
- store machine-readable before/after artifacts;
|
||||
- turn user runs into acceptance and repair targets.
|
||||
|
||||
This is a first-class quality contour, not auxiliary documentation.
|
||||
|
||||
### 5. Experimental Routing / Benchmark Contour
|
||||
|
||||
Main area:
|
||||
|
||||
- `router/`
|
||||
|
||||
Role:
|
||||
|
||||
- route-selection experiments;
|
||||
- store-sufficiency heuristics;
|
||||
- benchmark and validation support via Python scripts.
|
||||
|
||||
Important:
|
||||
|
||||
- this contour is not the current source of truth for the production assistant runtime;
|
||||
- current production routing lives in the TypeScript assistant stack.
|
||||
|
||||
## Assistant Runtime Map
|
||||
|
||||
The assistant runtime currently has these working layers:
|
||||
|
||||
1. `provider/model gateway`
|
||||
2. `living router`
|
||||
3. `address orchestration runtime`
|
||||
4. `exact execution lane`
|
||||
5. `coverage / evidence / grounding`
|
||||
6. `answer policy / packaging / debug`
|
||||
7. `session memory / navigation state`
|
||||
|
||||
### Provider / Model Gateway
|
||||
|
||||
Current main entry:
|
||||
|
||||
- [openaiResponsesClient.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/openaiResponsesClient.ts:1)
|
||||
|
||||
Current shape:
|
||||
|
||||
- pragmatic two-mode provider layer: `openai` and `local`
|
||||
|
||||
This layer is functional, but future-fragile if hybrid execution semantics grow.
|
||||
|
||||
### Living Router
|
||||
|
||||
Current main entry:
|
||||
|
||||
- [assistantService.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantService.ts:4248)
|
||||
|
||||
Current top-level modes:
|
||||
|
||||
- `address_data`
|
||||
- `assistant_data_scope`
|
||||
- `chat`
|
||||
|
||||
This is where the system decides which runtime contour gets control.
|
||||
|
||||
### Address Orchestration Runtime
|
||||
|
||||
Current main entry:
|
||||
|
||||
- [assistantAddressOrchestrationRuntimeAdapter.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantAddressOrchestrationRuntimeAdapter.ts:1)
|
||||
|
||||
Current responsibilities:
|
||||
|
||||
- predecompose;
|
||||
- effective message normalization;
|
||||
- carryover resolution;
|
||||
- rewrite protection;
|
||||
- continuation contract assembly;
|
||||
- address runtime metadata.
|
||||
|
||||
### Exact Execution Lane
|
||||
|
||||
Current main areas:
|
||||
|
||||
- [addressQueryService.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/addressQueryService.ts:1)
|
||||
- [addressIntentResolver.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/addressIntentResolver.ts:1)
|
||||
- [addressFilterExtractor.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/addressFilterExtractor.ts:1)
|
||||
- [addressRecipeCatalog.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/addressRecipeCatalog.ts:1)
|
||||
- [decomposeStage.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/address_runtime/decomposeStage.ts:1325)
|
||||
- [composeStage.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/address_runtime/composeStage.ts:1)
|
||||
|
||||
This lane already acts as a real exact-data runtime, not as generic chat assistance.
|
||||
|
||||
### Coverage / Evidence / Grounding
|
||||
|
||||
Current main areas:
|
||||
|
||||
- [assistantCoverageGrounding.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantCoverageGrounding.ts:1)
|
||||
- [assistantClaimBoundEvidence.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantClaimBoundEvidence.ts:1)
|
||||
- [assistantDataLayer.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantDataLayer.ts:1)
|
||||
|
||||
This layer already exists in code, even if it has not yet been named strongly enough in architecture docs.
|
||||
|
||||
### Answer Policy / Packaging / Debug
|
||||
|
||||
Current main areas:
|
||||
|
||||
- [answerComposer.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/answerComposer.ts:1)
|
||||
- [assistantAnswerPackageBuilder.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantAnswerPackageBuilder.ts:1)
|
||||
- [assistantDebugPayloadAssembler.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantDebugPayloadAssembler.ts:1)
|
||||
|
||||
This layer should own answer shape, not truth determination.
|
||||
|
||||
### Session Memory / Navigation State
|
||||
|
||||
Current main areas:
|
||||
|
||||
- [assistantSessionStore.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantSessionStore.ts:1)
|
||||
- [addressNavigationState.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/addressNavigationState.ts:329)
|
||||
- [investigationState.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/investigationState.ts:1)
|
||||
|
||||
This layer is one of the strongest parts of the architecture today.
|
||||
|
||||
## First-Class Runtime Artifacts Already Present
|
||||
|
||||
The following should be treated as first-class architectural artifacts, not helper byproducts:
|
||||
|
||||
- `dialogContinuationContractV2`
|
||||
- `result_set`
|
||||
- `focus_object`
|
||||
- `date_scope`
|
||||
- `organization_scope`
|
||||
- `coverage report`
|
||||
- `grounding check`
|
||||
- `evidence bundle`
|
||||
- `scenario manifest`
|
||||
- `scenario state`
|
||||
- `baseline_turn / rerun_turn artifacts`
|
||||
|
||||
## Structural Debt
|
||||
|
||||
The main structural debt is concentrated in oversized modules with mixed responsibilities:
|
||||
|
||||
- `assistantService.ts`
|
||||
- `composeStage.ts`
|
||||
- `answerComposer.ts`
|
||||
- `addressQueryService.ts`
|
||||
- `assistantDataLayer.ts`
|
||||
|
||||
This indicates the following problem:
|
||||
|
||||
- the system already has the right layers;
|
||||
- but too many of those layers are still implemented as tightly coupled code inside a few large files.
|
||||
|
||||
## Baseline Constraints
|
||||
|
||||
Any architectural turnaround must preserve:
|
||||
|
||||
- `AddressQueryService` as exact lane;
|
||||
- structured navigation state;
|
||||
- continuation contract semantics;
|
||||
- selected-object continuity;
|
||||
- limited-mode truthfulness;
|
||||
- scenario-based acceptance.
|
||||
|
||||
## Baseline Diagnosis
|
||||
|
||||
The project is not missing architecture.
|
||||
|
||||
The project already has architecture, but it is still expressed too much through:
|
||||
|
||||
- god services;
|
||||
- implicit workflow;
|
||||
- heuristic branching;
|
||||
- mixed policy/state/answer concerns.
|
||||
|
||||
That is the baseline condition that the rest of this package is designed to address.
|
||||
@@ -0,0 +1,393 @@
|
||||
# 02 - State And Transition Contracts
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines the objects that must become explicit in project design:
|
||||
|
||||
1. `state objects`
|
||||
2. `transition classes`
|
||||
|
||||
The goal is to stop treating the assistant as a prompt-driven flow with ad hoc carryover and start treating it as a stateful runtime with explicit transitions.
|
||||
|
||||
## State Model
|
||||
|
||||
### 1. Assistant Session Aggregate
|
||||
|
||||
Top-level first-class runtime state:
|
||||
|
||||
`assistant_session_state`
|
||||
|
||||
It must aggregate:
|
||||
|
||||
- `living_mode_state`
|
||||
- `address_navigation_state`
|
||||
- `investigation_state`
|
||||
- `clarification_state`
|
||||
- `answer_context_state`
|
||||
- `coverage_gate_state`
|
||||
|
||||
This aggregate is the architectural owner of cross-turn continuity.
|
||||
|
||||
### 2. Living Mode State
|
||||
|
||||
Purpose:
|
||||
|
||||
- remember which major runtime contour is active.
|
||||
|
||||
Fields:
|
||||
|
||||
- `living_mode`
|
||||
- `mode_reason`
|
||||
- `mode_source`
|
||||
- `mode_entry_turn_id`
|
||||
|
||||
Allowed values:
|
||||
|
||||
- `address_data`
|
||||
- `assistant_data_scope`
|
||||
- `chat`
|
||||
- `meta_followup`
|
||||
- `clarification`
|
||||
|
||||
### 3. Root Frame State
|
||||
|
||||
Purpose:
|
||||
|
||||
- represent the currently active root business slice.
|
||||
|
||||
Fields:
|
||||
|
||||
- `domain_id`
|
||||
- `root_route_id`
|
||||
- `organization_scope`
|
||||
- `date_scope`
|
||||
- `root_result_set_id`
|
||||
- `root_answer_object_ref`
|
||||
- `frame_status`
|
||||
|
||||
This state survives more transitions than object state.
|
||||
|
||||
### 4. Selected Object Frame State
|
||||
|
||||
Purpose:
|
||||
|
||||
- represent the currently active drilldown object.
|
||||
|
||||
Fields:
|
||||
|
||||
- `focus_object_ref`
|
||||
- `focus_object_kind`
|
||||
- `source_result_set_id`
|
||||
- `compatible_route_family`
|
||||
- `provenance_bundle_ref`
|
||||
- `temporal_ceiling`
|
||||
- `frame_status`
|
||||
|
||||
This state may only survive compatible object-level transitions.
|
||||
|
||||
### 5. Meta Frame State
|
||||
|
||||
Purpose:
|
||||
|
||||
- support questions about the already returned answer without replaying exact execution blindly.
|
||||
|
||||
Fields:
|
||||
|
||||
- `source_answer_object_ref`
|
||||
- `meta_question_kind`
|
||||
- `source_gate_status`
|
||||
- `meta_truth_mode`
|
||||
|
||||
Allowed meta classes:
|
||||
|
||||
- `evaluation`
|
||||
- `comparison`
|
||||
- `memory_recap`
|
||||
- `boundary_explanation`
|
||||
- `answer_interpretation`
|
||||
|
||||
### 6. Clarification State
|
||||
|
||||
Purpose:
|
||||
|
||||
- represent unfinished business queries that are waiting for missing anchors or disambiguation.
|
||||
|
||||
Fields:
|
||||
|
||||
- `clarification_kind`
|
||||
- `missing_anchors`
|
||||
- `candidate_scopes`
|
||||
- `resume_target_route`
|
||||
- `resume_target_frame`
|
||||
|
||||
### 7. Coverage Gate State
|
||||
|
||||
Purpose:
|
||||
|
||||
- capture whether the exact execution result is admissible for full, partial, or blocked downstream behavior.
|
||||
|
||||
Fields:
|
||||
|
||||
- `coverage_status`
|
||||
- `evidence_grade`
|
||||
- `grounding_status`
|
||||
- `truth_mode`
|
||||
- `carryover_eligibility`
|
||||
- `reason_codes`
|
||||
|
||||
Allowed values:
|
||||
|
||||
- `coverage_status`: `full`, `partial`, `blocked`
|
||||
- `truth_mode`: `confirmed`, `limited`, `clarification_required`, `unsupported`
|
||||
- `carryover_eligibility`: `full`, `root_only`, `object_only`, `meta_only`, `none`
|
||||
|
||||
## Transition Model
|
||||
|
||||
The architecture must distinguish transition classes explicitly.
|
||||
|
||||
### T1. Root Query Entry
|
||||
|
||||
Trigger:
|
||||
|
||||
- new root business question
|
||||
|
||||
Inputs:
|
||||
|
||||
- raw user query
|
||||
- living mode state
|
||||
|
||||
Outputs:
|
||||
|
||||
- new `root_frame_state`
|
||||
- new `coverage_gate_state`
|
||||
|
||||
Must not:
|
||||
|
||||
- inherit stale `focus_object`
|
||||
|
||||
### T2. Root Follow-Up With Date Or Scope Change
|
||||
|
||||
Trigger:
|
||||
|
||||
- `а на март 2020`
|
||||
- `на тот же период`
|
||||
- `еще раз по этой дате`
|
||||
|
||||
Inputs:
|
||||
|
||||
- existing `root_frame_state`
|
||||
- compatible temporal or organization shift
|
||||
|
||||
Outputs:
|
||||
|
||||
- updated `root_frame_state`
|
||||
- new exact route execution
|
||||
|
||||
Must preserve:
|
||||
|
||||
- root domain
|
||||
- organization scope if not explicitly changed
|
||||
|
||||
Must not:
|
||||
|
||||
- downgrade into `unknown` if supported root route exists
|
||||
|
||||
### T3. Explicit Selected Object Drilldown
|
||||
|
||||
Trigger:
|
||||
|
||||
- item selected from current result set
|
||||
- UI selected-object wording
|
||||
- full explicit object mention
|
||||
|
||||
Inputs:
|
||||
|
||||
- active `root_frame_state`
|
||||
- selected object reference
|
||||
|
||||
Outputs:
|
||||
|
||||
- `selected_object_frame_state`
|
||||
|
||||
Must preserve:
|
||||
|
||||
- source result set
|
||||
- compatible temporal ceiling
|
||||
|
||||
### T4. Short Action Follow-Up On Selected Object
|
||||
|
||||
Trigger:
|
||||
|
||||
- `кто поставщик`
|
||||
- `где купили`
|
||||
- `кому продали`
|
||||
- `какие документы`
|
||||
|
||||
Inputs:
|
||||
|
||||
- active `selected_object_frame_state`
|
||||
- compatible action request
|
||||
|
||||
Outputs:
|
||||
|
||||
- exact item-level capability route
|
||||
|
||||
Must not:
|
||||
|
||||
- fall into generic chat
|
||||
- fall into data-scope selection
|
||||
- lose selected object because the wording is short
|
||||
|
||||
### T5. Pronoun Or Compressed Object Follow-Up
|
||||
|
||||
Trigger:
|
||||
|
||||
- `по ней`
|
||||
- `по этой позиции`
|
||||
- `а эта кому ушла`
|
||||
|
||||
Inputs:
|
||||
|
||||
- active `selected_object_frame_state`
|
||||
- prior compatible object route
|
||||
|
||||
Outputs:
|
||||
|
||||
- continued object drilldown
|
||||
|
||||
Must not:
|
||||
|
||||
- degrade full object anchor into vague semantic noise
|
||||
|
||||
### T6. Domain Pivot With Root-Only Carryover
|
||||
|
||||
Trigger:
|
||||
|
||||
- user leaves the current object drilldown but remains in compatible higher business scope
|
||||
|
||||
Inputs:
|
||||
|
||||
- `root_frame_state`
|
||||
- incompatible `selected_object_frame_state`
|
||||
|
||||
Outputs:
|
||||
|
||||
- preserved root context
|
||||
- dropped object context
|
||||
|
||||
Must preserve:
|
||||
|
||||
- organization/date root scope
|
||||
|
||||
Must not:
|
||||
|
||||
- replay object route into another domain
|
||||
|
||||
### T7. Clarification Continuation
|
||||
|
||||
Trigger:
|
||||
|
||||
- user resolves missing anchor or ambiguity
|
||||
|
||||
Inputs:
|
||||
|
||||
- active `clarification_state`
|
||||
|
||||
Outputs:
|
||||
|
||||
- resumed target route
|
||||
- cleared or updated clarification state
|
||||
|
||||
Must not:
|
||||
|
||||
- forget the suspended target route
|
||||
|
||||
### T8. Meta Follow-Up Over Answer Object
|
||||
|
||||
Trigger:
|
||||
|
||||
- `это много или мало`
|
||||
- `это мы должны или нам`
|
||||
- `что из этого важнее`
|
||||
|
||||
Inputs:
|
||||
|
||||
- `answer_context_state`
|
||||
- `coverage_gate_state`
|
||||
|
||||
Outputs:
|
||||
|
||||
- meta answer
|
||||
|
||||
Must not:
|
||||
|
||||
- blindly replay exact route
|
||||
|
||||
### T9. Memory Recap
|
||||
|
||||
Trigger:
|
||||
|
||||
- `мы это обсуждали?`
|
||||
- `помнишь, о чем говорили`
|
||||
|
||||
Inputs:
|
||||
|
||||
- prior grounded answer context
|
||||
|
||||
Outputs:
|
||||
|
||||
- truthful recap
|
||||
|
||||
Must not:
|
||||
|
||||
- invent conversation memory
|
||||
|
||||
### T10. Unsupported Or Blocked Boundary
|
||||
|
||||
Trigger:
|
||||
|
||||
- unsupported route
|
||||
- blocked evidence gate
|
||||
- execution failure
|
||||
|
||||
Inputs:
|
||||
|
||||
- exact runtime outcome
|
||||
- `coverage_gate_state`
|
||||
|
||||
Outputs:
|
||||
|
||||
- bounded truthful answer or clarification
|
||||
|
||||
Must not:
|
||||
|
||||
- masquerade blocked execution as confirmed factual answer
|
||||
|
||||
## Transition Invariants
|
||||
|
||||
Every transition must declare:
|
||||
|
||||
- `entry condition`
|
||||
- `required prior state`
|
||||
- `allowed carryover depth`
|
||||
- `state mutations`
|
||||
- `forbidden carryover`
|
||||
- `expected answer mode`
|
||||
|
||||
## Required Artifacts
|
||||
|
||||
Any future implementation of these contracts should produce:
|
||||
|
||||
- transition table or registry;
|
||||
- state schema definitions;
|
||||
- transition tests;
|
||||
- scenario acceptance coverage by transition class.
|
||||
|
||||
## Done Criteria
|
||||
|
||||
This document is only considered implemented in architecture when:
|
||||
|
||||
- every major follow-up case maps to a named transition class;
|
||||
- every transition class has a declared state owner;
|
||||
- every transition class has a scenario-based regression family;
|
||||
- no critical follow-up behavior depends only on unnamed heuristic carryover.
|
||||
@@ -0,0 +1,253 @@
|
||||
# 03 - Capability Contract Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines what every runtime capability must declare in order to participate safely in the assistant architecture.
|
||||
|
||||
The system should stop treating capabilities as partially implicit products of:
|
||||
|
||||
- intent detection;
|
||||
- filter extraction;
|
||||
- recipe selection;
|
||||
- wording heuristics.
|
||||
|
||||
Instead, each capability must be a first-class contract object.
|
||||
|
||||
## Capability Contract Object
|
||||
|
||||
Each capability must declare the following fields.
|
||||
|
||||
### 1. Identity
|
||||
|
||||
- `capability_id`
|
||||
- `domain_id`
|
||||
- `runtime_lane`
|
||||
- `intent_ids`
|
||||
|
||||
Purpose:
|
||||
|
||||
- stable identification;
|
||||
- relation between capability, domain and route family.
|
||||
|
||||
### 2. Entry Semantics
|
||||
|
||||
- `entry_modes`
|
||||
- `supported_transition_classes`
|
||||
- `frame_compatibility`
|
||||
|
||||
Minimum allowed values:
|
||||
|
||||
- `root_entry`
|
||||
- `root_followup`
|
||||
- `selected_object_drilldown`
|
||||
- `meta_reuse`
|
||||
- `clarification_resume`
|
||||
|
||||
Purpose:
|
||||
|
||||
- define where the capability may legally be entered from.
|
||||
|
||||
### 3. Anchor Contract
|
||||
|
||||
- `required_anchors`
|
||||
- `optional_anchors`
|
||||
- `anchor_source_priority`
|
||||
- `anchor_admissibility_rules`
|
||||
|
||||
Purpose:
|
||||
|
||||
- make anchor requirements explicit;
|
||||
- prevent garbage anchor extraction from being treated as business input.
|
||||
|
||||
### 4. Scope Contract
|
||||
|
||||
- `organization_scope_behavior`
|
||||
- `date_scope_behavior`
|
||||
- `temporal_ceiling_policy`
|
||||
- `root_context_compatibility`
|
||||
|
||||
Purpose:
|
||||
|
||||
- define whether the capability reuses, narrows, widens, or rejects prior scope.
|
||||
|
||||
### 5. Selected-Object Contract
|
||||
|
||||
- `requires_focus_object`
|
||||
- `accepted_focus_object_kinds`
|
||||
- `focus_object_override_policy`
|
||||
- `bundle_reuse_policy`
|
||||
|
||||
Purpose:
|
||||
|
||||
- define whether the capability depends on an existing selected object;
|
||||
- define how object continuity is preserved.
|
||||
|
||||
### 6. Execution Contract
|
||||
|
||||
- `resolver_owner`
|
||||
- `recipe_owner`
|
||||
- `execution_adapter`
|
||||
- `result_shape`
|
||||
- `answer_object_shape`
|
||||
|
||||
Purpose:
|
||||
|
||||
- clearly identify the exact runtime owner of execution and output form.
|
||||
|
||||
### 7. Truth Gate Contract
|
||||
|
||||
- `minimum_evidence_policy`
|
||||
- `coverage_gate_behavior`
|
||||
- `truth_mode_fallbacks`
|
||||
- `blocked_reason_codes`
|
||||
|
||||
Purpose:
|
||||
|
||||
- declare what counts as sufficient evidence for this capability;
|
||||
- prevent answer policy from inventing truth semantics later.
|
||||
|
||||
### 8. Clarification Contract
|
||||
|
||||
- `clarification_triggers`
|
||||
- `clarification_questions`
|
||||
- `resume_policy`
|
||||
|
||||
Purpose:
|
||||
|
||||
- define when the capability must ask, not guess.
|
||||
|
||||
### 9. Failure Contract
|
||||
|
||||
- `empty_match_behavior`
|
||||
- `route_expectation_failure_behavior`
|
||||
- `execution_error_behavior`
|
||||
|
||||
Purpose:
|
||||
|
||||
- keep failures truthful and stable.
|
||||
|
||||
### 10. Acceptance Contract
|
||||
|
||||
- `required_unit_tests`
|
||||
- `required_transition_tests`
|
||||
- `required_scenario_families`
|
||||
|
||||
Purpose:
|
||||
|
||||
- make capability completion measurable.
|
||||
|
||||
## Minimal Contract Template
|
||||
|
||||
Each capability should be designable in the following shape:
|
||||
|
||||
```yaml
|
||||
capability_id: inventory_purchase_provenance_for_item
|
||||
domain_id: inventory_stock
|
||||
runtime_lane: address_exact
|
||||
intent_ids:
|
||||
- inventory_purchase_provenance_for_item
|
||||
entry_modes:
|
||||
- selected_object_drilldown
|
||||
- clarification_resume
|
||||
supported_transition_classes:
|
||||
- T3
|
||||
- T4
|
||||
- T5
|
||||
frame_compatibility:
|
||||
root_frame: required
|
||||
selected_object_frame: required
|
||||
required_anchors:
|
||||
- item
|
||||
optional_anchors:
|
||||
- organization
|
||||
- date_scope
|
||||
anchor_admissibility_rules:
|
||||
- no_low_quality_item_rewrite
|
||||
- no_conversational_noise_as_entity
|
||||
organization_scope_behavior: reuse_or_clarify
|
||||
date_scope_behavior: respect_root_temporal_ceiling
|
||||
temporal_ceiling_policy: must_not_expand_beyond_root_without_reason_code
|
||||
requires_focus_object: true
|
||||
accepted_focus_object_kinds:
|
||||
- inventory_item
|
||||
bundle_reuse_policy: provenance_bundle_preferred
|
||||
minimum_evidence_policy: route_specific_threshold
|
||||
coverage_gate_behavior: partial_or_blocked_if_evidence_insufficient
|
||||
empty_match_behavior: truthful_empty_match
|
||||
required_scenario_families:
|
||||
- canonical
|
||||
- colloquial
|
||||
- ui_selected_object
|
||||
- short_action_followup
|
||||
- pronoun_followup
|
||||
```
|
||||
|
||||
## Contract Rules
|
||||
|
||||
### Rule 1. Capability Must Declare Entry Legality
|
||||
|
||||
No capability may be entered only because a heuristic guessed it.
|
||||
|
||||
It must declare:
|
||||
|
||||
- which transition classes are legal;
|
||||
- which frames are required;
|
||||
- which frames are incompatible.
|
||||
|
||||
### Rule 2. Capability Must Declare Admissible Anchors
|
||||
|
||||
No capability may silently accept low-quality business anchors.
|
||||
|
||||
It must declare:
|
||||
|
||||
- what entity values are required;
|
||||
- what counts as an admissible extracted value;
|
||||
- when clarification is mandatory.
|
||||
|
||||
### Rule 3. Capability Must Declare Truth Gate Behavior
|
||||
|
||||
No capability may leave truth semantics to answer wording.
|
||||
|
||||
It must declare:
|
||||
|
||||
- what evidence threshold it needs;
|
||||
- how it behaves under partial evidence;
|
||||
- when it becomes blocked.
|
||||
|
||||
### Rule 4. Capability Must Declare Selected-Object Compatibility
|
||||
|
||||
All selected-object actions must explicitly declare:
|
||||
|
||||
- whether they require focus object;
|
||||
- whether they reuse a bundle from prior steps;
|
||||
- whether they tolerate short follow-up wording.
|
||||
|
||||
### Rule 5. Capability Must Declare Scenario Coverage
|
||||
|
||||
A capability is not accepted just because canonical wording works.
|
||||
|
||||
At minimum it must declare which of the following wording families are required:
|
||||
|
||||
- `canonical`
|
||||
- `colloquial`
|
||||
- `ui_selected_object`
|
||||
- `ui_selected_object_colloquial`
|
||||
- `short_action_followup`
|
||||
- `pronoun_followup`
|
||||
- `followup_date_carryover`
|
||||
|
||||
## What This Specification Replaces
|
||||
|
||||
This specification is designed to reduce architectural pressure on:
|
||||
|
||||
- `assistantService`
|
||||
- hidden carryover logic
|
||||
- implicit capability semantics in answer shaping
|
||||
|
||||
## Done Criteria
|
||||
|
||||
This specification is considered operational only when:
|
||||
|
||||
- critical capabilities are represented as explicit contract objects;
|
||||
- contract fields are sufficient to predict allowed entry, required anchors, truth behavior, and scenario acceptance;
|
||||
- new capability enablement can be reviewed primarily through contract review and tests, not only by reading large service files.
|
||||
@@ -0,0 +1,196 @@
|
||||
# 04 - Coverage Evidence Truth Gate
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines the missing architectural layer between:
|
||||
|
||||
- `exact execution lane`
|
||||
|
||||
and
|
||||
|
||||
- `answer policy / packaging`
|
||||
|
||||
This layer must exist as a first-class object because the system already needs to answer questions such as:
|
||||
|
||||
- do we have enough evidence;
|
||||
- is the result full, partial, or blocked;
|
||||
- may this result power follow-up carryover;
|
||||
- is limited mode required;
|
||||
- can the assistant speak as confirmed truth or only as bounded evidence.
|
||||
|
||||
## Architectural Position
|
||||
|
||||
The target runtime stack should be read as:
|
||||
|
||||
1. route and transition policy
|
||||
2. exact execution lane
|
||||
3. `coverage / evidence / truth gate`
|
||||
4. answer policy
|
||||
5. packaging and debug
|
||||
|
||||
Answer policy must not own the truth gate.
|
||||
|
||||
## Current Code Owners
|
||||
|
||||
The gate already exists in code in fragmented form:
|
||||
|
||||
- [assistantCoverageGrounding.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantCoverageGrounding.ts:1)
|
||||
- [assistantClaimBoundEvidence.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantClaimBoundEvidence.ts:1)
|
||||
- [assistantDataLayer.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantDataLayer.ts:622)
|
||||
- [addressQueryService.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/addressQueryService.ts:2806)
|
||||
- [answerComposer.ts](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/answerComposer.ts:22)
|
||||
|
||||
The architectural problem is not absence, but insufficient naming and isolation.
|
||||
|
||||
## Gate Inputs
|
||||
|
||||
The gate should consume:
|
||||
|
||||
- exact runtime result
|
||||
- normalized retrieval result
|
||||
- evidence items
|
||||
- candidate evidence items
|
||||
- coverage report
|
||||
- route expectation outcome
|
||||
- current frame state
|
||||
- requested truth mode
|
||||
|
||||
## Gate Outputs
|
||||
|
||||
The gate should produce:
|
||||
|
||||
- `coverage_status`
|
||||
- `grounding_status`
|
||||
- `truth_mode`
|
||||
- `carryover_eligibility`
|
||||
- `reason_codes`
|
||||
- `evidence_grade`
|
||||
- `blocked_or_limited_explanation`
|
||||
|
||||
These outputs must be machine-readable.
|
||||
|
||||
## Status Classes
|
||||
|
||||
### 1. `full_confirmed`
|
||||
|
||||
Meaning:
|
||||
|
||||
- coverage is sufficient;
|
||||
- evidence is admissible;
|
||||
- route expectation passed;
|
||||
- answer may speak in confirmed mode.
|
||||
|
||||
### 2. `partial_supported`
|
||||
|
||||
Meaning:
|
||||
|
||||
- some evidence exists;
|
||||
- some requirements remain uncovered or weakly covered;
|
||||
- answer must remain bounded and explicit about limitations.
|
||||
|
||||
### 3. `blocked_missing_anchor`
|
||||
|
||||
Meaning:
|
||||
|
||||
- exact execution cannot safely complete because required anchors are unresolved.
|
||||
|
||||
### 4. `blocked_route_expectation_failure`
|
||||
|
||||
Meaning:
|
||||
|
||||
- route was attempted, but the route contract itself did not pass baseline expectations.
|
||||
|
||||
### 5. `blocked_execution_error`
|
||||
|
||||
Meaning:
|
||||
|
||||
- system failure or execution failure prevents reliable business answer.
|
||||
|
||||
### 6. `limited_temporal_or_contextual`
|
||||
|
||||
Meaning:
|
||||
|
||||
- the system can say something useful, but only within a narrow and explicit evidence window.
|
||||
|
||||
## Carryover Eligibility Contract
|
||||
|
||||
The gate must also determine follow-up eligibility.
|
||||
|
||||
Allowed values:
|
||||
|
||||
- `full`
|
||||
- `root_only`
|
||||
- `object_only`
|
||||
- `meta_only`
|
||||
- `none`
|
||||
|
||||
Examples:
|
||||
|
||||
- `full_confirmed` result from root stock snapshot may often allow `full` or `root_only`
|
||||
- selected-object provenance with weak buyer evidence may allow `object_only` or `meta_only`
|
||||
- blocked route expectation should usually allow `none`
|
||||
|
||||
## Truth Rules
|
||||
|
||||
### Rule 1. Answer Policy May Downgrade, But Not Upgrade
|
||||
|
||||
Answer policy may choose a clearer wording.
|
||||
|
||||
Answer policy may not:
|
||||
|
||||
- turn blocked into confirmed;
|
||||
- turn partial into full;
|
||||
- suppress critical truth reason codes.
|
||||
|
||||
### Rule 2. Limited Mode Must Remain Truthful
|
||||
|
||||
If evidence is insufficient, limited mode must be explicit about:
|
||||
|
||||
- what is confirmed;
|
||||
- what is not confirmed;
|
||||
- why the system is limited.
|
||||
|
||||
### Rule 3. Carryover Must Respect The Gate
|
||||
|
||||
Follow-up policy may not assume that every previous answer is equally reusable.
|
||||
|
||||
Carryover must obey:
|
||||
|
||||
- gate-produced eligibility;
|
||||
- evidence window;
|
||||
- blocked or limited reason codes.
|
||||
|
||||
### Rule 4. Route Expectation Failure Is A Truth Event
|
||||
|
||||
If route expectation fails, this is not just a technical footnote.
|
||||
|
||||
It is a first-class truth gate outcome.
|
||||
|
||||
## Required Gate Artifacts
|
||||
|
||||
Every gated answer should be traceable through these artifacts:
|
||||
|
||||
- `evidence_bundle`
|
||||
- `coverage_contract`
|
||||
- `grounding_check`
|
||||
- `truth_mode`
|
||||
- `carryover_eligibility`
|
||||
- `reason_codes`
|
||||
|
||||
## Non-Goals
|
||||
|
||||
This gate is not responsible for:
|
||||
|
||||
- model wording style;
|
||||
- cosmetic answer formatting;
|
||||
- provider selection;
|
||||
- UI packaging details.
|
||||
|
||||
## Done Criteria
|
||||
|
||||
This layer is considered architecturally established only when:
|
||||
|
||||
- it is documented as separate from answer policy;
|
||||
- its outputs are explicit inputs to answer shaping;
|
||||
- carryover policy depends on gate output rather than hidden heuristics;
|
||||
- scenario acceptance can fail specifically on gate behavior, not only on final wording.
|
||||
@@ -0,0 +1,213 @@
|
||||
# 05 - AssistantService Extraction Map
|
||||
|
||||
## Purpose
|
||||
|
||||
This document maps the current architectural overload of `assistantService.ts` and identifies what should stop living there over time.
|
||||
|
||||
The goal is not to empty the file arbitrarily.
|
||||
|
||||
The goal is to turn it from a god-service into a thinner coordinator.
|
||||
|
||||
## Current Situation
|
||||
|
||||
`assistantService.ts` is currently the largest and most overloaded module in the assistant runtime.
|
||||
|
||||
Approximate size:
|
||||
|
||||
- `6243` lines
|
||||
|
||||
It currently mixes concerns from:
|
||||
|
||||
- living route selection;
|
||||
- follow-up carryover;
|
||||
- continuation contracts;
|
||||
- mode boundaries;
|
||||
- meta-followup logic;
|
||||
- memory recap detection;
|
||||
- provider-aware predecompose orchestration;
|
||||
- chat/data-scope/address boundary policy.
|
||||
|
||||
## Extraction Principle
|
||||
|
||||
`assistantService` should remain the top-level coordinator.
|
||||
|
||||
It should stop being the main owner of:
|
||||
|
||||
- policy logic;
|
||||
- transition semantics;
|
||||
- boundary semantics;
|
||||
- meta semantics.
|
||||
|
||||
## Extraction Targets
|
||||
|
||||
### 1. Living Route Policy
|
||||
|
||||
Current owner:
|
||||
|
||||
- `resolveAssistantOrchestrationDecision()`
|
||||
|
||||
Current location:
|
||||
|
||||
- [assistantService.ts:4248](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantService.ts:4248)
|
||||
|
||||
Target owner:
|
||||
|
||||
- `assistantRoutePolicyRuntimeAdapter`
|
||||
|
||||
Expected artifact:
|
||||
|
||||
- explicit living-route decision contract
|
||||
|
||||
Done when:
|
||||
|
||||
- route policy can be reviewed without reading the full coordinator;
|
||||
- top-level mode decisions are data-driven or contract-driven enough to be testable as a separate unit.
|
||||
|
||||
### 2. Carryover And Transition Policy
|
||||
|
||||
Current owner:
|
||||
|
||||
- `resolveAddressFollowupCarryoverContext()`
|
||||
- `buildAddressDialogContinuationContractV2()`
|
||||
|
||||
Current location:
|
||||
|
||||
- [assistantService.ts:2828](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantService.ts:2828)
|
||||
- [assistantService.ts:3111](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantService.ts:3111)
|
||||
|
||||
Target owner:
|
||||
|
||||
- `assistantTransitionRuntimeAdapter`
|
||||
- `assistantContinuationContractBuilder`
|
||||
|
||||
Expected artifact:
|
||||
|
||||
- explicit transition classes with state inputs and carryover depth
|
||||
|
||||
Done when:
|
||||
|
||||
- follow-up continuation is understood in terms of transitions, not just heuristic carryover.
|
||||
|
||||
### 3. Meta Follow-Up Policy
|
||||
|
||||
Current owner:
|
||||
|
||||
- meta and evaluative follow-up detection inside route decision logic
|
||||
|
||||
Target owner:
|
||||
|
||||
- `assistantMetaFollowupPolicy`
|
||||
|
||||
Expected artifact:
|
||||
|
||||
- meta question class registry
|
||||
- legal source answer object types
|
||||
|
||||
Done when:
|
||||
|
||||
- meta questions no longer depend on implicit branches buried inside living route logic.
|
||||
|
||||
### 4. Data-Scope And Boundary Policy
|
||||
|
||||
Current owner:
|
||||
|
||||
- `assistant_data_scope_query_detected` branches
|
||||
|
||||
Current references:
|
||||
|
||||
- [assistantService.ts:3974](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantService.ts:3974)
|
||||
- [assistantService.ts:4412](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantService.ts:4412)
|
||||
- [assistantService.ts:6052](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantService.ts:6052)
|
||||
|
||||
Target owner:
|
||||
|
||||
- `assistantBoundaryPolicy`
|
||||
|
||||
Expected artifact:
|
||||
|
||||
- explicit boundary mode contract:
|
||||
- `data_scope`
|
||||
- `operational_boundary`
|
||||
- `capability_contract`
|
||||
- `non_domain_chat`
|
||||
|
||||
Done when:
|
||||
|
||||
- emotional or colloquial user messages cannot accidentally trigger data-scope selection through hidden shared logic.
|
||||
|
||||
### 5. Memory Recap Policy
|
||||
|
||||
Current owner:
|
||||
|
||||
- route decision + living chat cooperation
|
||||
|
||||
Related consumer:
|
||||
|
||||
- [assistantLivingChatRuntimeAdapter.ts:255](/x:/1C/NDC_1C/llm_normalizer/backend/src/services/assistantLivingChatRuntimeAdapter.ts:255)
|
||||
|
||||
Target owner:
|
||||
|
||||
- `assistantMemoryRecapPolicy`
|
||||
|
||||
Expected artifact:
|
||||
|
||||
- truthful recap contract over grounded prior answer objects
|
||||
|
||||
Done when:
|
||||
|
||||
- memory recap logic becomes a named subsystem with its own truth rules.
|
||||
|
||||
### 6. Provider-Aware Orchestration Glue
|
||||
|
||||
Current owner:
|
||||
|
||||
- coordinator-level logic that adapts to `openai` vs `local`
|
||||
|
||||
Target owner:
|
||||
|
||||
- `assistantProviderExecutionPolicy`
|
||||
|
||||
Expected artifact:
|
||||
|
||||
- provider/runtime compatibility layer for orchestration expectations
|
||||
|
||||
Done when:
|
||||
|
||||
- provider quirks no longer leak into business routing logic.
|
||||
|
||||
## What Should Stay In AssistantService
|
||||
|
||||
After extraction, `assistantService` should still own:
|
||||
|
||||
- high-level request coordination;
|
||||
- dependency wiring;
|
||||
- stage invocation order;
|
||||
- final turn assembly and persistence orchestration.
|
||||
|
||||
It should not be removed as an architectural object.
|
||||
|
||||
It should become thinner.
|
||||
|
||||
## Proposed Extraction Order
|
||||
|
||||
1. extract route decision contract
|
||||
2. extract transition/carryover policy
|
||||
3. extract boundary/data-scope policy
|
||||
4. extract meta and memory recap policy
|
||||
5. isolate provider-aware orchestration glue
|
||||
|
||||
This order is chosen because route and transition pressure are currently the main source of runtime fragility.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- do not split the file mechanically just to reduce line count;
|
||||
- do not create many tiny helpers with no architectural ownership;
|
||||
- do not move exact execution logic out of its proper lane.
|
||||
|
||||
## Done Criteria
|
||||
|
||||
This extraction plan is complete only when:
|
||||
|
||||
- the remaining `assistantService` can be described as a coordinator;
|
||||
- major policy categories have explicit owners outside `assistantService`;
|
||||
- scenario regressions can point to policy subsystems instead of a single god-service.
|
||||
@@ -0,0 +1,238 @@
|
||||
# 06 - Phase Acceptance Matrix
|
||||
|
||||
## Purpose
|
||||
|
||||
This document turns the high-level turnaround direction into a phase-by-phase execution matrix.
|
||||
|
||||
Each phase must specify:
|
||||
|
||||
- `goal`
|
||||
- `output artifacts`
|
||||
- `done criteria`
|
||||
- `non-goals`
|
||||
- `acceptance signals`
|
||||
|
||||
## Phase 0. Shared Baseline
|
||||
|
||||
Goal:
|
||||
|
||||
- align the team on one architecture vocabulary and one baseline map.
|
||||
|
||||
Output artifacts:
|
||||
|
||||
- baseline note in `docs/ARCH/11 - unified_project_architecture_and_reference_update_plan_2026-04-15.md`
|
||||
- this package under `docs/ARCH/11 - architecture_turnaround/`
|
||||
|
||||
Done when:
|
||||
|
||||
- project discussions use the same names for layers, state, transitions, truth gate, and capabilities;
|
||||
- no major planning discussion treats the system as "just a chat with LLM".
|
||||
|
||||
Non-goals:
|
||||
|
||||
- code changes;
|
||||
- capability rewrites.
|
||||
|
||||
Acceptance signals:
|
||||
|
||||
- planning references point to the package rather than ad hoc prose;
|
||||
- new refactor proposals can be mapped to a package artifact.
|
||||
|
||||
## Phase 1. Formal Layer Separation
|
||||
|
||||
Goal:
|
||||
|
||||
- explicitly separate project subsystems and their sources of truth.
|
||||
|
||||
Output artifacts:
|
||||
|
||||
- updated architecture notes if needed;
|
||||
- clear internal naming for:
|
||||
- data foundation
|
||||
- assistant runtime
|
||||
- domain loop
|
||||
- experimental router contour
|
||||
|
||||
Done when:
|
||||
|
||||
- production assistant routing is no longer confused with Python router experiments;
|
||||
- `canonical_layer` and `llm_normalizer/backend` are treated as different subsystems in planning.
|
||||
|
||||
Non-goals:
|
||||
|
||||
- merging runtimes;
|
||||
- changing domain behavior.
|
||||
|
||||
Acceptance signals:
|
||||
|
||||
- no architecture review uses the wrong contour as the current runtime source of truth.
|
||||
|
||||
## Phase 2. State And Transition Contracts
|
||||
|
||||
Goal:
|
||||
|
||||
- make state and transition classes explicit.
|
||||
|
||||
Output artifacts:
|
||||
|
||||
- state schema note
|
||||
- transition class registry note
|
||||
- transition-oriented tests or planning matrix
|
||||
|
||||
Done when:
|
||||
|
||||
- every critical follow-up path is described as a named transition class;
|
||||
- root frame, selected object frame, meta frame, clarification state, and coverage gate state are explicit objects.
|
||||
|
||||
Non-goals:
|
||||
|
||||
- answer wording cleanup;
|
||||
- adding new business capabilities.
|
||||
|
||||
Acceptance signals:
|
||||
|
||||
- critical scenario failures can be described as transition failures, not only as "assistant got confused";
|
||||
- at least one major follow-up-heavy domain can be read through transition contracts alone.
|
||||
|
||||
## Phase 3. Capability Contracts
|
||||
|
||||
Goal:
|
||||
|
||||
- make capabilities explicit contract objects instead of half-implicit route behavior.
|
||||
|
||||
Output artifacts:
|
||||
|
||||
- capability contract schema
|
||||
- pilot contract set for critical inventory capabilities
|
||||
|
||||
Done when:
|
||||
|
||||
- critical capabilities declare entry modes, anchors, scope policy, truth behavior, and scenario families;
|
||||
- new capability review can happen via contract inspection.
|
||||
|
||||
Non-goals:
|
||||
|
||||
- low-code workflow migration;
|
||||
- removing recipe catalog.
|
||||
|
||||
Acceptance signals:
|
||||
|
||||
- at least one selected-object capability and one root capability are represented as full contract specs.
|
||||
|
||||
## Phase 4. Coverage / Evidence / Truth Gate Isolation
|
||||
|
||||
Goal:
|
||||
|
||||
- separate truth determination from answer policy.
|
||||
|
||||
Output artifacts:
|
||||
|
||||
- gate contract
|
||||
- reason-code taxonomy
|
||||
- carryover-eligibility contract
|
||||
|
||||
Done when:
|
||||
|
||||
- answer layer no longer decides whether a result is full, partial, or blocked;
|
||||
- truth mode and carryover eligibility are explicit gate outputs.
|
||||
|
||||
Non-goals:
|
||||
|
||||
- UI redesign;
|
||||
- full answer package rewrite.
|
||||
|
||||
Acceptance signals:
|
||||
|
||||
- scenario regressions can fail specifically on gate semantics;
|
||||
- limited mode honesty is measurable independently from wording quality.
|
||||
|
||||
## Phase 5. AssistantService Extraction
|
||||
|
||||
Goal:
|
||||
|
||||
- reduce `assistantService` from god-service to coordinator.
|
||||
|
||||
Output artifacts:
|
||||
|
||||
- extraction map
|
||||
- named policy owners
|
||||
- reduced coordinator responsibility map
|
||||
|
||||
Done when:
|
||||
|
||||
- route policy, transition policy, boundary policy, and meta policy have explicit owners outside the coordinator;
|
||||
- `assistantService` retains orchestration ownership but not most raw policy logic.
|
||||
|
||||
Non-goals:
|
||||
|
||||
- file splitting for its own sake;
|
||||
- replacing the coordinator with a monolithic new router.
|
||||
|
||||
Acceptance signals:
|
||||
|
||||
- scenario regressions can point to extracted policy owners;
|
||||
- code review no longer requires reading most of `assistantService.ts` to understand one policy area.
|
||||
|
||||
## Phase 6. Provider / Runtime Axis Hardening
|
||||
|
||||
Goal:
|
||||
|
||||
- make provider/runtime behavior an explicit architectural concern.
|
||||
|
||||
Output artifacts:
|
||||
|
||||
- provider execution contract
|
||||
- structured-output compatibility matrix
|
||||
- local/openai execution semantics note
|
||||
|
||||
Done when:
|
||||
|
||||
- provider quirks no longer bleed into business routing policy;
|
||||
- structured output, tool calling expectations, and fallback behavior are documented per provider mode.
|
||||
|
||||
Non-goals:
|
||||
|
||||
- adding many providers immediately;
|
||||
- model benchmarking as primary objective.
|
||||
|
||||
Acceptance signals:
|
||||
|
||||
- changing provider mode does not silently change core business semantics without explicit compatibility review.
|
||||
|
||||
## Phase 7. Scenario Acceptance As Primary Gate
|
||||
|
||||
Goal:
|
||||
|
||||
- enforce scenario-tree acceptance as the refactoring completion standard.
|
||||
|
||||
Output artifacts:
|
||||
|
||||
- phase-specific acceptance matrix
|
||||
- updated scenario packs and required wording families
|
||||
|
||||
Done when:
|
||||
|
||||
- no phase is considered complete based only on unit tests or prettier answers;
|
||||
- critical paths, critical edges, and selected-object continuity remain mandatory acceptance criteria.
|
||||
|
||||
Non-goals:
|
||||
|
||||
- shrinking evaluation to smoke tests;
|
||||
- accepting root-only success as domain completion.
|
||||
|
||||
Acceptance signals:
|
||||
|
||||
- `pack_state.final_status`
|
||||
- scenario acceptance matrix
|
||||
- no unresolved `P0`
|
||||
- direct answer, temporal honesty, selected-object continuity, and truth gate invariants all pass.
|
||||
|
||||
## Cross-Phase Rule
|
||||
|
||||
A phase is not done when the code "looks cleaner".
|
||||
|
||||
A phase is done only when:
|
||||
|
||||
- the declared artifact exists;
|
||||
- the responsible layer is explicit;
|
||||
- acceptance signals are green.
|
||||
@@ -0,0 +1,135 @@
|
||||
# 07 - External Reference Appendix
|
||||
|
||||
## Purpose
|
||||
|
||||
This appendix keeps external references available without overloading the core planning documents.
|
||||
|
||||
It records:
|
||||
|
||||
- which pattern is borrowed;
|
||||
- why it is relevant;
|
||||
- what should not be copied literally.
|
||||
|
||||
## Dify
|
||||
|
||||
Sources:
|
||||
|
||||
- <https://github.com/langgenius/dify>
|
||||
- <https://docs.dify.ai/versions/3-0-x/en/user-guide/workflow/key-concepts>
|
||||
- <https://docs.dify.ai/en/use-dify/nodes/agent>
|
||||
- <https://docs.dify.ai/en/use-dify/nodes/variable-assigner>
|
||||
|
||||
Borrow:
|
||||
|
||||
- explicit distinction between workflow and chatflow;
|
||||
- named nodes for classifier, agent, answer, variable management;
|
||||
- persistent conversation variables.
|
||||
|
||||
Do not borrow literally:
|
||||
|
||||
- low-code canvas as a direct replacement for exact 1C runtime logic.
|
||||
|
||||
## Open WebUI
|
||||
|
||||
Sources:
|
||||
|
||||
- <https://github.com/open-webui/open-webui>
|
||||
- <https://docs.openwebui.com/features/extensibility/>
|
||||
- <https://docs.openwebui.com/features/chat-conversations/rag/>
|
||||
|
||||
Borrow:
|
||||
|
||||
- layered extensibility model;
|
||||
- clear distinction between in-process tools, external APIs, and separate heavy pipelines;
|
||||
- input/output filter mindset.
|
||||
|
||||
Do not borrow literally:
|
||||
|
||||
- generic plugin-first shell as the main architecture for exact-data routing.
|
||||
|
||||
## Onyx
|
||||
|
||||
Sources:
|
||||
|
||||
- <https://github.com/onyx-dot-app/onyx>
|
||||
- <https://docs.onyx.app/admins/actions/overview>
|
||||
|
||||
Borrow:
|
||||
|
||||
- platform view of chat, agents, actions, connectors;
|
||||
- separation between indexed knowledge, actions, and chat experience.
|
||||
|
||||
Do not borrow literally:
|
||||
|
||||
- enterprise search architecture as a substitute for 1C exact route discipline.
|
||||
|
||||
## LibreChat
|
||||
|
||||
Sources:
|
||||
|
||||
- <https://github.com/danny-avila/LibreChat>
|
||||
- <https://www.librechat.ai/docs/features/agents>
|
||||
|
||||
Borrow:
|
||||
|
||||
- explicit agent capability surface;
|
||||
- tool exposure discipline;
|
||||
- deferred tools concept.
|
||||
|
||||
Do not borrow literally:
|
||||
|
||||
- treat MCP/tool abundance as a substitute for domain-specific capability contracts.
|
||||
|
||||
## Vanna
|
||||
|
||||
Source:
|
||||
|
||||
- <https://github.com/vanna-ai/vanna>
|
||||
|
||||
Borrow:
|
||||
|
||||
- exact-data assistant framing;
|
||||
- tool registry plus structured outputs;
|
||||
- user-aware execution semantics.
|
||||
|
||||
Do not borrow literally:
|
||||
|
||||
- SQL assistant assumptions as the whole model for our multi-layer accounting runtime.
|
||||
|
||||
## DB-GPT
|
||||
|
||||
Source:
|
||||
|
||||
- <https://github.com/eosphoros-ai/DB-GPT>
|
||||
|
||||
Borrow:
|
||||
|
||||
- AI data assistant as platform-plus-domain-skill composition;
|
||||
- workflows and skills as explicit architectural objects.
|
||||
|
||||
Do not borrow literally:
|
||||
|
||||
- broad platform scope at the expense of current bounded hardening goals.
|
||||
|
||||
## LangGraph
|
||||
|
||||
Source:
|
||||
|
||||
- <https://docs.langchain.com/oss/javascript/langgraph/durable-execution>
|
||||
|
||||
Borrow:
|
||||
|
||||
- durable execution mindset;
|
||||
- checkpointing and deterministic replay;
|
||||
- explicit state graph thinking.
|
||||
|
||||
Do not borrow literally:
|
||||
|
||||
- framework migration as an end in itself.
|
||||
|
||||
## Summary
|
||||
|
||||
The external references collectively support one conclusion:
|
||||
|
||||
- the project should move toward more explicit state, transition, and capability contracts;
|
||||
- it should not dissolve its exact-data rails into a generic agent shell.
|
||||
@@ -0,0 +1,70 @@
|
||||
# 11 - Architecture Turnaround Package
|
||||
|
||||
## Purpose
|
||||
|
||||
This folder is the execution-oriented continuation of the baseline note:
|
||||
|
||||
- [11 - unified_project_architecture_and_reference_update_plan_2026-04-15.md](</x:/1C/NDC_1C/docs/ARCH/11 - unified_project_architecture_and_reference_update_plan_2026-04-15.md:1>)
|
||||
|
||||
That baseline note answers:
|
||||
|
||||
- what the project is today;
|
||||
- where the main architectural fragility sits;
|
||||
- what direction is safe.
|
||||
|
||||
This package answers the next question:
|
||||
|
||||
- how the team should design the architectural turnaround without breaking the current exact-data baseline.
|
||||
|
||||
## Package Contents
|
||||
|
||||
1. [01 - project_architecture_baseline_map.md](./01%20-%20project_architecture_baseline_map.md)
|
||||
2. [02 - state_and_transition_contracts.md](./02%20-%20state_and_transition_contracts.md)
|
||||
3. [03 - capability_contract_spec.md](./03%20-%20capability_contract_spec.md)
|
||||
4. [04 - coverage_evidence_truth_gate.md](./04%20-%20coverage_evidence_truth_gate.md)
|
||||
5. [05 - assistantService_extraction_map.md](./05%20-%20assistantService_extraction_map.md)
|
||||
6. [06 - phase_acceptance_matrix.md](./06%20-%20phase_acceptance_matrix.md)
|
||||
7. [07 - external_reference_appendix.md](./07%20-%20external_reference_appendix.md)
|
||||
|
||||
## Architectural Objects Of Planning
|
||||
|
||||
This package makes five objects explicit:
|
||||
|
||||
1. `state model`
|
||||
2. `transition model`
|
||||
3. `capability contract model`
|
||||
4. `coverage / evidence / truth gate`
|
||||
5. `assistantService extraction plan`
|
||||
|
||||
These are the objects that should now drive refactoring discussions.
|
||||
|
||||
## How To Use The Package
|
||||
|
||||
Read in this order:
|
||||
|
||||
1. baseline note in `docs/ARCH/11 - unified_project_architecture_and_reference_update_plan_2026-04-15.md`
|
||||
2. `01 - project_architecture_baseline_map.md`
|
||||
3. `02 - state_and_transition_contracts.md`
|
||||
4. `03 - capability_contract_spec.md`
|
||||
5. `04 - coverage_evidence_truth_gate.md`
|
||||
6. `05 - assistantService_extraction_map.md`
|
||||
7. `06 - phase_acceptance_matrix.md`
|
||||
8. `07 - external_reference_appendix.md`
|
||||
|
||||
## Planning Rules
|
||||
|
||||
- Do not treat this package as a rewrite plan.
|
||||
- Do not dissolve `AddressQueryService` into generic chat logic.
|
||||
- Do not move state back into transcript-only memory.
|
||||
- Do not let answer wording substitute for policy/runtime fixes.
|
||||
- Use scenario-based acceptance as the primary gate for all phases.
|
||||
|
||||
## Expected Outcome
|
||||
|
||||
When this package is fully operational, the project should stop being described as:
|
||||
|
||||
- "a big custom assistant service with many heuristics"
|
||||
|
||||
and start being described as:
|
||||
|
||||
- "a stateful exact-data assistant with explicit transition contracts and isolated truth gating."
|
||||
+992
@@ -0,0 +1,992 @@
|
||||
# 11 - Unified Project Architecture And Reference Update Plan 2026-04-15
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует единый архитектурный срез проекта `NDC_1C` на `2026-04-15` и связывает:
|
||||
|
||||
- текущее фактическое устройство репозитория;
|
||||
- текущее устройство assistant runtime;
|
||||
- уже существующие архитектурные ограничения и сильные стороны;
|
||||
- внешний reference landscape из open-source LLM-проектов;
|
||||
- безопасный план обновления подхода без разрушения рабочего baseline.
|
||||
|
||||
Связанный execution-oriented пакет planning artifacts:
|
||||
|
||||
- [11 - architecture_turnaround](</x:/1C/NDC_1C/docs/ARCH/11 - architecture_turnaround/README.md:1>)
|
||||
|
||||
Документ нужен не для исторического обзора, а как единая опорная карта:
|
||||
|
||||
- что в проекте уже является устойчивым фундаментом;
|
||||
- что является техническим и архитектурным долгом;
|
||||
- где проект типовой по классу систем;
|
||||
- где проект уже имеет осмысленную кастомную специализацию;
|
||||
- как переходить от heuristic-heavy hardening к более устойчивой архитектурной форме.
|
||||
|
||||
Этот документ дополняет, а не заменяет:
|
||||
|
||||
- `docs/ARCH/10 - current_assistant_architecture_2026-04-15.md`
|
||||
- `docs/ARCH/10A - current_assistant_hardening_plan_2026-04-15.md`
|
||||
- `graphify-out/GRAPH_REPORT.md`
|
||||
|
||||
|
||||
## 2. Executive Summary
|
||||
|
||||
На текущем этапе `NDC_1C` уже не является "просто чат-приложением с LLM".
|
||||
|
||||
Фактически проект состоит из нескольких самостоятельных архитектурных контуров:
|
||||
|
||||
1. `1C/OData acquisition + canonical layer`
|
||||
2. `feature/risk engines over canonical store`
|
||||
3. `LLM normalizer + assistant runtime`
|
||||
4. `domain orchestration / scenario loop / eval artifacts`
|
||||
5. `research and benchmark contour` вокруг Python `router/`
|
||||
|
||||
Главный вывод по результатам локального анализа и сравнения с open-source references:
|
||||
|
||||
- по классу продукта проект действительно типовой: это `LLM + tools/data + state + UI/API`;
|
||||
- по реализации текущий runtime у нас уже существенно более специализирован, чем обычный generic chat shell;
|
||||
- основная проблема проекта не в отсутствии "правильной идеи", а в том, что слишком много системной политики собрано вручную внутри нескольких очень больших модулей;
|
||||
- мы уже имеем сильные архитектурные элементы, которые нельзя терять;
|
||||
- правильный следующий шаг это не rewrite в сторону "универсального суперагента", а переход к более явной workflow/state-oriented форме поверх уже существующих exact-capability rails.
|
||||
|
||||
Короткая формула:
|
||||
|
||||
`проект типовой по классу`
|
||||
|
||||
но
|
||||
|
||||
`архитектурно перегружен ручной orchestration-логикой`
|
||||
|
||||
и потому
|
||||
|
||||
`нуждается не в изобретении новых возможностей, а в упорядочивании существующих слоев`.
|
||||
|
||||
|
||||
## 3. Источники для этого среза
|
||||
|
||||
### 3.1 Локальные источники
|
||||
|
||||
- `graphify-out/GRAPH_REPORT.md`
|
||||
- `README.md`
|
||||
- `canonical_layer/app.py`
|
||||
- `llm_normalizer/backend/src/server.ts`
|
||||
- `llm_normalizer/backend/src/services/*`
|
||||
- `docs/orchestration/active_domain_contract.json`
|
||||
- `.codex/` и `artifacts/domain_runs/*`
|
||||
|
||||
### 3.2 Внешние reference sources
|
||||
|
||||
- Dify: <https://github.com/langgenius/dify>
|
||||
- Dify docs, key concepts: <https://docs.dify.ai/versions/3-0-x/en/user-guide/workflow/key-concepts>
|
||||
- Dify docs, agent node: <https://docs.dify.ai/en/use-dify/nodes/agent>
|
||||
- Dify docs, variable assigner: <https://docs.dify.ai/en/use-dify/nodes/variable-assigner>
|
||||
- Open WebUI: <https://github.com/open-webui/open-webui>
|
||||
- Open WebUI docs, extensibility: <https://docs.openwebui.com/features/extensibility/>
|
||||
- Open WebUI docs, RAG: <https://docs.openwebui.com/features/chat-conversations/rag/>
|
||||
- Onyx: <https://github.com/onyx-dot-app/onyx>
|
||||
- Onyx docs, actions overview: <https://docs.onyx.app/admins/actions/overview>
|
||||
- LibreChat: <https://github.com/danny-avila/LibreChat>
|
||||
- LibreChat docs, agents: <https://www.librechat.ai/docs/features/agents>
|
||||
- Vanna: <https://github.com/vanna-ai/vanna>
|
||||
- DB-GPT: <https://github.com/eosphoros-ai/DB-GPT>
|
||||
- LangGraph docs, durable execution: <https://docs.langchain.com/oss/javascript/langgraph/durable-execution>
|
||||
|
||||
|
||||
## 4. Текущая карта проекта целиком
|
||||
|
||||
### 4.1 Верхнеуровневые контуры репозитория
|
||||
|
||||
Текущий репозиторий содержит не один сервис, а несколько связанных слоев:
|
||||
|
||||
- `odata_probe/`
|
||||
- слой исследования и проверки read-only доступа к 1C OData;
|
||||
- `canonical_layer/`
|
||||
- Python/FastAPI слой над канонической моделью и хранилищем;
|
||||
- `llm_normalizer/backend/`
|
||||
- TypeScript/Express runtime для LLM normalizer, assistant, eval и autoruns;
|
||||
- `router/`
|
||||
- Python policy/benchmark контур для route selection и sufficiency checks;
|
||||
- `orchestration/`
|
||||
- служебный orchestration runtime для batch/use-case loops;
|
||||
- `docs/orchestration/active_domain_contract.json`
|
||||
- single mutable source для текущего активного domain/scenario pack;
|
||||
- `.codex/`
|
||||
- project-scoped loop/orchestration навыки и роли;
|
||||
- `artifacts/domain_runs/`
|
||||
- машинно-читаемые артефакты сценарных прогонов и hardening loop;
|
||||
- `graphify-out/`
|
||||
- knowledge graph и архитектурный срез кодовой базы.
|
||||
|
||||
### 4.2 Ключевой смысл этой композиции
|
||||
|
||||
Проект уже организован как многоступенчатая AI/data система:
|
||||
|
||||
1. сначала добываются и нормализуются read-only данные 1C;
|
||||
2. затем они кладутся в канонический слой и feature/risk engines;
|
||||
3. затем поверх них строится exact-data assistant runtime;
|
||||
4. затем этот runtime проверяется domain scenarios, evaluation и artifacts;
|
||||
5. отдельно существует research/policy contour, который не является главным runtime.
|
||||
|
||||
Это важно: обсуждая архитектуру, нельзя сводить проект только к `llm_normalizer/backend`.
|
||||
|
||||
|
||||
## 5. Слой 1: 1C acquisition и canonical layer
|
||||
|
||||
### 5.1 Что это такое
|
||||
|
||||
Базовый контур проекта по-прежнему rooted в read-only интеграции с 1C.
|
||||
|
||||
Это видно уже из top-level README:
|
||||
|
||||
- `odata_probe/` собирает и проверяет доступность entity sets и link semantics;
|
||||
- `canonical_layer/` строит каноническую модель поверх 1C данных;
|
||||
- проект принципиально read-only по policy.
|
||||
|
||||
### 5.2 Текущая реализация
|
||||
|
||||
`canonical_layer/app.py` поднимает FastAPI-приложение:
|
||||
|
||||
- `CanonicalService`
|
||||
- `RefreshService`
|
||||
- `FeatureService`
|
||||
- `RiskService`
|
||||
|
||||
Доступные API-поверхности включают:
|
||||
|
||||
- `GET /documents`
|
||||
- `GET /postings`
|
||||
- `GET /graph/document/{document_id}`
|
||||
- `POST /refresh/run`
|
||||
- `POST /features/run`
|
||||
- `POST /risk/run`
|
||||
|
||||
То есть canonical layer уже не ограничивается "просто прокси к 1C", а включает:
|
||||
|
||||
- data access API;
|
||||
- refresh pipeline;
|
||||
- feature engine;
|
||||
- risk engine.
|
||||
|
||||
### 5.3 Архитектурная роль
|
||||
|
||||
Этот слой это не accessory для ассистента, а нижний data foundation проекта.
|
||||
|
||||
Именно он отвечает за:
|
||||
|
||||
- устойчивый read-only доступ;
|
||||
- канонизацию сущностей;
|
||||
- промежуточное локальное store-представление;
|
||||
- data services, которые могут использоваться не только LLM-слоем.
|
||||
|
||||
По классу архитектуры это типичный `data platform substrate` для AI assistant products.
|
||||
|
||||
|
||||
## 6. Слой 2: LLM normalizer backend
|
||||
|
||||
### 6.1 Входная точка
|
||||
|
||||
`llm_normalizer/backend/src/server.ts` поднимает Express-приложение и регистрирует:
|
||||
|
||||
- `/api/health`
|
||||
- `testConnection`
|
||||
- `sharedLlmConfig`
|
||||
- `normalize`
|
||||
- `eval`
|
||||
- `assistant`
|
||||
- `autoRuns`
|
||||
- `history`
|
||||
- `presets`
|
||||
- `accountingAgent`
|
||||
|
||||
Текущая сборка сервисов:
|
||||
|
||||
- `OpenAIResponsesClient`
|
||||
- `NormalizerService`
|
||||
- `EvalService`
|
||||
- `AssistantSessionStore`
|
||||
- `AssistantService`
|
||||
- `InMemoryRuntimeAdapter`
|
||||
|
||||
### 6.2 Что это значит
|
||||
|
||||
Backend уже совмещает несколько ролей:
|
||||
|
||||
- LLM gateway;
|
||||
- normalizer runtime;
|
||||
- assistant runtime;
|
||||
- eval runtime;
|
||||
- batch/autorun runtime;
|
||||
- session persistence for assistant mode.
|
||||
|
||||
Именно здесь архитектура становится наиболее плотной и наиболее хрупкой.
|
||||
|
||||
|
||||
## 7. Слой 3: Текущая архитектура assistant runtime
|
||||
|
||||
### 7.1 Зафиксированная форма
|
||||
|
||||
Согласно `ARCH 10` и текущему коду, assistant runtime уже устроен как пятислойная система:
|
||||
|
||||
1. `living router`
|
||||
2. `address orchestration runtime`
|
||||
3. `address exact execution lane`
|
||||
4. `session memory + navigation state`
|
||||
5. `answer/debug contract layer`
|
||||
|
||||
### 7.2 Living router
|
||||
|
||||
Главная точка выбора режима сейчас это:
|
||||
|
||||
- `resolveAssistantOrchestrationDecision()` в `assistantService.ts`
|
||||
|
||||
Текущие верхние living modes:
|
||||
|
||||
- `address_data`
|
||||
- `assistant_data_scope`
|
||||
- `chat`
|
||||
|
||||
На этом слое решается:
|
||||
|
||||
- идти ли в exact data contour;
|
||||
- уйти ли в data-scope/meta contract;
|
||||
- оставить ли запрос в обычном chat mode;
|
||||
- перехватить ли follow-up/meta/memory case.
|
||||
|
||||
### 7.3 Address orchestration runtime
|
||||
|
||||
Вынесен в:
|
||||
|
||||
- `assistantAddressOrchestrationRuntimeAdapter.ts`
|
||||
|
||||
Он уже отвечает за:
|
||||
|
||||
- LLM predecompose и fallback predecompose;
|
||||
- нормализацию effective message;
|
||||
- resolution carryover context;
|
||||
- защиту от плохой canonical rewrite;
|
||||
- сборку `dialogContinuationContract`;
|
||||
- формирование `addressRuntimeMeta`.
|
||||
|
||||
Это уже похоже не на "просто helper", а на отдельный orchestration stage.
|
||||
|
||||
### 7.4 Exact execution lane
|
||||
|
||||
Текущий exact lane строится вокруг:
|
||||
|
||||
- `AddressQueryService`
|
||||
- `addressRecipeCatalog`
|
||||
- `addressCapabilityPolicy`
|
||||
- `addressIntentResolver`
|
||||
- `addressFilterExtractor`
|
||||
- `address_runtime/decomposeStage.ts`
|
||||
- `address_runtime/composeStage.ts`
|
||||
|
||||
Именно этот слой исполняет конкретные capabilities, routes и recipes.
|
||||
|
||||
### 7.5 Session/navigation state
|
||||
|
||||
Критический текущий актив:
|
||||
|
||||
- `addressNavigationState.ts`
|
||||
|
||||
State уже хранит:
|
||||
|
||||
- `active_result_set_id`
|
||||
- `active_focus_object`
|
||||
- `last_confirmed_route`
|
||||
- `date_scope`
|
||||
- `organization_scope`
|
||||
- `result_sets`
|
||||
- `navigation_history`
|
||||
|
||||
То есть система уже не полагается только на transcript memory.
|
||||
|
||||
### 7.6 Answer/debug contract layer
|
||||
|
||||
Ответ формируется не напрямую из LLM output, а через отдельный packaging/debug contour:
|
||||
|
||||
- `answerComposer.ts`
|
||||
- `assistantAnswerPackageBuilder.ts`
|
||||
- `assistantDebugPayloadAssembler.ts`
|
||||
- `assistantStage4AnswerContractAudit.ts`
|
||||
|
||||
Это означает, что проект уже имеет машинно-читаемые answer/debug rails, а не просто "text in/text out".
|
||||
|
||||
|
||||
## 8. Что graphify говорит о текущей кодовой базе
|
||||
|
||||
На `2026-04-15` по `graphify-out/GRAPH_REPORT.md`:
|
||||
|
||||
- корпус: `473 files`
|
||||
- граф: `4865 nodes`
|
||||
- `10622 edges`
|
||||
- `132 communities`
|
||||
|
||||
Ключевые god nodes:
|
||||
|
||||
- `resolveAddressIntent()`
|
||||
- `composeFactualReply()`
|
||||
- `resolveAssistantOrchestrationDecision()`
|
||||
|
||||
Наиболее важные сообщества для assistant runtime:
|
||||
|
||||
- orchestration around `AssistantService`
|
||||
- exact execution around `AddressQueryService`
|
||||
- navigation state / focus object / result sets
|
||||
- address orchestration runtime adapters
|
||||
|
||||
Это подтверждает центральный архитектурный факт:
|
||||
|
||||
`главная форма системы уже не prompt-centric, а runtime-centric`
|
||||
|
||||
но при этом
|
||||
|
||||
`runtime слишком сильно сосредоточен вокруг нескольких god modules`.
|
||||
|
||||
|
||||
## 9. Что в проекте уже сделано сильно
|
||||
|
||||
### 9.1 Structured state вместо transcript-only memory
|
||||
|
||||
Во многих LLM-продуктах контекст держится только историей сообщений.
|
||||
|
||||
У нас уже есть явные сущности:
|
||||
|
||||
- `result_set`
|
||||
- `focus_object`
|
||||
- `date_scope`
|
||||
- `organization_scope`
|
||||
- `last_confirmed_route`
|
||||
|
||||
Это зрелее, чем у большинства generic agent shells.
|
||||
|
||||
### 9.2 Exact-data lane как отдельный контур
|
||||
|
||||
`AddressQueryService` у нас уже отделен от chat/mode выбора.
|
||||
|
||||
Это означает:
|
||||
|
||||
- есть шанс держать business truthfulness;
|
||||
- есть шанс тестировать exact capabilities отдельно;
|
||||
- можно hardening делать не только через wording, но и через route policy.
|
||||
|
||||
### 9.3 Limited mode и truthfulness rails
|
||||
|
||||
В кодовой базе уже присутствуют:
|
||||
|
||||
- route expectation contracts;
|
||||
- limited mode;
|
||||
- missing anchor handling;
|
||||
- honesty around empty/incomplete results.
|
||||
|
||||
Это правильное направление для exact assistant над бухгалтерскими данными.
|
||||
|
||||
### 9.4 Scenario-oriented hardening loop
|
||||
|
||||
Через `artifacts/domain_runs/*` и `.codex/skills/domain-case-loop` проект уже имеет не только тесты, но и domain acceptance artifacts:
|
||||
|
||||
- `baseline_turn.json`
|
||||
- `rerun_turn.json`
|
||||
- `scenario_manifest.json`
|
||||
- `scenario_state.json`
|
||||
- acceptance matrices
|
||||
|
||||
Это очень сильная инженерная практика, которой нет у многих open-source chat products.
|
||||
|
||||
|
||||
## 10. Где сейчас архитектурная хрупкость
|
||||
|
||||
### 10.1 God services
|
||||
|
||||
По размеру и плотности ответственности особенно выделяются:
|
||||
|
||||
- `assistantService.ts` - 6243 lines
|
||||
- `address_runtime/composeStage.ts` - 4817 lines
|
||||
- `answerComposer.ts` - 4681 lines
|
||||
- `addressQueryService.ts` - 4415 lines
|
||||
- `assistantDataLayer.ts` - 4272 lines
|
||||
|
||||
Это главный симптом того, что:
|
||||
|
||||
- routing;
|
||||
- state evolution;
|
||||
- policy;
|
||||
- answer shaping;
|
||||
- partial chat/meta behavior;
|
||||
- exact capability glue
|
||||
|
||||
слишком часто живут в одних и тех же модулях.
|
||||
|
||||
### 10.2 Implicit workflow вместо explicit workflow
|
||||
|
||||
Система уже ведет себя как state machine, но выражена в основном через:
|
||||
|
||||
- `if/else`
|
||||
- guard trees
|
||||
- carryover heuristics
|
||||
- rewrite protection
|
||||
- mode decisions
|
||||
|
||||
а не через явный graph/workflow model.
|
||||
|
||||
Из-за этого:
|
||||
|
||||
- локальный фикс легко меняет глобальное поведение;
|
||||
- сложно визуально понимать допустимые переходы;
|
||||
- acceptance часто приходится собирать эмпирически по прогонам.
|
||||
|
||||
### 10.3 Policy смешана с orchestration и answer layer
|
||||
|
||||
В текущей форме слишком много policy decisions живет внутри orchestration ядра:
|
||||
|
||||
- domain pivot
|
||||
- meta-followup
|
||||
- memory recap
|
||||
- data-scope boundary
|
||||
- short follow-up behavior
|
||||
- raw vs canonical message preference
|
||||
|
||||
Это делает систему чувствительной к incremental patching.
|
||||
|
||||
### 10.4 Provider/runtime abstraction узкая
|
||||
|
||||
`OpenAIResponsesClient` сейчас фактически является главным LLM gateway с режимом:
|
||||
|
||||
- `openai`
|
||||
- `local`
|
||||
|
||||
То есть провайдерная архитектура пока прагматичная, но не полноформатная.
|
||||
|
||||
Для текущего этапа этого достаточно, но это означает:
|
||||
|
||||
- модельный слой пока не является сильной самостоятельной осью архитектуры;
|
||||
- orchestration и provider logic не так чисто разведены, как в крупных product shells.
|
||||
|
||||
### 10.5 Python router не является главным runtime
|
||||
|
||||
`router/` полезен как bench/policy contour:
|
||||
|
||||
- `query_classifier.py`
|
||||
- `route_selector.py`
|
||||
- `store_sufficiency.py`
|
||||
|
||||
Но он не является source of truth для текущего assistant runtime.
|
||||
|
||||
Это значит, что:
|
||||
|
||||
- нельзя проектировать основную архитектуру, думая, что Python router и есть текущий production routing;
|
||||
- любые будущие сближения этих контуров надо делать явно и документированно.
|
||||
|
||||
|
||||
## 11. Что показывают внешние references
|
||||
|
||||
### 11.1 Dify
|
||||
|
||||
Полезный architectural pattern:
|
||||
|
||||
- явное разделение `Workflow` и `Chatflow`;
|
||||
- node-based orchestration;
|
||||
- встроенные classifier, agent, tool, variable, answer nodes;
|
||||
- отдельные conversation variables, переживающие многоходовый чат.
|
||||
|
||||
Что полезно для нас:
|
||||
|
||||
- идея сделать часть нашей текущей implicit orchestration более явной;
|
||||
- отделить workflow state от answer wording;
|
||||
- использовать более явную модель conversation variables/state transitions.
|
||||
|
||||
Что не нужно делать буквально:
|
||||
|
||||
- переписывать текущий exact runtime в low-code canvas;
|
||||
- пытаться заменить существующие domain rails на generic visual flow.
|
||||
|
||||
### 11.2 Open WebUI
|
||||
|
||||
Полезный architectural pattern:
|
||||
|
||||
- product shell + extensibility layers;
|
||||
- разделение на in-process tools, external OpenAPI/MCP, separate pipelines;
|
||||
- input/output filters;
|
||||
- четкое понимание, где живут heavy operations.
|
||||
|
||||
Что полезно для нас:
|
||||
|
||||
- явнее развести `tool/action layer`, `message filters`, `heavy execution lanes`;
|
||||
- отделить extensibility concerns от core orchestration;
|
||||
- думать о boundary/filter layer как о самостоятельном слое.
|
||||
|
||||
### 11.3 Onyx
|
||||
|
||||
Полезный architectural pattern:
|
||||
|
||||
- AI platform как слой поверх connectors/search/chat/agents/actions;
|
||||
- MCP/OpenAPI actions;
|
||||
- enterprise-friendly separation между agents, actions и indexed knowledge.
|
||||
|
||||
Что полезно для нас:
|
||||
|
||||
- видеть assistant не как monolith, а как application layer;
|
||||
- усиливать distinction между exact domain actions и general conversational shell.
|
||||
|
||||
### 11.4 LibreChat
|
||||
|
||||
Полезный architectural pattern:
|
||||
|
||||
- agent/tool shell;
|
||||
- MCP integration;
|
||||
- deferred tools, чтобы не перегружать контекст;
|
||||
- тонкая настройка agent capabilities.
|
||||
|
||||
Что полезно для нас:
|
||||
|
||||
- capability exposure должен быть более декларативным;
|
||||
- tool universe не должен быть размазан по orchestration heuristics;
|
||||
- selection of available actions может быть более explicit.
|
||||
|
||||
### 11.5 Vanna
|
||||
|
||||
Полезный architectural pattern:
|
||||
|
||||
- exact-data assistant через agent + tool registry;
|
||||
- user-aware execution;
|
||||
- structured UI outputs;
|
||||
- observability и lifecycle hooks.
|
||||
|
||||
Что полезно для нас:
|
||||
|
||||
- точные data routes надо трактовать как first-class actions;
|
||||
- identity/scope/date constraints должны протекать через tool execution и answer shape явно;
|
||||
- structured outputs должны быть устойчивым контрактом.
|
||||
|
||||
### 11.6 DB-GPT
|
||||
|
||||
Полезный architectural pattern:
|
||||
|
||||
- AI data assistant как отдельный класс продукта;
|
||||
- skills, workflows, SQL/code execution, sandboxing;
|
||||
- separation between platform and domain skills.
|
||||
|
||||
Что полезно для нас:
|
||||
|
||||
- наш проект не обязательно "уникален";
|
||||
- data assistant products уже давно строятся как composable platform + domain logic;
|
||||
- это аргумент в пользу архитектурной декомпозиции, а не против нее.
|
||||
|
||||
### 11.7 LangGraph
|
||||
|
||||
Полезный conceptual pattern:
|
||||
|
||||
- durable execution;
|
||||
- persistence/checkpointing;
|
||||
- deterministic replay;
|
||||
- explicit state graph;
|
||||
- idempotent tasks.
|
||||
|
||||
Что полезно для нас:
|
||||
|
||||
- follow-up heavy assistant с carryover почти неизбежно выигрывает от explicit state graph mindset;
|
||||
- наш current navigation state уже является хорошей базой для более graph-like architecture;
|
||||
- особенно важно для multi-turn domain scenarios и bounded recovery после ошибок.
|
||||
|
||||
|
||||
## 12. Где мы типовые, а где уже нет
|
||||
|
||||
### 12.1 Типовые части проекта
|
||||
|
||||
Мы полностью типовые в следующем:
|
||||
|
||||
- есть LLM gateway;
|
||||
- есть tool/data execution;
|
||||
- есть retrieval/data grounding;
|
||||
- есть session state;
|
||||
- есть answer packaging;
|
||||
- есть eval/autorun контур;
|
||||
- есть multi-layer backend over business data.
|
||||
|
||||
В этом смысле проект действительно не изобретает новый класс систем.
|
||||
|
||||
### 12.2 Нетиповые, но сильные части
|
||||
|
||||
Мы уже сильнее generic OSS chat shells в следующем:
|
||||
|
||||
- exact capability discipline;
|
||||
- structured navigation state;
|
||||
- selected-object continuity;
|
||||
- scenario-tree acceptance;
|
||||
- limited-mode truthfulness;
|
||||
- explicit answer/debug contracts;
|
||||
- domain hardening through machine-readable artifacts.
|
||||
|
||||
Это нельзя терять в погоне за "более красивой" типовой архитектурой.
|
||||
|
||||
### 12.3 Нетиповые и хрупкие части
|
||||
|
||||
Мы хрупки там, где типовые проекты обычно используют более явный framework layer:
|
||||
|
||||
- implicit orchestration inside god services;
|
||||
- policy encoded in large custom functions;
|
||||
- state transitions expressed through heuristic branches instead of explicit graph/node semantics;
|
||||
- boundary/meta handling слишком тесно связано с main assistant coordinator.
|
||||
|
||||
|
||||
## 13. Что нельзя ломать при архитектурном обновлении
|
||||
|
||||
При любом дальнейшем update plan нельзя разрушать следующие baseline элементы:
|
||||
|
||||
- `AddressQueryService` как отдельный exact lane;
|
||||
- `addressNavigationState` с `result_set/focus_object/date_scope/organization_scope`;
|
||||
- `dialogContinuationContractV2`;
|
||||
- selected-object continuity;
|
||||
- route expectation audit;
|
||||
- limited mode truthfulness;
|
||||
- domain artifacts и scenario acceptance loop;
|
||||
- `docs/orchestration/active_domain_contract.json` как mutable active domain source.
|
||||
|
||||
Принцип:
|
||||
|
||||
`generic best practices не должны размывать exact-data baseline`.
|
||||
|
||||
|
||||
## 14. Unified diagnosis
|
||||
|
||||
На `2026-04-15` архитектурная проблема проекта формулируется так:
|
||||
|
||||
### 14.1 Не проблема
|
||||
|
||||
Проблема не в том, что:
|
||||
|
||||
- проект слишком специфичен;
|
||||
- проект делает что-то принципиально уникальное;
|
||||
- для проекта не существует внешних референсов;
|
||||
- нужен новый "умный супер-роутер", который заменит все существующие слои.
|
||||
|
||||
### 14.2 Реальная проблема
|
||||
|
||||
Реальная проблема в том, что:
|
||||
|
||||
- правильные слои уже есть;
|
||||
- правильные state entities уже есть;
|
||||
- правильный exact runtime уже есть;
|
||||
|
||||
но
|
||||
|
||||
- orchestration и policy слишком централизованы;
|
||||
- implicit workflow слишком велик;
|
||||
- код слишком легко деградирует от incremental heuristics;
|
||||
- system behavior недостаточно выражен как явные runtime contracts и state transitions.
|
||||
|
||||
Коротко:
|
||||
|
||||
`архитектура не отсутствует`
|
||||
|
||||
а
|
||||
|
||||
`архитектура уже есть, но собрана слишком вручную и слишком плотно`.
|
||||
|
||||
|
||||
## 15. Целевой update direction
|
||||
|
||||
Правильное направление обновления:
|
||||
|
||||
`не rewrite`
|
||||
|
||||
и
|
||||
|
||||
`не новый универсальный агент`
|
||||
|
||||
а
|
||||
|
||||
`explicit workflow/state shell поверх существующих exact rails`.
|
||||
|
||||
Это значит:
|
||||
|
||||
- меньше hidden orchestration;
|
||||
- больше explicit route/state contracts;
|
||||
- тоньше coordinator modules;
|
||||
- более явные boundaries между:
|
||||
- route policy;
|
||||
- state transition policy;
|
||||
- capability registry/execution;
|
||||
- answer policy;
|
||||
- meta/chat boundary.
|
||||
|
||||
|
||||
## 16. План обновления по найденным references
|
||||
|
||||
### Phase 0. Зафиксировать единый baseline
|
||||
|
||||
Цель:
|
||||
|
||||
- прекратить обсуждать проект как "просто LLM чат";
|
||||
- закрепить единый словарь слоев и boundaries.
|
||||
|
||||
Что сделать:
|
||||
|
||||
- использовать этот документ как общий architecture map;
|
||||
- сохранить `ARCH 10` и `ARCH 10A` как assistant-runtime specific docs;
|
||||
- считать текущий baseline immutable without explicit note.
|
||||
|
||||
Ожидаемый результат:
|
||||
|
||||
- любые дальнейшие изменения обсуждаются относительно явной карты проекта, а не по ощущениям.
|
||||
|
||||
### Phase 1. Развести проектные слои формально
|
||||
|
||||
Borrowed pattern:
|
||||
|
||||
- product shell layering из Open WebUI / Onyx
|
||||
|
||||
Цель:
|
||||
|
||||
- явно отделить:
|
||||
- data foundation;
|
||||
- assistant runtime;
|
||||
- orchestration/eval loop;
|
||||
- experimental router contour.
|
||||
|
||||
Что обновить концептуально:
|
||||
|
||||
- `canonical_layer` и `llm_normalizer/backend` должны описываться как разные subsystems;
|
||||
- Python `router/` должен быть явно помечен как benchmark/research contour;
|
||||
- `.codex` и `artifacts/domain_runs` должны считаться отдельным quality/hardening contour.
|
||||
|
||||
Ожидаемый результат:
|
||||
|
||||
- меньше путаницы, где именно находится source of truth для runtime behavior.
|
||||
|
||||
### Phase 2. Вынести orchestration grammar в явные contracts
|
||||
|
||||
Borrowed pattern:
|
||||
|
||||
- Workflow/Chatflow + conversation variables из Dify
|
||||
- state graph mindset из LangGraph
|
||||
|
||||
Цель:
|
||||
|
||||
- превратить главный orchestration policy из "большого дерева if-ов" в более явный contract system.
|
||||
|
||||
Что обновить концептуально:
|
||||
|
||||
- формализовать переходы между:
|
||||
- `address_data`
|
||||
- `assistant_data_scope`
|
||||
- `chat`
|
||||
- `meta-followup`
|
||||
- `memory-recap`
|
||||
- `organization-clarification`
|
||||
- для каждого класса перехода иметь:
|
||||
- входной trigger class;
|
||||
- допустимый carryover depth;
|
||||
- allowed state reuse;
|
||||
- forbidden cross-domain leakage;
|
||||
- expected answer mode.
|
||||
|
||||
Ожидаемый результат:
|
||||
|
||||
- routing перестает быть набором локальных heuristic patches и становится описуемой state policy.
|
||||
|
||||
### Phase 3. Разделить root policy и object policy
|
||||
|
||||
Borrowed pattern:
|
||||
|
||||
- explicit conversation variables из Dify
|
||||
- durable state semantics из LangGraph
|
||||
|
||||
Цель:
|
||||
|
||||
- окончательно закрепить различие между:
|
||||
- `root frame`
|
||||
- `selected object frame`
|
||||
- `meta frame`
|
||||
|
||||
Что обновить концептуально:
|
||||
|
||||
- root state живет дольше и используется шире;
|
||||
- object state переносится только в совместимых сценариях;
|
||||
- meta state работает поверх answer object/result object, а не replay-ит exact route вслепую.
|
||||
|
||||
Ожидаемый результат:
|
||||
|
||||
- меньше ложных carryover;
|
||||
- меньше cross-domain contamination;
|
||||
- меньше случайных уходов в generic chat.
|
||||
|
||||
### Phase 4. Сделать capability exposure более декларативным
|
||||
|
||||
Borrowed pattern:
|
||||
|
||||
- tool/action registry from LibreChat / Open WebUI / Vanna / Onyx
|
||||
|
||||
Цель:
|
||||
|
||||
- capabilities должны быть first-class registry, а не только следствием разбросанной policy.
|
||||
|
||||
Что обновить концептуально:
|
||||
|
||||
- описывать capability не только через intent/resolver;
|
||||
- дополнительно иметь явные поля:
|
||||
- supported wording families;
|
||||
- allowed anchor types;
|
||||
- selected-object compatibility;
|
||||
- root-context compatibility;
|
||||
- meta-followup compatibility;
|
||||
- answer mode;
|
||||
- clarification policy.
|
||||
|
||||
Ожидаемый результат:
|
||||
|
||||
- меньше логики в giant service functions;
|
||||
- больше declarative routing discipline.
|
||||
|
||||
### Phase 5. Выделить answer policy как самостоятельный слой
|
||||
|
||||
Borrowed pattern:
|
||||
|
||||
- answer nodes / structured outputs из Dify и Vanna
|
||||
- filters/boundary layers из Open WebUI
|
||||
|
||||
Цель:
|
||||
|
||||
- отделить:
|
||||
- exact answer shape;
|
||||
- limited answer shape;
|
||||
- clarification shape;
|
||||
- meta/explanatory shape;
|
||||
- operational boundary shape.
|
||||
|
||||
Что обновить концептуально:
|
||||
|
||||
- не позволять routing fix-ам решаться только wording patch-ами;
|
||||
- answer layer должен знать свой response class и формировать shape по контракту;
|
||||
- `direct_answer_first` должен быть частью policy, а не удачной случайностью конкретного compose path.
|
||||
|
||||
Ожидаемый результат:
|
||||
|
||||
- ответы становятся устойчивее и предсказуемее даже при edge-cases.
|
||||
|
||||
### Phase 6. Зафиксировать runtime checkpoints и replay-safe state
|
||||
|
||||
Borrowed pattern:
|
||||
|
||||
- durable execution / replay / idempotent tasks из LangGraph
|
||||
|
||||
Цель:
|
||||
|
||||
- сблизить session/navigation state с моделью checkpointed execution.
|
||||
|
||||
Что обновить концептуально:
|
||||
|
||||
- каждый важный state transition должен иметь machine-readable checkpoint semantics;
|
||||
- follow-up interpretation должна опираться на сохраненные transition objects, а не только на текст прошлых сообщений;
|
||||
- сценарные прогоны должны проверять не только answer text, но и корректность state transitions.
|
||||
|
||||
Ожидаемый результат:
|
||||
|
||||
- меньше регрессий, где exact route есть, но follow-up interpretation ломает доступ к нему.
|
||||
|
||||
### Phase 7. Упорядочить provider and execution interfaces
|
||||
|
||||
Borrowed pattern:
|
||||
|
||||
- product shell abstraction из LibreChat / Open WebUI / Dify
|
||||
|
||||
Цель:
|
||||
|
||||
- постепенно превратить LLM gateway в более явный provider runtime layer.
|
||||
|
||||
Что обновить концептуально:
|
||||
|
||||
- развести:
|
||||
- orchestration logic;
|
||||
- provider execution;
|
||||
- model-specific JSON / response normalization;
|
||||
- local/openai compatibility concerns.
|
||||
|
||||
Ожидаемый результат:
|
||||
|
||||
- меньше provider-driven логики внутри business orchestration.
|
||||
|
||||
### Phase 8. Сценарная приемка как главный architectural gate
|
||||
|
||||
Borrowed pattern:
|
||||
|
||||
- LLMOps/observability from Dify
|
||||
- enterprise auditability from Onyx/Vanna
|
||||
|
||||
Цель:
|
||||
|
||||
- закрепить, что acceptance идет по scenario-tree, а не по отдельным красивым ответам.
|
||||
|
||||
Что обновить концептуально:
|
||||
|
||||
- любой architectural update считается успешным только если:
|
||||
- сохраняется root path;
|
||||
- сохраняются critical edges;
|
||||
- сохраняется selected-object continuity;
|
||||
- не деградирует limited truthfulness;
|
||||
- не ломаются neighboring domains.
|
||||
|
||||
Ожидаемый результат:
|
||||
|
||||
- меньше "качелей", где один кейс улучшается ценой трех соседних.
|
||||
|
||||
|
||||
## 17. Что не нужно делать
|
||||
|
||||
В рамках update plan не нужно:
|
||||
|
||||
1. Переписывать runtime под Dify/Open WebUI/LibreChat как платформенную миграцию.
|
||||
2. Вводить "универсальный суперклассификатор", который обходит текущие rails.
|
||||
3. Возвращать state обратно в transcript-only memory.
|
||||
4. Маскировать state/policy проблемы только answer wording правками.
|
||||
5. Смешивать Python `router/` и текущий TS assistant runtime без явного redesign note.
|
||||
6. Жертвовать exact-data discipline ради более "естественного" чата.
|
||||
|
||||
|
||||
## 18. Целевая формула обновленного проекта
|
||||
|
||||
Если выражать желаемое состояние кратко, то проект должен двигаться к следующей форме:
|
||||
|
||||
### 18.1 Слой проекта
|
||||
|
||||
`1C/OData -> canonical store -> feature/risk data services -> assistant orchestration shell -> exact capabilities -> answer/debug contracts -> scenario acceptance loop`
|
||||
|
||||
### 18.2 Архитектурная форма assistant runtime
|
||||
|
||||
`thin router + explicit state transitions + declarative capability contracts + isolated answer policy + exact execution lane`
|
||||
|
||||
### 18.3 Главный принцип
|
||||
|
||||
`не делать систему "умнее любой ценой"`
|
||||
|
||||
а
|
||||
|
||||
`делать систему более явной, более контрактной и менее хрупкой`.
|
||||
|
||||
|
||||
## 19. Итог
|
||||
|
||||
На `2026-04-15` проект `NDC_1C` уже нельзя честно описывать как "обычный чат с LLM и другой базой".
|
||||
|
||||
Правильнее описывать его так:
|
||||
|
||||
- это read-only AI/data system поверх 1C;
|
||||
- у нее есть canonical/data foundation;
|
||||
- есть feature/risk layer;
|
||||
- есть specialized exact-data assistant runtime;
|
||||
- есть scenario-based hardening loop;
|
||||
- и есть существенный orchestration debt, возникший из-за ручной эволюции.
|
||||
|
||||
Поэтому правильный next move:
|
||||
|
||||
`не ломать то, что уже собрано`
|
||||
|
||||
и
|
||||
|
||||
`не пытаться заменить систему generic framework-ом`
|
||||
|
||||
а
|
||||
|
||||
`собрать более явную architecture grammar поверх уже существующих рабочих слоев`.
|
||||
|
||||
Это и есть safest update path по итогам локального анализа и внешних references.
|
||||
Reference in New Issue
Block a user