Skip to content

FAC-135 feat: aggregate-scope pipelines, tri-view analytics, faculty self-view #345

Description

@y4nder

Context

FAC-134 surfaced two architectural issues during manual verification:

  1. Per-type pipeline scope was too narrow — the pipeline ran per questionnaireVersion, but faculty analytics need cross-type aggregation (themes drawn from all student feedback, not siloed by questionnaire type). Low-volume types produced degenerate results or empty views.
  2. Faculty had no self-service analytics view — only Dean/Chairperson/Campus-Head roles could view faculty analytics. Faculty members themselves had no entry point and no redacted perspective appropriate for their role.

What was built

Backend (api.faculytics)

Phase A — Aggregate-scope pipelines

  • Pipeline scope collapsed from per-questionnaireVersion to {scopeType, scopeId}. questionnaireVersion is now nullable on AnalysisPipeline.
  • Qualitative-summary lookup uses $or filter to match both aggregate (questionnaireVersion = null) and legacy per-type pipelines.
  • Pipeline summary/status DTOs updated for the new scope shape.

Phase B — Tiered scheduler

  • TieredPipelineSchedulerJob: cron-driven pipeline scheduling with next-run calculation.
  • Auto-confirm orchestrator path for scheduled (non-manual) pipeline triggers.

Tri-view backend support

  • AnalysisAccessService: Faculty self-only auth — faculty users can only access their own analysis data via teaching-footprint scope check.
  • New GET /analytics/faculty/:id/questionnaire-types endpoint returning per-faculty per-semester submission counts.
  • RecommendedAction.facet column + migration for action categorization.

Recommendation schema tighten

  • topicReference changed from optional().nullable() to nullable() — required field, null only when score-driven.
  • LLM prompt copy updated to enforce this contract.
  • Schema-level and integration tests added.

Frontend (app.faculytics)

Tri-view split

  • Faculty report screen split into three tabs: Insights, Scores, Feedback.
  • Questionnaire-type secondary tabs with per-type submission counts.
  • Brand-blue tab styling (line variant for main tabs, tinted pills for sub-tabs).

Faculty self-view

  • /faculty/analytics auto-resolves the current semester from the user's campus.
  • Feedback tab redacted entirely for Faculty role.
  • Theme explorer cards hide "What Students Say", "All Comments", and sentiment breakdown — only Suggested Action is shown.
  • Back button routes to /faculty/courses with role-aware label.

Bug fixes

  • Fixed stale qualitative-summary cache after pipeline regeneration (transition-detecting invalidation).
  • Hardened questionnaireTypeCode derivation to never produce empty strings.
  • Removed dead facet lens from Insights tab.
  • Fixed ?facet= URL param auto-strip for old bookmarks.

PRs

Acceptance criteria

  • Aggregate-scope pipelines correctly found by qualitative-summary endpoint
  • Legacy per-type pipelines still matched via $or fallback
  • Faculty user can only access their own analysis data
  • /questionnaire-types endpoint returns per-faculty submission counts
  • Recommendation topicReference enforced as required-or-null (not optional)
  • Faculty self-view at /faculty/analytics auto-resolves semester
  • Faculty sees only Insights + Scores (Feedback tab hidden)
  • Faculty theme cards show only Suggested Action (no comments, no sentiment breakdown)
  • Pipeline completion invalidates qualitative-summary cache
  • questionnaireTypeCode never sent as empty string to API
  • All backend tests pass (1028 tests)
  • Frontend typecheck + lint clean

Related

  • FAC-134 (surfaced the per-type scope problem during verification)
  • FAC-132 (original pipeline infrastructure)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions