U1-R2B Research Design UI + Manual Override

#127
Files changed (3) hide show
  1. app.py +48 -29
  2. core/advanced_method_registry.py +35 -53
  3. i18n.py +58 -54
app.py CHANGED
@@ -306,6 +306,8 @@ for key, default in {
306
  "sp_completed_download_scroll_task_id": "",
307
  "sp_method_confirmation": "",
308
  "sp_method_confirmation_signature": "",
 
 
309
  "sp_material_document_use": "reference",
310
  }.items():
311
  if key not in st.session_state:
@@ -506,7 +508,6 @@ def _method_intent_signature() -> str:
506
  payload = {
507
  "topic": str(st.session_state.get("sp_topic") or DEFAULT_TOPIC),
508
  "keywords": str(st.session_state.get("sp_keywords") or DEFAULT_KEYWORDS),
509
- "materials": _uploaded_material_descriptors(),
510
  }
511
  return hashlib.sha256(
512
  json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8")
@@ -776,8 +777,9 @@ def _process_pending_launch(lang_code: str) -> None:
776
  idempotency_key = str(pending.get("idempotency_key") or "").strip()
777
  pending_signature = str(pending.get("method_intent_signature") or "").strip()
778
 
779
- # U1-R2 repeats the capability preflight immediately before any task/quota
780
- # creation so a stale rerun or modified session state cannot bypass it.
 
781
  preflight, current_signature = _current_method_preflight(
782
  confirmed_method_family=pending_family or None
783
  )
@@ -797,7 +799,7 @@ def _process_pending_launch(lang_code: str) -> None:
797
  method_label = tr(lang_code, f"method_{resolved_family}")
798
  st.warning(tr(lang_code, "method_not_supported", method=method_label))
799
  else:
800
- st.warning(tr(lang_code, "method_confirmation_required"))
801
  return
802
 
803
  projection = get_product_ui_projection()
@@ -1504,30 +1506,48 @@ def render_workspace_controls(user):
1504
  }
1505
  method_signature = ""
1506
  else:
1507
- preflight, method_signature = _current_method_preflight()
1508
- if str(preflight.get("block_reason") or "") == "method_confirmation_required":
1509
- stored = str(st.session_state.get("sp_method_confirmation") or "").strip().casefold()
1510
- stored_sig = str(st.session_state.get("sp_method_confirmation_signature") or "").strip()
1511
- selected_default = stored if stored_sig == method_signature and stored in METHOD_FAMILIES else ""
1512
- options = [""] + list(METHOD_FAMILIES)
1513
- selected = st.selectbox(
1514
- tr(lang_code, "method_confirm_label"),
1515
- options,
1516
- index=options.index(selected_default) if selected_default in options else 0,
1517
- format_func=lambda family: (
1518
- tr(lang_code, "method_confirm_placeholder")
1519
- if not family else tr(lang_code, f"method_{family}")
1520
- ),
1521
- )
1522
- if selected:
1523
- st.session_state["sp_method_confirmation"] = selected
1524
- st.session_state["sp_method_confirmation_signature"] = method_signature
1525
- preflight, method_signature = _current_method_preflight(confirmed_method_family=selected)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1526
  else:
1527
- # Explicit Title/Keyword cues are authoritative; stale confirmations
1528
- # from a previous ambiguous intent cannot override them.
1529
  st.session_state["sp_method_confirmation"] = ""
1530
  st.session_state["sp_method_confirmation_signature"] = ""
 
1531
 
1532
  method_family = str(preflight.get("method_family") or "undetermined").strip().casefold()
1533
  method_label = (
@@ -1535,14 +1555,13 @@ def render_workspace_controls(user):
1535
  if method_family in METHOD_FAMILIES
1536
  else tr(lang_code, "method_undetermined")
1537
  )
1538
- st.markdown(f"**{tr(lang_code, 'detected_method_label')}:** {method_label}")
 
1539
  st.caption(tr(lang_code, "method_detection_explanation"))
1540
 
1541
  block_reason = str(preflight.get("block_reason") or "")
1542
  if block_reason == "method_capability_blocked":
1543
  st.warning(tr(lang_code, "method_not_supported", method=method_label))
1544
- elif block_reason == "method_confirmation_required":
1545
- st.warning(tr(lang_code, "method_confirmation_required"))
1546
  elif not active:
1547
  st.info(tr(lang_code, "method_supported", method=method_label))
1548
 
@@ -1639,7 +1658,7 @@ def render_workspace_controls(user):
1639
  if reason == "method_capability_blocked":
1640
  st.warning(tr(lang_code, "method_not_supported", method=method_label))
1641
  else:
1642
- st.warning(tr(lang_code, "method_confirmation_required"))
1643
  else:
1644
  resolved_family = str(click_preflight.get("method_family") or "").strip().casefold()
1645
  resolved_mode = str(click_preflight.get("legacy_policy_lane") or "").strip().lower()
 
306
  "sp_completed_download_scroll_task_id": "",
307
  "sp_method_confirmation": "",
308
  "sp_method_confirmation_signature": "",
309
+ "sp_method_selector": "qualitative",
310
+ "sp_method_selector_signature": "",
311
  "sp_material_document_use": "reference",
312
  }.items():
313
  if key not in st.session_state:
 
508
  payload = {
509
  "topic": str(st.session_state.get("sp_topic") or DEFAULT_TOPIC),
510
  "keywords": str(st.session_state.get("sp_keywords") or DEFAULT_KEYWORDS),
 
511
  }
512
  return hashlib.sha256(
513
  json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8")
 
777
  idempotency_key = str(pending.get("idempotency_key") or "").strip()
778
  pending_signature = str(pending.get("method_intent_signature") or "").strip()
779
 
780
+ # U1-R2B repeats the capability preflight immediately before any task/quota
781
+ # creation so a stale rerun or modified session state cannot bypass a
782
+ # manually adjusted or auto/default research design.
783
  preflight, current_signature = _current_method_preflight(
784
  confirmed_method_family=pending_family or None
785
  )
 
799
  method_label = tr(lang_code, f"method_{resolved_family}")
800
  st.warning(tr(lang_code, "method_not_supported", method=method_label))
801
  else:
802
+ st.warning(tr(lang_code, "method_resolution_invalid"))
803
  return
804
 
805
  projection = get_product_ui_projection()
 
1506
  }
1507
  method_signature = ""
1508
  else:
1509
+ # U1-R2B: Title + Keywords determine the automatic design. If no design
1510
+ # cue is present, the resolver defaults to qualitative. The selector is
1511
+ # always visible for a new task and may override the automatic/default
1512
+ # choice, but the capability gate still runs afterwards.
1513
+ auto_preflight, method_signature = _current_method_preflight(confirmed_method_family="")
1514
+ auto_family = str(auto_preflight.get("method_family") or "qualitative").strip().casefold()
1515
+ if auto_family not in METHOD_FAMILIES:
1516
+ auto_family = "qualitative"
1517
+
1518
+ stored = str(st.session_state.get("sp_method_confirmation") or "").strip().casefold()
1519
+ stored_sig = str(st.session_state.get("sp_method_confirmation_signature") or "").strip()
1520
+ selected_default = stored if stored_sig == method_signature and stored in METHOD_FAMILIES else auto_family
1521
+
1522
+ # A changed Title/Keywords signature invalidates a previous manual
1523
+ # override and resets the visible selector to the fresh auto/default
1524
+ # result. This prevents stale method choices leaking across topics.
1525
+ selector_sig = str(st.session_state.get("sp_method_selector_signature") or "").strip()
1526
+ if selector_sig != method_signature:
1527
+ st.session_state["sp_method_confirmation"] = ""
1528
+ st.session_state["sp_method_confirmation_signature"] = ""
1529
+ st.session_state["sp_method_selector"] = auto_family
1530
+ st.session_state["sp_method_selector_signature"] = method_signature
1531
+ selected_default = auto_family
1532
+ elif str(st.session_state.get("sp_method_selector") or "").strip().casefold() not in METHOD_FAMILIES:
1533
+ st.session_state["sp_method_selector"] = selected_default
1534
+
1535
+ selected = st.selectbox(
1536
+ tr(lang_code, "detected_method_label"),
1537
+ list(METHOD_FAMILIES),
1538
+ index=list(METHOD_FAMILIES).index(selected_default),
1539
+ format_func=lambda family: tr(lang_code, f"method_{family}"),
1540
+ key="sp_method_selector",
1541
+ disabled=active,
1542
+ )
1543
+ selected = str(selected or auto_family).strip().casefold()
1544
+ if selected != auto_family:
1545
+ st.session_state["sp_method_confirmation"] = selected
1546
+ st.session_state["sp_method_confirmation_signature"] = method_signature
1547
  else:
 
 
1548
  st.session_state["sp_method_confirmation"] = ""
1549
  st.session_state["sp_method_confirmation_signature"] = ""
1550
+ preflight, method_signature = _current_method_preflight(confirmed_method_family=selected)
1551
 
1552
  method_family = str(preflight.get("method_family") or "undetermined").strip().casefold()
1553
  method_label = (
 
1555
  if method_family in METHOD_FAMILIES
1556
  else tr(lang_code, "method_undetermined")
1557
  )
1558
+ if active:
1559
+ st.markdown(f"**{tr(lang_code, 'detected_method_label')}:** {method_label}")
1560
  st.caption(tr(lang_code, "method_detection_explanation"))
1561
 
1562
  block_reason = str(preflight.get("block_reason") or "")
1563
  if block_reason == "method_capability_blocked":
1564
  st.warning(tr(lang_code, "method_not_supported", method=method_label))
 
 
1565
  elif not active:
1566
  st.info(tr(lang_code, "method_supported", method=method_label))
1567
 
 
1658
  if reason == "method_capability_blocked":
1659
  st.warning(tr(lang_code, "method_not_supported", method=method_label))
1660
  else:
1661
+ st.warning(tr(lang_code, "method_resolution_invalid"))
1662
  else:
1663
  resolved_family = str(click_preflight.get("method_family") or "").strip().casefold()
1664
  resolved_mode = str(click_preflight.get("legacy_policy_lane") or "").strip().lower()
core/advanced_method_registry.py CHANGED
@@ -1,10 +1,13 @@
1
  # -*- coding: utf-8 -*-
2
- """Deterministic method-family resolver and capability preflight for SmartPaper.
3
 
4
- U1-R2 derives an academic ``method_family`` from frozen user intent
5
- (Title/Keywords plus light material metadata), maps that family to the legacy
6
- AMJ/ASQ policy lane, and blocks unsupported method families before task/quota
7
- creation. It never selects providers/models and never rewrites Title/Keywords.
 
 
 
8
  """
9
  from __future__ import annotations
10
 
@@ -12,7 +15,7 @@ import os
12
  import re
13
  from typing import Any, Iterable
14
 
15
- METHOD_RESOLVER_VERSION = "smartpaper-auto-method-resolver-v2"
16
  METHOD_CAPABILITY_REGISTRY_VERSION = "smartpaper-method-capability-registry-v2"
17
 
18
  METHOD_FAMILIES = (
@@ -197,11 +200,12 @@ def resolve_method_family(
197
  *,
198
  materials: Iterable[Any] | None = None,
199
  ) -> dict[str, Any]:
200
- """Resolve an academic method family from frozen user intent.
201
 
202
- Explicit Title/Keyword cues are authoritative. Material *metadata* can add
203
- support, but never overrides an explicit method cue. File contents are
204
- deliberately not read here.
 
205
  """
206
  source_title = _normalized_text(title)
207
  source_keywords = _keyword_items(keywords)
@@ -217,41 +221,28 @@ def resolve_method_family(
217
  chosen = family
218
 
219
  descriptors = _material_descriptors(materials)
220
- material_hits: list[str] = []
221
- for descriptor in descriptors:
222
- name = descriptor.get("name") or ""
223
- for family, patterns in _MATERIAL_NAME_PATTERNS:
224
- if any(re.search(pattern, name, flags=re.I | re.UNICODE) for pattern in patterns):
225
- if family not in material_hits:
226
- material_hits.append(family)
227
 
228
- # Explicit academic wording outranks material filename hints. When there is
229
- # no explicit cue, one unique material hint is useful but remains ambiguous
230
- # until future U1 benchmarks justify auto-acceptance.
231
- confidence = "HIGH_CONFIDENCE" if chosen else "AMBIGUOUS"
232
  reason_codes: list[str] = []
233
  if chosen:
234
  reason_codes.append("explicit_title_keyword_method_cue")
235
  conflicting = [row["method_family"] for row in hits if row["method_family"] != chosen]
236
  if conflicting:
237
  reason_codes.append("lower_priority_method_cues_present")
238
- elif len(material_hits) == 1:
239
- chosen = material_hits[0]
240
- reason_codes.append("material_filename_method_hint_only")
241
- elif len(material_hits) > 1:
242
- reason_codes.append("conflicting_material_method_hints")
243
  else:
 
244
  reason_codes.append("no_explicit_method_cue")
 
245
 
246
  capability = method_capability(chosen)
247
  return {
248
  "resolver_version": METHOD_RESOLVER_VERSION,
249
  "shadow_only": False,
250
- "method_family": chosen or "undetermined",
251
  "confidence": confidence,
252
  "reason_codes": reason_codes,
253
  "title_keyword_hits": hits,
254
- "material_hint_families": material_hits,
255
  "material_count": len(descriptors),
256
  "derived_policy_lane": capability.get("legacy_policy_lane"),
257
  "capability": capability,
@@ -279,35 +270,26 @@ def resolve_generation_preflight(
279
  ) -> dict[str, Any]:
280
  """Resolve method + capability before any task/quota creation.
281
 
282
- A user confirmation is accepted only when deterministic resolution is
283
- genuinely ambiguous. Explicit Title/Keyword cues always remain authoritative.
 
 
284
  """
285
  resolution = resolve_method_family(title, keywords, materials=materials)
286
  family = str(resolution.get("method_family") or "").strip().casefold()
287
- confidence = str(resolution.get("confidence") or "").strip().upper()
288
 
289
  confirmed = str(confirmed_method_family or "").strip().casefold()
290
- if confidence == "AMBIGUOUS":
291
- if confirmed in METHOD_FAMILIES:
292
- family = confirmed
293
- capability = method_capability(family)
294
- resolution = dict(resolution)
295
- resolution.update({
296
- "method_family": family,
297
- "confidence": "USER_CONFIRMED",
298
- "derived_policy_lane": capability.get("legacy_policy_lane"),
299
- "capability": capability,
300
- "reason_codes": list(resolution.get("reason_codes") or []) + ["user_confirmed_method_family"],
301
- })
302
- else:
303
- return {
304
- "can_start_generation": False,
305
- "block_reason": "method_confirmation_required",
306
- "resolution": resolution,
307
- "method_family": family or "undetermined",
308
- "legacy_policy_lane": None,
309
- "capability": method_capability(family),
310
- }
311
 
312
  capability = method_capability(family)
313
  lane = str(capability.get("legacy_policy_lane") or "").strip().casefold() or None
@@ -315,7 +297,7 @@ def resolve_generation_preflight(
315
  if family not in METHOD_FAMILIES or not lane:
316
  return {
317
  "can_start_generation": False,
318
- "block_reason": "method_confirmation_required",
319
  "resolution": resolution,
320
  "method_family": family or "undetermined",
321
  "legacy_policy_lane": None,
 
1
  # -*- coding: utf-8 -*-
2
+ """Deterministic research-design resolver and capability preflight for SmartPaper.
3
 
4
+ U1-R2B derives an academic ``method_family`` from Title + Keywords only, maps
5
+ that family to the legacy AMJ/ASQ policy lane, and blocks unsupported method
6
+ families before task/quota creation. When no design cue is detected, the
7
+ resolver defaults to qualitative research. A user's manual design adjustment
8
+ is authoritative for the current Title + Keywords signature, but it never
9
+ bypasses the capability gate. This module never selects providers/models and
10
+ never rewrites Title/Keywords.
11
  """
12
  from __future__ import annotations
13
 
 
15
  import re
16
  from typing import Any, Iterable
17
 
18
+ METHOD_RESOLVER_VERSION = "smartpaper-auto-method-resolver-v3"
19
  METHOD_CAPABILITY_REGISTRY_VERSION = "smartpaper-method-capability-registry-v2"
20
 
21
  METHOD_FAMILIES = (
 
200
  *,
201
  materials: Iterable[Any] | None = None,
202
  ) -> dict[str, Any]:
203
+ """Resolve one academic research-design family from Title + Keywords.
204
 
205
+ ``materials`` remains in the public signature for backward compatibility,
206
+ but U1-R2B deliberately does not use uploaded material names or contents to
207
+ infer the design. If no explicit design cue is found, qualitative research
208
+ is selected as the non-blocking default.
209
  """
210
  source_title = _normalized_text(title)
211
  source_keywords = _keyword_items(keywords)
 
221
  chosen = family
222
 
223
  descriptors = _material_descriptors(materials)
 
 
 
 
 
 
 
224
 
225
+ confidence = "AUTO_DETECTED" if chosen else "DEFAULT_QUALITATIVE"
 
 
 
226
  reason_codes: list[str] = []
227
  if chosen:
228
  reason_codes.append("explicit_title_keyword_method_cue")
229
  conflicting = [row["method_family"] for row in hits if row["method_family"] != chosen]
230
  if conflicting:
231
  reason_codes.append("lower_priority_method_cues_present")
 
 
 
 
 
232
  else:
233
+ chosen = "qualitative"
234
  reason_codes.append("no_explicit_method_cue")
235
+ reason_codes.append("default_qualitative")
236
 
237
  capability = method_capability(chosen)
238
  return {
239
  "resolver_version": METHOD_RESOLVER_VERSION,
240
  "shadow_only": False,
241
+ "method_family": chosen,
242
  "confidence": confidence,
243
  "reason_codes": reason_codes,
244
  "title_keyword_hits": hits,
245
+ "material_hint_families": [],
246
  "material_count": len(descriptors),
247
  "derived_policy_lane": capability.get("legacy_policy_lane"),
248
  "capability": capability,
 
270
  ) -> dict[str, Any]:
271
  """Resolve method + capability before any task/quota creation.
272
 
273
+ A valid manual selection may override either an auto-detected design or the
274
+ qualitative fallback. Capability validation always runs after the manual
275
+ selection, so an unsupported advanced method still cannot create a task or
276
+ reserve quota.
277
  """
278
  resolution = resolve_method_family(title, keywords, materials=materials)
279
  family = str(resolution.get("method_family") or "").strip().casefold()
 
280
 
281
  confirmed = str(confirmed_method_family or "").strip().casefold()
282
+ if confirmed in METHOD_FAMILIES and confirmed != family:
283
+ family = confirmed
284
+ capability = method_capability(family)
285
+ resolution = dict(resolution)
286
+ resolution.update({
287
+ "method_family": family,
288
+ "confidence": "USER_OVERRIDE",
289
+ "derived_policy_lane": capability.get("legacy_policy_lane"),
290
+ "capability": capability,
291
+ "reason_codes": list(resolution.get("reason_codes") or []) + ["user_override_method_family"],
292
+ })
 
 
 
 
 
 
 
 
 
 
293
 
294
  capability = method_capability(family)
295
  lane = str(capability.get("legacy_policy_lane") or "").strip().casefold() or None
 
297
  if family not in METHOD_FAMILIES or not lane:
298
  return {
299
  "can_start_generation": False,
300
+ "block_reason": "method_resolution_invalid",
301
  "resolution": resolution,
302
  "method_family": family or "undetermined",
303
  "legacy_policy_lane": None,
i18n.py CHANGED
@@ -276,25 +276,26 @@ TEXTS: dict[str, dict[str, str]] = {
276
  "download_asq_template": "📥 一键下载 TXT 访谈模板",
277
  "start_asq": "🚀 启动 ASQ 模式生成",
278
  "research_materials_label": "研究资料(可选)",
279
- "research_materials_help": "支持 PDF、TXT、DOC、DOCX、CSV、XLS、XLSX。SmartPaper 会结合论文题目、关键词与文件特征判断研究设计和资料用途。",
280
  "drop_research_materials": "将研究资料拖到这里",
281
  "limit_research_materials": "每个文件最大 1 GB · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
282
  "material_document_use_label": "如何使用上传的 PDF/DOC/DOCX 文件?",
283
  "material_use_reference": "作为参考文献资料",
284
  "material_use_research": "作为研究资料",
285
- "detected_method_label": "研究设计(自动识别)",
286
- "method_detection_explanation": "SmartPaper 根据论文题目、关键词和可选研究资料自动识别研究方法;不会修改你的题目或关键词。",
287
- "method_confirm_label": "请确认研究设计",
288
- "method_confirm_placeholder": "请选择研究方法",
289
- "method_confirmation_required": "当前信息不足以可靠识别研究设计,请先确认研究方法。",
290
- "method_not_supported": "已识别为“{method}”。该研究方法的专用生成引擎尚未开放;本次不会创建任务,也不会占用额度。",
291
- "method_supported": "已识别为“{method}”。系统将按对应研究流程生成论文。",
292
- "method_undetermined": "尚未确定",
293
- "method_survey_path": "问卷与路径关系研究",
294
- "method_qualitative": "定性研究",
295
- "method_fsqca": "fsQCA 组态研究",
 
296
  "method_meta_analysis": "元分析",
297
- "method_panel_econometrics": "面板计量研究",
298
  "method_bibliometric_integrative_review": "文献计量与整合性综述",
299
  "adaptive_template_expander": "💡 推荐模板(可选)",
300
  "download_research_template": "📥 下载研究资料模板",
@@ -517,26 +518,27 @@ TEXTS: dict[str, dict[str, str]] = {
517
  "download_asq_template": "📥 Download TXT Interview Template",
518
  "start_asq": "🚀 Start ASQ Generation",
519
  "research_materials_label": "Research Materials (Optional)",
520
- "research_materials_help": "Supports PDF, TXT, DOC, DOCX, CSV, XLS, and XLSX. SmartPaper uses the Title, Keywords, and file characteristics to infer the research design and material role.",
521
  "drop_research_materials": "Drag research materials here",
522
  "limit_research_materials": "Up to 1 GB per file · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
523
  "material_document_use_label": "How should SmartPaper use the uploaded PDF/DOC/DOCX files?",
524
  "material_use_reference": "Use as reference literature",
525
  "material_use_research": "Use as research materials",
526
- "detected_method_label": "Research Design (Auto-detected)",
527
- "method_detection_explanation": "SmartPaper infers the research method from the Title, Keywords, and optional materials without rewriting your Title or Keywords.",
528
- "method_confirm_label": "Confirm Research Design",
529
- "method_confirm_placeholder": "Select a research method",
530
- "method_confirmation_required": "The current information is insufficient for reliable method detection. Please confirm the research design first.",
531
- "method_not_supported": "Detected method: {method}. Its dedicated generation engine is not yet enabled, so no task will be created and no quota will be used.",
532
- "method_supported": "Detected method: {method}. SmartPaper will use the corresponding research workflow.",
533
- "method_undetermined": "Not yet determined",
534
- "method_survey_path": "Survey and Path-Relationship Study",
535
- "method_qualitative": "Qualitative Study",
536
- "method_fsqca": "fsQCA Configurational Study",
 
537
  "method_meta_analysis": "Meta-Analysis",
538
- "method_panel_econometrics": "Panel Econometric Study",
539
- "method_bibliometric_integrative_review": "Bibliometric and Integrative Review",
540
  "adaptive_template_expander": "💡 Recommended Template (Optional)",
541
  "download_research_template": "📥 Download Research Materials Template",
542
  "template_help_survey_path": "A variable-level or statistical-results table is recommended. If no data are uploaded, SmartPaper may construct draft evidence under the project provenance rules.",
@@ -758,26 +760,27 @@ TEXTS: dict[str, dict[str, str]] = {
758
  "download_asq_template": "📥 Скачать TXT-шаблон интервью",
759
  "start_asq": "🚀 Запустить формирование в режиме ASQ",
760
  "research_materials_label": "Материалы исследования (необязательно)",
761
- "research_materials_help": "Поддерживаются PDF, TXT, DOC, DOCX, CSV, XLS и XLSX. SmartPaper определяет дизайн исследования и назначение материалов по названию статьи, ключевым словам и характеристикам файлов.",
762
  "drop_research_materials": "Перетащите исследовательские материалы сюда",
763
  "limit_research_materials": "До 1 ГБ на файл · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
764
  "material_document_use_label": "Как использовать загруженные файлы PDF/DOC/DOCX?",
765
  "material_use_reference": "Как научные источники",
766
  "material_use_research": "Как исследовательские материалы",
767
- "detected_method_label": "Дизайн исследования (определяется автоматически)",
768
- "method_detection_explanation": "SmartPaper определяет метод по названию статьи, ключевым словам и необязательным материалам, не изменяя название и ключевые слова.",
769
- "method_confirm_label": "Подтвердите дизайн исследования",
770
- "method_confirm_placeholder": "Выберите метод исследования",
771
- "method_confirmation_required": "Имеющейся информации недостаточно для надёжного определения метода. Сначала подтвердите дизайн исследования.",
772
- "method_not_supported": "Определён метод «{method}». Специализированный движок этого метода пока не включён, поэтому задача не будет создана и кв��та не будет списана.",
773
- "method_supported": "Определён метод «{method}». SmartPaper применит соответствующий исследовательский процесс.",
774
- "method_undetermined": "Пока не определён",
775
- "method_survey_path": "Опросное исследование и анализ связей",
 
776
  "method_qualitative": "Качественное исследование",
777
- "method_fsqca": "Конфигурационное исследование fsQCA",
778
- "method_meta_analysis": "Мета-анализ",
779
- "method_panel_econometrics": "Панельное эконометрическое исследование",
780
- "method_bibliometric_integrative_review": "Библиометрический и интегративный обзор",
781
  "adaptive_template_expander": "💡 Рекомендуемый шаблон (необязательно)",
782
  "download_research_template": "📥 Скачать шаблон исследовательских материалов",
783
  "template_help_survey_path": "Рекомендуется таблица переменных или статистических результатов. При отсутствии данных SmartPaper может сформировать черновые доказательные материалы в рамках правил происхождения данных.",
@@ -999,26 +1002,27 @@ TEXTS: dict[str, dict[str, str]] = {
999
  "download_asq_template": "📥 TXT сұхбат үлгісін жүктеу",
1000
  "start_asq": "🚀 ASQ режимінде дайындауды бастау",
1001
  "research_materials_label": "Зерттеу материалдары (міндетті емес)",
1002
- "research_materials_help": "PDF, TXT, DOC, DOCX, CSV, XLS және XLSX форматтары қолдау табады. SmartPaper мақала атауы, түйін сөздер және файл сипаттары негізінде зерттеу дизайны мен материалдардың қызметін анықтайды.",
1003
  "drop_research_materials": "Зерттеу материалдарын ос�� жерге сүйреп әкеліңіз",
1004
  "limit_research_materials": "Әр файлға 1 ГБ дейін · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
1005
  "material_document_use_label": "Жүктелген PDF/DOC/DOCX файлдарын қалай пайдалану керек?",
1006
  "material_use_reference": "Ғылыми дереккөз ретінде",
1007
  "material_use_research": "Зерттеу материалы ретінде",
1008
- "detected_method_label": "Зерттеу дизайны (автоматты түрде анықталады)",
1009
- "method_detection_explanation": "SmartPaper зерттеу әдісін мақала атауы, түйін сөздер және қосымша материалдар негізінде анықтайды; мақала атауы мен түйін сөздерді өзгертпейді.",
1010
- "method_confirm_label": "Зерттеу дизайнын растаңыз",
1011
- "method_confirm_placeholder": "Зерттеу әдісін таңдаңыз",
1012
- "method_confirmation_required": "Қазіргі ақпарат зерттеу әдісін сенімді анықтауға жеткіліксіз. Алдымен зерттеу дизайнын растаңыз.",
1013
- "method_not_supported": "«{method}» әдісі анықталды. Бұл әдістің арнайы генерация қозғалтқышы әлі қосылмаған, сондықтан тапсырма құрылмайды және квота пайдаланылмайды.",
1014
- "method_supported": "«{method}» әдісі анықталды. SmartPaper тиісті зерттеу үдерісін қолданады.",
1015
- "method_undetermined": "Әзірге анықталмаған",
1016
- "method_survey_path": "Сауалнама және байланыстарды талдау зерттеуі",
 
1017
  "method_qualitative": "Сапалық зерттеу",
1018
- "method_fsqca": "fsQCA конфигурациялық зерттеуі",
1019
  "method_meta_analysis": "Мета-талдау",
1020
- "method_panel_econometrics": "Панельдік эконометрикалық зерттеу",
1021
- "method_bibliometric_integrative_review": "Библиометриялық және интегративті шолу",
1022
  "adaptive_template_expander": "💡 Ұсынылатын үлгі (міндетті емес)",
1023
  "download_research_template": "📥 Зерттеу материалдары үлгісін жүктеу",
1024
  "template_help_survey_path": "Айнымалылар немесе статистикалық нәтижелер кестесі ұсынылады. Дерек жүктелмесе, SmartPaper жоба ережелеріне сәйкес бастапқы нұсқаға арналған көмекші дәлелдерді құра алады.",
 
276
  "download_asq_template": "📥 一键下载 TXT 访谈模板",
277
  "start_asq": "🚀 启动 ASQ 模式生成",
278
  "research_materials_label": "研究资料(可选)",
279
+ "research_materials_help": "支持 PDF、TXT、DOC、DOCX、CSV、XLS、XLSX。上传资料用于辅助论文生成;研究设计仅根据论文题目和关键词自动识别。",
280
  "drop_research_materials": "将研究资料拖到这里",
281
  "limit_research_materials": "每个文件最大 1 GB · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
282
  "material_document_use_label": "如何使用上传的 PDF/DOC/DOCX 文件?",
283
  "material_use_reference": "作为参考文献资料",
284
  "material_use_research": "作为研究资料",
285
+ "detected_method_label": "研究设计(自动识别,可调整)",
286
+ "method_detection_explanation": "基于论文题目和关键词自动识别研究设计。未识别时默认质性研究,可手动调整。",
287
+ "method_confirm_label": "调整研究设计",
288
+ "method_confirm_placeholder": "请选择研究设计",
289
+ "method_confirmation_required": "研究设计状态异常,请重新选择研究设计。",
290
+ "method_resolution_invalid": "研究设计状态异常,请重新选择研究设计。",
291
+ "method_not_supported": "当前研究设计为“{method}”。该研究设计的专用生成引擎尚未开放;本次不会创建任务,也不会占用额度。",
292
+ "method_supported": "当前研究设计为“{method}”。系统将按对应研究流程生成论文。",
293
+ "method_undetermined": "质性研究(默认)",
294
+ "method_survey_path": "问卷量化研究",
295
+ "method_qualitative": "质性研究",
296
+ "method_fsqca": "模糊集定性比较分析(fsQCA)",
297
  "method_meta_analysis": "元分析",
298
+ "method_panel_econometrics": "面板数据计量分析",
299
  "method_bibliometric_integrative_review": "文献计量与整合性综述",
300
  "adaptive_template_expander": "💡 推荐模板(可选)",
301
  "download_research_template": "📥 下载研究资料模板",
 
518
  "download_asq_template": "📥 Download TXT Interview Template",
519
  "start_asq": "🚀 Start ASQ Generation",
520
  "research_materials_label": "Research Materials (Optional)",
521
+ "research_materials_help": "Supports PDF, TXT, DOC, DOCX, CSV, XLS, and XLSX. Uploaded files support paper generation; Research Design is identified from the Title and Keywords only.",
522
  "drop_research_materials": "Drag research materials here",
523
  "limit_research_materials": "Up to 1 GB per file · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
524
  "material_document_use_label": "How should SmartPaper use the uploaded PDF/DOC/DOCX files?",
525
  "material_use_reference": "Use as reference literature",
526
  "material_use_research": "Use as research materials",
527
+ "detected_method_label": "Research Design (Auto-detected, Adjustable)",
528
+ "method_detection_explanation": "Automatically identifies the Research Design from the Title and Keywords. If none is identified, Qualitative Research is used by default. You can adjust it manually.",
529
+ "method_confirm_label": "Adjust Research Design",
530
+ "method_confirm_placeholder": "Select a Research Design",
531
+ "method_confirmation_required": "The Research Design state is invalid. Please select a Research Design again.",
532
+ "method_resolution_invalid": "The Research Design state is invalid. Please select a Research Design again.",
533
+ "method_not_supported": "Current Research Design: {method}. Its dedicated generation engine is not yet enabled, so no task will be created and no quota will be used.",
534
+ "method_supported": "Current Research Design: {method}. SmartPaper will use the corresponding research workflow.",
535
+ "method_undetermined": "Qualitative Research (Default)",
536
+ "method_survey_path": "Survey-Based Quantitative Research",
537
+ "method_qualitative": "Qualitative Research",
538
+ "method_fsqca": "Fuzzy-Set Qualitative Comparative Analysis (fsQCA)",
539
  "method_meta_analysis": "Meta-Analysis",
540
+ "method_panel_econometrics": "Panel Data Econometric Analysis",
541
+ "method_bibliometric_integrative_review": "Bibliometric Analysis and Integrative Literature Review",
542
  "adaptive_template_expander": "💡 Recommended Template (Optional)",
543
  "download_research_template": "📥 Download Research Materials Template",
544
  "template_help_survey_path": "A variable-level or statistical-results table is recommended. If no data are uploaded, SmartPaper may construct draft evidence under the project provenance rules.",
 
760
  "download_asq_template": "📥 Скачать TXT-шаблон интервью",
761
  "start_asq": "🚀 Запустить формирование в режиме ASQ",
762
  "research_materials_label": "Материалы исследования (необязательно)",
763
+ "research_materials_help": "Поддерживаются PDF, TXT, DOC, DOCX, CSV, XLS и XLSX. Загруженные файлы используются как дополнительные исследовательские или справочные материалы; дизайн исследования определяется по названию статьи и ключевым словам.",
764
  "drop_research_materials": "Перетащите исследовательские материалы сюда",
765
  "limit_research_materials": "До 1 ГБ на файл · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
766
  "material_document_use_label": "Как использовать загруженные файлы PDF/DOC/DOCX?",
767
  "material_use_reference": "Как научные источники",
768
  "material_use_research": "Как исследовательские материалы",
769
+ "detected_method_label": "Дизайн исследования (определяется автоматически, можно изменить)",
770
+ "method_detection_explanation": "Дизайн исследования определяется автоматически по названию статьи и ключевым словам. Если определить его не удаётся, по умолчанию выбирается качественное исследование. Выбор можно изменить вручную.",
771
+ "method_confirm_label": "Изменить дизайн исследования",
772
+ "method_confirm_placeholder": "Выберите дизайн исследования",
773
+ "method_confirmation_required": "Некорректное состояние дизайна исследования. Выберите дизайн исследования повторно.",
774
+ "method_resolution_invalid": "Некорректное состояние дизайна исследования. Выберите дизайн исследования повторно.",
775
+ "method_not_supported": "Текущий дизайн исследования: «{method}». Специализированный движок для этого дизайна пока не включён, поэтому задача не будет создана и квота не будет списана.",
776
+ "method_supported": "Текущий дизайн исследования: «{method}». SmartPaper применит соответствующий исследовательский процесс.",
777
+ "method_undetermined": "Качественное исследование (по умолчанию)",
778
+ "method_survey_path": "Количественное исследование на основе опроса",
779
  "method_qualitative": "Качественное исследование",
780
+ "method_fsqca": "Качественный сравнительный анализ на основе нечётких множеств (fsQCA)",
781
+ "method_meta_analysis": "Метаанализ",
782
+ "method_panel_econometrics": "Эконометрический анализ панельных данных",
783
+ "method_bibliometric_integrative_review": "Библиометрический анализ и интегративный обзор литературы",
784
  "adaptive_template_expander": "💡 Рекомендуемый шаблон (необязательно)",
785
  "download_research_template": "📥 Скачать шаблон исследовательских материалов",
786
  "template_help_survey_path": "Рекомендуется таблица переменных или статистических результатов. При отсутствии данных SmartPaper может сформировать черновые доказательные материалы в рамках правил происхождения данных.",
 
1002
  "download_asq_template": "📥 TXT сұхбат үлгісін жүктеу",
1003
  "start_asq": "🚀 ASQ режимінде дайындауды бастау",
1004
  "research_materials_label": "Зерттеу материалдары (міндетті емес)",
1005
+ "research_materials_help": "PDF, TXT, DOC, DOCX, CSV, XLS және XLSX форматтары қолдау табады. Жүктелген файлдар қосымша зерттеу немесе анықтамалық материал ретінде пайдаланылады; зерттеу дизайны мақала тақырыбы мен кілт сөздер бойынша анықталады.",
1006
  "drop_research_materials": "Зерттеу материалдарын ос�� жерге сүйреп әкеліңіз",
1007
  "limit_research_materials": "Әр файлға 1 ГБ дейін · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
1008
  "material_document_use_label": "Жүктелген PDF/DOC/DOCX файлдарын қалай пайдалану керек?",
1009
  "material_use_reference": "Ғылыми дереккөз ретінде",
1010
  "material_use_research": "Зерттеу материалы ретінде",
1011
+ "detected_method_label": "Зерттеу дизайны (автоматты түрде анықталады, өзгертуге болады)",
1012
+ "method_detection_explanation": "Зерттеу дизайны мақала тақырыбы мен кілт сөздер негізінде автоматты түрде анықталады. Анықталмаса, әдепкі бойынша сапалық зерттеу таңдалады. Таңдауды қолмен өзгертуге болады.",
1013
+ "method_confirm_label": "Зерттеу дизайнын өзгерту",
1014
+ "method_confirm_placeholder": "Зерттеу дизайнын таңдаңыз",
1015
+ "method_confirmation_required": "Зерттеу дизайнының күйі жарамсыз. Зерттеу дизайнын қайта таңдаңыз.",
1016
+ "method_resolution_invalid": "Зерттеу дизайнының күйі жарамсыз. Зерттеу дизайнын қайта таңдаңыз.",
1017
+ "method_not_supported": "Ағымдағы зерттеу дизайны: «{method}». Бұл дизайнның арнайы генерация қозғалтқышы әлі қосылмаған, сондықтан тапсырма құрылмайды және квота пайдаланылмайды.",
1018
+ "method_supported": "Ағымдағы зерттеу дизайны: «{method}». SmartPaper тиісті зерттеу үдерісін қолданады.",
1019
+ "method_undetermined": "Сапалық зерттеу (әдепкі)",
1020
+ "method_survey_path": "Сауалнамаға негізделген сандық зерттеу",
1021
  "method_qualitative": "Сапалық зерттеу",
1022
+ "method_fsqca": "Бұлыңғыр жиындарға негізделген сапалық салыстырмалы талдау (fsQCA)",
1023
  "method_meta_analysis": "Мета-талдау",
1024
+ "method_panel_econometrics": "Панельдік деректерді эконометриялық талдау",
1025
+ "method_bibliometric_integrative_review": "Библиометриялық талдау және әдебиеттерге интегративті шолу",
1026
  "adaptive_template_expander": "💡 Ұсынылатын үлгі (міндетті емес)",
1027
  "download_research_template": "📥 Зерттеу материалдары үлгісін жүктеу",
1028
  "template_help_survey_path": "Айнымалылар немесе статистикалық нәтижелер кестесі ұсынылады. Дерек жүктелмесе, SmartPaper жоба ережелеріне сәйкес бастапқы нұсқаға арналған көмекші дәлелдерді құра алады.",