feat: ContentGuardianAgent, onboarding UX, Team Activity action wiring, docs, agent help modal

ContentGuardianAgent consolidation:
- Merge 3 duplicate classes into single source in specialized/content_guardian.py
- Watchdog audit_committee() with heuristic scoring, coverage gaps, overlaps, alerts
- Remove misleading rejection_rate() helper; use acceptance_rate directly
- Integrate audit + alerts + trend signals into today_workflow_service.py

Team Activity page:
- QualityAuditPanel: health ring, per-agent critiques, coverage gaps, overlaps
- TrendSignalsPanel: opportunity cards with urgency/impact/coverage bars
- AlertBanner: persistent dismiss via POST /alerts/{id}/mark-read
- AgentHelpModal: dialog showing all 8 agents with descriptions, tools, schedule
- QualityAuditPanel action buttons: Fill gap -> /content-planning, Resolve overlap, View CTA on alerts/issues
- TrendSignalsPanel action buttons: Create content from this trend -> /blog-writer with trend context state

Onboarding system:
- Step 4 validation: no auto-pass via basic_ready; requires persona data or explicit progression
- Step 5 validation: logs warning on auto-pass without integration data
- OnboardingCompletionService: single DB session, transactional task creation, upsert pattern
- Business-without-website: nullable website_url on SIFIndexingTask and MarketTrendsTask
- DeepCompetitorAnalysisExecutor: 5-min timeout, 10-competitor cap, asyncio.wait_for
- Persona generation: async with 30s timeout, falls back to scheduler
- OnboardingProgressService.reset_onboarding(): resets session + pauses all DB tasks
- OnboardingControlService.reset_onboarding(): also cancels APScheduler jobs
- FinalStep TaskSchedulingPanel: shows scheduled/failed tasks after completion, 8s auto-redirect
- onboarding_completed agent activity event logged to feed

Documentation:
- docs-site/features/onboarding/: overview, steps, scheduler-tasks, technical-reference (4 pages)
- docs-site/mkdocs.yml: added Onboarding System nav section
- docs-site/features/sif-agents/: overview, agent-directory, committee-system, content-guardian (4 pages)
- docs-site/features/team-activity/: overview, quality-audit, trend-signals, alert-system (4 pages)
- docs-site/features/todays-workflow/: updated overview, technical-architecture, workflow-guide, api-reference
This commit is contained in:
ajaysi
2026-06-01 12:24:31 +05:30
parent 9b472f1c18
commit 923fa671fe
90 changed files with 8914 additions and 2731 deletions

View File

@@ -126,21 +126,85 @@ class SocialAmplificationAgent(BaseALwrityAgent):
async def propose_daily_tasks(self, context: Dict[str, Any]) -> List[TaskProposal]:
"""
Propose social media tasks.
Propose social media tasks based on user's onboarding context.
Derives platforms and content types from user data.
"""
proposals = []
# 1. Social Post Creation
onboarding = context.get("onboarding_data", {})
if not isinstance(onboarding, dict):
return proposals
# Extract selected platforms from onboarding step 5
selected_platforms = []
try:
step5 = onboarding.get("step5_summary") or onboarding.get("distribution_channels") or {}
if isinstance(step5, dict):
sp = step5.get("selected_platforms") or step5.get("platforms") or []
selected_platforms = [p for p in sp if isinstance(p, str)]
if not selected_platforms:
# Fallback: check top-level keys
for key in ("selected_platforms", "platforms", "social_platforms"):
val = onboarding.get(key)
if isinstance(val, list):
selected_platforms = [p for p in val if isinstance(p, str)]
break
except Exception:
pass
platform_urls = {
"linkedin": "/linkedin-writer",
"facebook": "/facebook-writer",
"twitter": "/linkedin-writer", # no dedicated twitter writer, use linkedin as fallback
"instagram": "/linkedin-writer",
"tiktok": "/linkedin-writer",
"youtube": "/linkedin-writer",
}
target_platforms = [p for p in selected_platforms if p.lower() in platform_urls]
if not target_platforms:
# No known platforms configured — generic engage task
proposals.append(TaskProposal(
title="Share content on social media",
description="Promote your latest published piece across your social channels.",
pillar_id="engage",
priority="medium",
estimated_time=20,
source_agent="SocialAmplificationAgent",
reasoning="Social distribution drives referral traffic and builds audience engagement.",
action_type="navigate",
action_url="/linkedin-writer",
))
return proposals
platform = target_platforms[0]
platform_label = platform.capitalize()
proposals.append(TaskProposal(
title="Create LinkedIn Thread",
description="Summarize your latest blog post into a 5-tweet thread.",
pillar_id="distribute",
title=f"Share content on {platform_label}",
description=f"Adapt and publish your latest content as a {platform_label} post to drive engagement.",
pillar_id="engage",
priority="medium",
estimated_time=20,
source_agent="SocialAmplificationAgent",
reasoning="Repurpose existing content.",
reasoning=f"Consistent {platform_label} posting maintains audience engagement and extends content reach.",
action_type="navigate",
action_url="/content-planning-dashboard"
action_url=platform_urls[platform.lower()],
context_data={"platform": platform.lower()},
))
if len(target_platforms) > 1:
platform2 = target_platforms[1]
proposals.append(TaskProposal(
title=f"Cross-post to {platform2.capitalize()}",
description=f"Repurpose your latest content for your {platform2.capitalize()} audience.",
pillar_id="engage",
priority="low",
estimated_time=15,
source_agent="SocialAmplificationAgent",
reasoning=f"Cross-posting to {platform2.capitalize()} increases reach without additional content creation cost.",
action_type="navigate",
action_url=platform_urls[platform2.lower()],
context_data={"platform": platform2.lower()},
))
return proposals