cesjavi commited on
Commit
a7168e9
·
1 Parent(s): aeb2234

Refine final report consolidation and text cleanup

Browse files
backend/services/orchestrator_service.py CHANGED
@@ -69,6 +69,34 @@ def _format_output_for_report(output_data) -> str:
69
  return clean_report_text(dedupe_lines("\n".join(_format_value_for_report(primary))))
70
 
71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  def _has_usable_output(output_data) -> bool:
73
  if not output_data:
74
  return False
@@ -505,11 +533,19 @@ class OrchestratorService:
505
  lines.extend(["## Approved Work Summary", ""])
506
 
507
  report_exclusions: list[str] = []
508
- for index, task in enumerate(curated_tasks, start=1):
 
509
  curated_text, excluded_lines = self._curate_task_output(task.get("output_data"))
510
  report_exclusions.extend(excluded_lines)
 
 
 
 
 
 
 
511
  lines.extend([
512
- f"### {index}. {task['title']}",
513
  task.get("description") or "No task description provided.",
514
  "",
515
  curated_text,
@@ -551,7 +587,7 @@ class OrchestratorService:
551
  if isinstance(data, str):
552
  conclusion = data
553
  elif isinstance(data, dict):
554
- conclusion = data.get("conclusion") or data.get("content") or str(data)
555
  except Exception as exc:
556
  logger.warning(f"Failed to generate dynamic conclusion: {exc}")
557
 
@@ -560,7 +596,7 @@ class OrchestratorService:
560
  conclusion,
561
  "",
562
  "## Completion Status",
563
- f"{len(tasks)} tasks reached done status. {len(curated_tasks)} task outputs passed final quality validation. {len(excluded_tasks)} task outputs were excluded from the final report."
564
  ])
565
 
566
  supabase.table("projects").update({"status": "completed"}).eq("id", project_id).execute()
@@ -577,7 +613,7 @@ class OrchestratorService:
577
  return {
578
  "project_id": project_id,
579
  "project_name": project["name"],
580
- "task_count": len(curated_tasks),
581
  "variant": variant,
582
  "report": clean_report_text(dedupe_lines(report)),
583
  "charts": _build_report_charts(curated_tasks)
 
69
  return clean_report_text(dedupe_lines("\n".join(_format_value_for_report(primary))))
70
 
71
 
72
+ def _is_empty_curated_text(text: str) -> bool:
73
+ normalized = (text or "").strip().lower()
74
+ return normalized in {
75
+ "",
76
+ "no approved output was saved for this task.",
77
+ "{}",
78
+ "[]",
79
+ }
80
+
81
+
82
+ def _format_conclusion_payload(data: dict) -> str:
83
+ conclusion = data.get("strategicConclusion") or data.get("conclusion") or data.get("content") or ""
84
+ next_steps = data.get("nextSteps") or data.get("next_steps") or []
85
+
86
+ lines: list[str] = []
87
+ if isinstance(conclusion, str) and conclusion.strip():
88
+ lines.append(conclusion.strip())
89
+
90
+ if isinstance(next_steps, list) and next_steps:
91
+ lines.append("")
92
+ lines.append("Next steps:")
93
+ for step in next_steps[:5]:
94
+ if isinstance(step, str) and step.strip():
95
+ lines.append(f"- {step.strip()}")
96
+
97
+ return "\n".join(lines).strip() or "\n".join(_format_value_for_report(data))
98
+
99
+
100
  def _has_usable_output(output_data) -> bool:
101
  if not output_data:
102
  return False
 
533
  lines.extend(["## Approved Work Summary", ""])
534
 
535
  report_exclusions: list[str] = []
536
+ kept_task_count = 0
537
+ for task in curated_tasks:
538
  curated_text, excluded_lines = self._curate_task_output(task.get("output_data"))
539
  report_exclusions.extend(excluded_lines)
540
+ if _is_empty_curated_text(curated_text):
541
+ excluded_tasks.append({
542
+ "title": task.get("title", "Untitled task"),
543
+ "reasons": ["Task output became empty after quality filtering."]
544
+ })
545
+ continue
546
+ kept_task_count += 1
547
  lines.extend([
548
+ f"### {kept_task_count}. {task['title']}",
549
  task.get("description") or "No task description provided.",
550
  "",
551
  curated_text,
 
587
  if isinstance(data, str):
588
  conclusion = data
589
  elif isinstance(data, dict):
590
+ conclusion = _format_conclusion_payload(data)
591
  except Exception as exc:
592
  logger.warning(f"Failed to generate dynamic conclusion: {exc}")
593
 
 
596
  conclusion,
597
  "",
598
  "## Completion Status",
599
+ f"{len(tasks)} tasks reached done status. {kept_task_count} task outputs were included in the final report. {len(excluded_tasks)} task outputs were excluded from the final report."
600
  ])
601
 
602
  supabase.table("projects").update({"status": "completed"}).eq("id", project_id).execute()
 
613
  return {
614
  "project_id": project_id,
615
  "project_name": project["name"],
616
+ "task_count": kept_task_count,
617
  "variant": variant,
618
  "report": clean_report_text(dedupe_lines(report)),
619
  "charts": _build_report_charts(curated_tasks)
backend/services/output_quality.py CHANGED
@@ -271,7 +271,7 @@ def report_text_from_output(output_data: Any) -> str:
271
 
272
 
273
  def clean_report_text(text: str) -> str:
274
- cleaned = text.replace("■", "-")
275
  cleaned = re.sub(r"[ \t]+", " ", cleaned)
276
  cleaned = re.sub(r"\n{3,}", "\n\n", cleaned)
277
  return cleaned.strip()
@@ -307,3 +307,5 @@ def filter_report_sections(text: str) -> tuple[str, list[str]]:
307
  continue
308
  kept_lines.append(line)
309
  return "\n".join(kept_lines).strip(), excluded
 
 
 
271
 
272
 
273
  def clean_report_text(text: str) -> str:
274
+ cleaned = text.replace("■", "-").replace("\u25A0", "-")
275
  cleaned = re.sub(r"[ \t]+", " ", cleaned)
276
  cleaned = re.sub(r"\n{3,}", "\n\n", cleaned)
277
  return cleaned.strip()
 
307
  continue
308
  kept_lines.append(line)
309
  return "\n".join(kept_lines).strip(), excluded
310
+
311
+