P0-R5-R3-C event-driven Research Design state fix

#141
Files changed (1) hide show
  1. app.py +43 -25
app.py CHANGED
@@ -505,16 +505,16 @@ def _uploaded_material_descriptors() -> list[dict[str, str]]:
505
 
506
 
507
  def _method_intent_signature() -> str:
508
- """Identity for the manual Research Design control and current paper intent.
509
 
510
- A new task defaults to Qualitative Research. If the user manually selects
511
- Survey-Based Quantitative Research, changing the Title or Keywords resets
512
- the design to Qualitative Research so the workflow and recommended template
513
- return to the qualitative/ASQ lane together. Uploaded materials do not reset
514
- the selection.
515
  """
516
  payload = {
517
- "research_design_control": "manual-default-qualitative-v2",
518
  "topic": str(st.session_state.get("sp_topic") or DEFAULT_TOPIC).strip(),
519
  "keywords": str(st.session_state.get("sp_keywords") or DEFAULT_KEYWORDS).strip(),
520
  }
@@ -523,6 +523,21 @@ def _method_intent_signature() -> str:
523
  ).hexdigest()
524
 
525
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  def _current_method_preflight(*, confirmed_method_family: str | None = None) -> tuple[dict, str]:
527
  signature = _method_intent_signature()
528
  stored_confirmation = str(st.session_state.get("sp_method_confirmation") or "").strip()
@@ -1479,8 +1494,20 @@ def render_workspace_controls(user):
1479
  st.rerun()
1480
  st.markdown("---")
1481
 
1482
- st.text_input(tr(lang_code, "topic_label"), value=DEFAULT_TOPIC, disabled=active, key="sp_topic")
1483
- st.text_input(tr(lang_code, "keywords_label"), value=DEFAULT_KEYWORDS, disabled=active, key="sp_keywords")
 
 
 
 
 
 
 
 
 
 
 
 
1484
 
1485
  # U1-R2 unified research workspace: academic intent/materials first, then
1486
  # product/length controls. Legacy AMJ/ASQ remains internal policy routing.
@@ -1521,24 +1548,15 @@ def render_workspace_controls(user):
1521
  method_signature = ""
1522
  else:
1523
  # SmartPaper intentionally supports only two reader-visible research
1524
- # designs. New tasks default to qualitative research. The user may
1525
- # adjust the design manually. Changing Title or Keywords resets a manual
1526
- # survey selection to qualitative; uploaded materials do not reset it.
1527
  method_signature = _method_intent_signature()
1528
- stored = str(st.session_state.get("sp_method_confirmation") or "").strip().casefold()
1529
- stored_sig = str(st.session_state.get("sp_method_confirmation_signature") or "").strip()
1530
- selected_default = (
1531
- stored if stored_sig == method_signature and stored in METHOD_FAMILIES else "qualitative"
1532
- )
1533
-
1534
- selector_sig = str(st.session_state.get("sp_method_selector_signature") or "").strip()
1535
- if selector_sig != method_signature:
1536
- st.session_state["sp_method_confirmation"] = ""
1537
- st.session_state["sp_method_confirmation_signature"] = ""
1538
- st.session_state["sp_method_selector"] = "qualitative"
1539
- st.session_state["sp_method_selector_signature"] = method_signature
1540
  selected_default = "qualitative"
1541
- elif str(st.session_state.get("sp_method_selector") or "").strip().casefold() not in METHOD_FAMILIES:
1542
  st.session_state["sp_method_selector"] = selected_default
1543
 
1544
  selected = st.selectbox(
 
505
 
506
 
507
  def _method_intent_signature() -> str:
508
+ """Identity of the current paper intent for launch-time stale-state checks.
509
 
510
+ Title/Keywords remain part of the launch signature so a pending generation
511
+ cannot start against a different paper intent. Research Design reset itself
512
+ is event-driven by the Title/Keywords widgets rather than by every Streamlit
513
+ rerun; unrelated product-tier, word-count, and button reruns therefore never
514
+ change the selected design. Uploaded materials do not reset the selection.
515
  """
516
  payload = {
517
+ "research_design_control": "manual-default-qualitative-v3-event-reset",
518
  "topic": str(st.session_state.get("sp_topic") or DEFAULT_TOPIC).strip(),
519
  "keywords": str(st.session_state.get("sp_keywords") or DEFAULT_KEYWORDS).strip(),
520
  }
 
523
  ).hexdigest()
524
 
525
 
526
+ def _reset_research_design_after_intent_edit() -> None:
527
+ """Reset a not-yet-started paper to the qualitative default after intent edit.
528
+
529
+ Streamlit invokes this callback only when the Title or Keywords widget
530
+ actually changes. It is intentionally not attached to product tier, target
531
+ words, research materials, or the Generate button.
532
+ """
533
+ st.session_state["sp_method_selector"] = "qualitative"
534
+ st.session_state["sp_method_confirmation"] = ""
535
+ st.session_state["sp_method_confirmation_signature"] = ""
536
+ st.session_state["sp_method_selector_signature"] = ""
537
+ st.session_state["sp_pending_launch"] = None
538
+ st.session_state["run_mode"] = "asq"
539
+
540
+
541
  def _current_method_preflight(*, confirmed_method_family: str | None = None) -> tuple[dict, str]:
542
  signature = _method_intent_signature()
543
  stored_confirmation = str(st.session_state.get("sp_method_confirmation") or "").strip()
 
1494
  st.rerun()
1495
  st.markdown("---")
1496
 
1497
+ st.text_input(
1498
+ tr(lang_code, "topic_label"),
1499
+ value=DEFAULT_TOPIC,
1500
+ disabled=active,
1501
+ key="sp_topic",
1502
+ on_change=_reset_research_design_after_intent_edit,
1503
+ )
1504
+ st.text_input(
1505
+ tr(lang_code, "keywords_label"),
1506
+ value=DEFAULT_KEYWORDS,
1507
+ disabled=active,
1508
+ key="sp_keywords",
1509
+ on_change=_reset_research_design_after_intent_edit,
1510
+ )
1511
 
1512
  # U1-R2 unified research workspace: academic intent/materials first, then
1513
  # product/length controls. Legacy AMJ/ASQ remains internal policy routing.
 
1548
  method_signature = ""
1549
  else:
1550
  # SmartPaper intentionally supports only two reader-visible research
1551
+ # designs. New tasks default to qualitative research. Title/Keywords
1552
+ # changes reset the selector through their explicit on_change callback;
1553
+ # unrelated Streamlit reruns must preserve the user's manual selection.
1554
  method_signature = _method_intent_signature()
1555
+ selected_default = str(
1556
+ st.session_state.get("sp_method_selector") or "qualitative"
1557
+ ).strip().casefold()
1558
+ if selected_default not in METHOD_FAMILIES:
 
 
 
 
 
 
 
 
1559
  selected_default = "qualitative"
 
1560
  st.session_state["sp_method_selector"] = selected_default
1561
 
1562
  selected = st.selectbox(