P0-R3 Research Design manual authority fix

#137
Files changed (2) hide show
  1. app.py +11 -18
  2. core/advanced_method_registry.py +8 -11
app.py CHANGED
@@ -1517,11 +1517,10 @@ def render_workspace_controls(user):
1517
  }
1518
  method_signature = ""
1519
  else:
1520
- # U1-R2C: SmartPaper intentionally supports only two reader-visible
1521
- # research designs. No cue defaults to qualitative. Specialized-method
1522
- # cues (panel/meta/fsQCA/bibliometric-review) are advisory-only and pin
1523
- # the current topic to the qualitative framework rather than exposing
1524
- # or blocking on an unsupported method family.
1525
  auto_preflight, method_signature = _current_method_preflight(confirmed_method_family="")
1526
  auto_family = str(auto_preflight.get("method_family") or "qualitative").strip().casefold()
1527
  if auto_family not in METHOD_FAMILIES:
@@ -1531,16 +1530,14 @@ def render_workspace_controls(user):
1531
  stored = str(st.session_state.get("sp_method_confirmation") or "").strip().casefold()
1532
  stored_sig = str(st.session_state.get("sp_method_confirmation_signature") or "").strip()
1533
  selected_default = (
1534
- auto_family
1535
- if specialized_redirect
1536
- else (stored if stored_sig == method_signature and stored in METHOD_FAMILIES else auto_family)
1537
  )
1538
 
1539
  # A changed Title/Keywords signature invalidates a previous manual
1540
- # override. Specialized topics also clear any prior override so they
1541
- # cannot be silently converted into an ordinary survey manuscript.
1542
  selector_sig = str(st.session_state.get("sp_method_selector_signature") or "").strip()
1543
- if selector_sig != method_signature or specialized_redirect:
1544
  st.session_state["sp_method_confirmation"] = ""
1545
  st.session_state["sp_method_confirmation_signature"] = ""
1546
  st.session_state["sp_method_selector"] = auto_family
@@ -1555,14 +1552,10 @@ def render_workspace_controls(user):
1555
  index=list(METHOD_FAMILIES).index(selected_default),
1556
  format_func=lambda family: tr(lang_code, f"method_{family}"),
1557
  key="sp_method_selector",
1558
- disabled=active or specialized_redirect,
1559
  )
1560
  selected = str(selected or auto_family).strip().casefold()
1561
- if specialized_redirect:
1562
- selected = "qualitative"
1563
- st.session_state["sp_method_confirmation"] = ""
1564
- st.session_state["sp_method_confirmation_signature"] = ""
1565
- elif selected != auto_family:
1566
  st.session_state["sp_method_confirmation"] = selected
1567
  st.session_state["sp_method_confirmation_signature"] = method_signature
1568
  else:
@@ -1582,7 +1575,7 @@ def render_workspace_controls(user):
1582
 
1583
  block_reason = str(preflight.get("block_reason") or "")
1584
  specialized_redirect = bool((preflight.get("resolution") or {}).get("specialized_method_detected"))
1585
- if specialized_redirect and not active:
1586
  st.warning(tr(lang_code, "specialized_method_redirect"))
1587
  elif block_reason:
1588
  st.warning(tr(lang_code, "method_resolution_invalid"))
 
1517
  }
1518
  method_signature = ""
1519
  else:
1520
+ # SmartPaper intentionally supports only two reader-visible research
1521
+ # designs. No cue defaults to qualitative. Specialized-method cues remain
1522
+ # advisory-only for automatic detection; an explicit user selection
1523
+ # between the two supported designs is authoritative for this topic.
 
1524
  auto_preflight, method_signature = _current_method_preflight(confirmed_method_family="")
1525
  auto_family = str(auto_preflight.get("method_family") or "qualitative").strip().casefold()
1526
  if auto_family not in METHOD_FAMILIES:
 
1530
  stored = str(st.session_state.get("sp_method_confirmation") or "").strip().casefold()
1531
  stored_sig = str(st.session_state.get("sp_method_confirmation_signature") or "").strip()
1532
  selected_default = (
1533
+ stored if stored_sig == method_signature and stored in METHOD_FAMILIES else auto_family
 
 
1534
  )
1535
 
1536
  # A changed Title/Keywords signature invalidates a previous manual
1537
+ # override. For the same signature, the user's explicit selection remains
1538
+ # authoritative even when automatic detection found a specialized cue.
1539
  selector_sig = str(st.session_state.get("sp_method_selector_signature") or "").strip()
1540
+ if selector_sig != method_signature:
1541
  st.session_state["sp_method_confirmation"] = ""
1542
  st.session_state["sp_method_confirmation_signature"] = ""
1543
  st.session_state["sp_method_selector"] = auto_family
 
1552
  index=list(METHOD_FAMILIES).index(selected_default),
1553
  format_func=lambda family: tr(lang_code, f"method_{family}"),
1554
  key="sp_method_selector",
1555
+ disabled=active,
1556
  )
1557
  selected = str(selected or auto_family).strip().casefold()
1558
+ if selected != auto_family:
 
 
 
 
1559
  st.session_state["sp_method_confirmation"] = selected
1560
  st.session_state["sp_method_confirmation_signature"] = method_signature
1561
  else:
 
1575
 
1576
  block_reason = str(preflight.get("block_reason") or "")
1577
  specialized_redirect = bool((preflight.get("resolution") or {}).get("specialized_method_detected"))
1578
+ if specialized_redirect and not active and method_family == "qualitative":
1579
  st.warning(tr(lang_code, "specialized_method_redirect"))
1580
  elif block_reason:
1581
  st.warning(tr(lang_code, "method_resolution_invalid"))
core/advanced_method_registry.py CHANGED
@@ -5,8 +5,9 @@ U1-R2C intentionally limits production research design to two supported paths:
5
  qualitative research and survey-based quantitative research. Specialized cues
6
  such as fsQCA, panel data/econometrics, meta-analysis, and bibliometric/review
7
  methods are detected only to provide a reader-facing scope notice; they are not
8
- exposed as selectable method families and are redirected to the qualitative
9
- framework before task creation.
 
10
 
11
  This module never selects providers/models and never rewrites Title/Keywords.
12
  """
@@ -16,7 +17,7 @@ import os
16
  import re
17
  from typing import Any, Iterable
18
 
19
- METHOD_RESOLVER_VERSION = "smartpaper-auto-method-resolver-v4"
20
  METHOD_CAPABILITY_REGISTRY_VERSION = "smartpaper-method-capability-registry-v3"
21
 
22
  # Reader-visible / task-owning method families. Order is intentional:
@@ -252,16 +253,15 @@ def resolve_generation_preflight(
252
  """Resolve the two supported designs before any task/quota creation.
253
 
254
  Manual adjustment is available only between qualitative and survey-based
255
- quantitative research. Specialized-method cues intentionally pin the
256
- current topic to the qualitative fallback so a user cannot silently turn a
257
- panel/meta/fsQCA/review topic into an ordinary survey manuscript.
258
  """
259
  resolution = resolve_method_family(title, keywords, materials=materials)
260
  family = str(resolution.get("method_family") or "qualitative").strip().casefold()
261
 
262
  confirmed = str(confirmed_method_family or "").strip().casefold()
263
- specialized = bool(resolution.get("specialized_method_detected"))
264
- if not specialized and confirmed in METHOD_FAMILIES and confirmed != family:
265
  family = confirmed
266
  capability = method_capability(family)
267
  resolution = dict(resolution)
@@ -272,9 +272,6 @@ def resolve_generation_preflight(
272
  "capability": capability,
273
  "reason_codes": list(resolution.get("reason_codes") or []) + ["user_override_method_family"],
274
  })
275
- elif specialized:
276
- resolution = dict(resolution)
277
- resolution["manual_override_locked"] = True
278
 
279
  capability = method_capability(family)
280
  lane = str(capability.get("legacy_policy_lane") or "").strip().casefold() or None
 
5
  qualitative research and survey-based quantitative research. Specialized cues
6
  such as fsQCA, panel data/econometrics, meta-analysis, and bibliometric/review
7
  methods are detected only to provide a reader-facing scope notice; they are not
8
+ exposed as selectable method families. Automatic detection falls back to the
9
+ qualitative framework, while an explicit user selection between the two supported
10
+ designs remains authoritative for the current Title + Keywords signature.
11
 
12
  This module never selects providers/models and never rewrites Title/Keywords.
13
  """
 
17
  import re
18
  from typing import Any, Iterable
19
 
20
+ METHOD_RESOLVER_VERSION = "smartpaper-auto-method-resolver-v5"
21
  METHOD_CAPABILITY_REGISTRY_VERSION = "smartpaper-method-capability-registry-v3"
22
 
23
  # Reader-visible / task-owning method families. Order is intentional:
 
253
  """Resolve the two supported designs before any task/quota creation.
254
 
255
  Manual adjustment is available only between qualitative and survey-based
256
+ quantitative research. Automatic detection may map specialized-method cues
257
+ to the qualitative fallback, but an explicit user selection between the two
258
+ supported production designs is authoritative for the current topic.
259
  """
260
  resolution = resolve_method_family(title, keywords, materials=materials)
261
  family = str(resolution.get("method_family") or "qualitative").strip().casefold()
262
 
263
  confirmed = str(confirmed_method_family or "").strip().casefold()
264
+ if confirmed in METHOD_FAMILIES and confirmed != family:
 
265
  family = confirmed
266
  capability = method_capability(family)
267
  resolution = dict(resolution)
 
272
  "capability": capability,
273
  "reason_codes": list(resolution.get("reason_codes") or []) + ["user_override_method_family"],
274
  })
 
 
 
275
 
276
  capability = method_capability(family)
277
  lane = str(capability.get("legacy_policy_lane") or "").strip().casefold() or None