Branch, Cone, and Feature Inventory

A per-function index of R/branches/, R/cones/, and R/features/. AGENTS.md lists these one row per file; this page is the detail. Check the source before trusting a signature — this table drifts.

Branches — Reusable Domain Computations (R/branches/)

File Main function(s) Purpose
catalog-extraction.R catalog_program_scope(index, credentials), extract_catalog_rule_tree(html), extract_catalog_record(record, kind, receipt, edition, schemas, fields), catalog_rule_rows(record, section) Preserve captured list nesting, named wrappers, grade thresholds, source evidence and unresolved conditions; classify explicit credential scope
catalog-comparison.R catalog_section_rows(record), compare_catalog_sections(before, after) Compare source wording, explicit structure, formatting and metadata without eligibility/equivalence inference
catalog-milestones.R resolve_catalog_milestones(records), catalog_milestone_rows(records, rules) Shared standing/admission identities, program-link resolution and captured admission-policy context; preserves status predicates without inferring student eligibility, credits or semester placement
catalog-review.R build_catalog_review_items(records, nodes, issues), catalog_review_program_entities(records, program_id), filter_catalog_review(payload, program, kind, phase), catalog_review_tree_text(tree, level) Actionable unreviewed work list, program reference closure and draft structure display; references never establish requirements
catalog-normalization.R catalog_normalization_blocks(html, section, record), validate_catalog_normalization(proposal, request), catalog_normalization_review_state(proposal), edit_catalog_normalization(state, proposal, request), catalog_normalization_decision(state, type, id, decision, note), catalog_normalization_issues(state), approve_catalog_normalization(state), clear_catalog_normalization_flag(state, type, id, note) Faithful source passages, fixed normalized graph/evidence/coverage validation and pure human-review transitions; edits reset approvals
degree-requirements.R degree_rule_outline(catalog, catalog_ids), degree_math_start_choices(roadmaps, catalog_id), build_degree_roadmap(catalog, roadmaps, catalog_id, math_start, english_start) (built from resolve_degree_entry_routes(), prepare_degree_roadmap_nodes(), schedule_degree_roadmap(nodes, links, conditions, max_load) and allocate_degree_semester_credits(nodes, loads, policy, completed_credits)), assign_degree_roadmap_rows(nodes), build_degree_allowance_slots(terms, slot_credits), degree_semester_seasons(semesters, start_season), get_degree_chain_metrics(nodes, links, conditions = NULL) (counts plus upstream_ids / downstream_ids, so the browser never walks the graph), attach_degree_roadmap_evidence(nodes, roadmaps, catalog, catalog_id), attach_pathway_groups(rows, groups), degree_path_course_table(paths, group_id) Preserve rule trees, select program-specific math routes, schedule complete workloads with early foundations, later upper-level courses, semester floors and credit limits, align authored course families beneath Gen Ed options without rescheduling, compute prerequisite chains, resolve quoted evidence, and classify descriptive coursework; no eligibility inference
population.R build_population(programs, degrees, students, opt) Build student populations for analysis; returns tibble with student_id + classification columns. The central cohort-building function.
  get_focal_programs(programs, opt) Resolve program names/codes to canonical list for population filters
  build_demographic_population(programs, opt) Population scoped by demographic characteristics
  get_ongoing_ids(), get_graduated_ids(), get_switched_out_ids(), get_never_declared_ids() Sub-classifiers used internally by build_population()
  get_entry_pathways(), classify_origin(), classify_entry_method(), classify_entry_status() Entry-type classification helpers
comparison.R build_comparison(treatment_ids, pool_ids, programs, ..., term_credits) Build treatment/control groups for observational analyses. Demographic and standing covariates come from cedar_programs at each student’s covariate term; the matched academic-position covariates (cum_gpa_entering, unm_credits_entering, total_credits_entering) are reconstructed via build_gpa_timeline() / build_credit_timeline(). current_unm_gpa (Banner Institution GPA) rides along for the profile only — see the descriptive-vs-matched split below. Never add a pull-stamped field to continuous_cols
  compute_balance(groups) Report covariate balance between treatment and control
enrl.R calc_cl_enrls(students), get_enrl(sections, opt), calc_first_day_enrl(students, sections, by_part_term = FALSE, pool_campuses = FALSE), add_first_day_enrl(cl_enrls, students, sections), class_list_status_date_coverage(students), enrollment_capacity_metrics(enrollment, capacity, constrained_threshold = CEDAR_NEAR_FULL_FILL), summarize_listing_overlap(students) Enrollment counts and stats; first-day enrollment reconstructed from class-list status dates, and which terms carry those dates; seat fill against the near-full level; students listed under more than one crosslisted code
  enrollment_capacity_metrics(enrollment, capacity), capacity_saturation_metrics(census_enrl, capacity) Shared numeric fill/quality/constraint calculations; census wrapper retains its named output contract, while first-day callers label their own lifecycle point.
  get_course_section_counts(sections) Active section count + total enrollment per course, crosslist-deduplicated. Returns one row per (term, subject_course, course_title, campus). Join on those four columns. Reusable in any tab, feature, or RStudio analysis that needs a “how many sections / how many students” summary without running a full enrollment pipeline.
  prepare_enrollment_trend_history(), get_enrollment_momentum(), prepare_enrollment_trend_plot_series() Enrollment Trend Signals helpers. Keep plot prep and campus-specific series handling here, not in dashboard/report modules.
  get_low_enrollment_courses(courses, opt, threshold) Sections below a threshold, filtered and deduplicated via filter_DESRs()
  classify_low_enrollment_terms(sections, terms, current_term, min_days_after_start) Which Low Enrollment view each selected term gets: a term after cedar_current_term with no enrollment yet is a schedule (concerns, each course against its history via get_enrollment_concerns()); every other term gets section alerts. registration_open marks counts pulled before registration settled, so the page labels them rather than presenting them as final
course-attempts.R prepare_course_attempts(students, opt) Shared cleaned course-attempt rows for grade/outcome analyses. New cones usually should not call this directly unless they need row-level attempts
  get_course_outcome_rates(students, opt, group_cols, min_n) Preferred cone API for DFW, W, D/F, C-, below-C, and early-drop metrics
  get_grade_distribution(students, opt, group_cols, min_n) Preferred cone API for A/B/C/D/F/W/Other grade distributions
demographics.R summarize_student_demographics(filtered_students, opt) Flexible demographic summary grouped by opt$group_cols (counts, term-type means, pct of course enrollment). Used by course-demographics and waitlist cones
headcount.R get_headcount(programs, opt) Student enrollment counts by program; result$scope holds headcount_scope_facts(), and describe_headcount_scope(facts, in_progress_terms) turns facts into the scope strip’s words (shared with the Dept Dashboard cards)
credit-hours.R get_credit_hours(students, opt), credit_hours_by_major(students, dept_code, major_codes, term_start, term_end, …), credit_hours_by_fac(students, faculty, dept_code, subj_codes, term_start, term_end, palette) Credit hour production; who takes a department’s courses (home major codes come from the caller, Dept Trends’ prog_codes); SCH by faculty job category (not displayed by Dept Trends today)
  filter_sch_rows(students) The one definition of an SCH row (credit-hours 2.0.0): still-registered (RE/RS/RR), audits excluded. Attempted, not earned, so a term has SCH before its grades post
data-edges.R cedar_data_edges(students, degrees, min_graded_share, max_term) The canonical right/left edge of the loaded data. Returns first_enrolled, last_enrolled, last_enrolled_complete, last_graded, last_degree. Never bound an analysis with max(term) or arithmetic on cedar_current_term — see the right-edge policy above
  cedar_report_edges(students, degrees) The app’s edges, computed once at startup by global.R and the cache-warming scripts. Returns the full edges plus graded_through, report_end_term and report_latest_term for the startup globals. Never capped at cedar_current_term; stops if the settled or graded edge cannot be determined
  cedar_edge_note(edges, which) The sentence a capped surface shows to explain which edge it used
  cedar_longitudinal_edge(edges, grade_dependent) Hard edge for analyses that require comparable history or later observation: last_enrolled_complete, or the earlier of it and last_graded when grades are read
  cedar_registration_settled(term, pulled, min_days_after_start) Whether a pull came at least min_days_after_start days after the term’s nominal start: the one settled rule behind last_enrolled_complete, shared with Low Enrollment’s in-progress label
  cedar_in_progress_terms(edges), cedar_in_progress_note(in_progress) Terms after last_graded (to last_enrolled) with their newest pull date and whether registration has settled, and the page sentence describing them. Descriptive charts show these terms and label them; they never drop them
gpa-timeline.R build_gpa_timeline(students, opt), attach_gpa_position() Per-term cumulative GPA rebuilt from class-list grade points, because inst_gpa is frozen across a student’s history for 67.8% of students with 5+ terms. gpa_entering excludes the term’s own grades
credit-timeline.R build_credit_timeline(term_credits, programs, opt) The only sanctioned source for “how far into their studies was this student at term T”. Rebuilds the position from the per-term class-list series plus a recovered transfer block, because the cedar_programs cumulative columns are stamped at pull time and frozen across a student’s history. Read the field reliability contract above before using anything else
  attach_credit_position(events, timeline, term_col, basis) Join a credit position onto any table of student-term events
degrees.R count_degrees(degrees, opt) Degree completion counts
course-flows.R get_next_course_pairs(students, opt, source_courses), get_previous_course_pairs(students, opt, target_courses) Campus-scoped source→destination course pairs across adjacent terms. Course sequencing always joins and groups by campus so students at different campuses are never treated as one flow
  get_course_destinations(), get_course_feeders(), get_concurrent_courses(), summarize_concurrent_courses(), get_course_flow_neighbors() Summaries of what registered students take after / before / alongside a course. Concurrent results count student-term enrollments, retain campus grain, and use every selected-course student-term in the percentage denominator; get_course_flow_neighbors() returns the combined named list
  get_downstream_course_options(students, course_x, opt) Course Dynamics follow-on picker. Percentages use the same course-level eligibility denominator as the selected-pair analysis: complete follow-up opportunity, with students who already passed a single Y strictly before X excluded. Includes registered and late-drop Y attempts so the picker and analysis cannot drift
  get_downstream_pair_audit(students, course_x, course_y, opt) Instructor-neutral course-pair denominator plus yearly course-order totals. Each student appears once, keyed to the year of first X; strict-prior and same-term Y passes remain separate
pathways.R pathways_level_filter(), pathways_observation_boundary(), apply_pathways_population_window(), resolve_pathways_focal_programs/dept_codes/subjects() Pure result-shaping helpers for the Pathways module — calculation-affecting rules kept testable without loading Shiny

Named population groups (R/branches/population.R)

Function Purpose
population_group_ids() / population_group_choices() / population_group_default(surface) The shared group registry (CEDAR_POPULATION_GROUPS, from institution/<id>/population_groups.csv) as ids or selectize choices, and the group a surface preselects (default_for in the file, else the first group)
population_group_program_names(group_id) The program names a group declares
population_group_major_codes(group_id, programs, include_pre_majors) Resolves a group to Banner major codes through name matching and each pre-major’s leads_to (programs.csv), because each alone misses real pre-majors. include_pre_majors takes build_population()’s vocabulary: lump / majors_only / pre_only
population_group_audit(group_id, programs) codes, unmatched_names, and near_miss — the drifted names a name-declared group would otherwise drop silently. Run it when adding a group

Data anomaly screens (R/branches/data-anomalies.R)

Function Purpose
detect_pre_major_self_mapping(programs) Pre-majors whose dept_code is their own major_code — always a mapping failure, and invisible to cedar_mapping_issues because the row is mapped
detect_selective_admission_signal(programs, degrees, opt) Programs carrying far more declared majors than they graduate. Pair student_level with award_category; counting graduate majors against baccalaureate degrees is what made Special Education score 13.4
build_data_anomaly_report(programs, degrees, opt) Both screens in the cedar_mapping_issues column shape

Mapping audit (R/branches/mapping-audit.R)

Function Purpose
audit_mapping_coverage(files, sections, students, programs, degrees) Every value the loaded data uses that institution/<id>/ does not cover — course subjects, section colleges, program codes, source college names, units with no college — plus programs whose mapped college differs from Banner’s Translated College (pre-majors’ differences marked expected). Any table may be NULL; the checked attribute says which kinds ran. Fails loudly on a missing column
summarize_mapping_audit(audit) One log line; the transform prints it at the end of every run

College resolution lives with the files (R/lists/institution_files.R): resolve_program_colleges(program_code, college_code, files) (program → unit → college, with per-program and pre-major-target overrides), translate_source_college(values, files), college_value_is_known(values, files). unit_mapping_rows(unit_codes, files) lists the confirmed subject and program rows behind a unit, with names; the shared scope block unit_codes_scope() (R/modules/ui-helpers.R) renders it on Dept Trends, the Dept Dashboard and Headcount.

Registry accessors (R/lists/data_semantics.R): cedar_data_semantics(kind), cedar_semantic_notes(table, values, terms), cedar_semantic_caption(notes).

Cones — Single-Question Analyses (R/cones/)

grouped-student-paths.R: get_grouped_student_paths(students, population, groups, opt) returns safe group/campus/enrolled-term cells and course detail. Requires opt$data_edges; applies the population ceiling, settled edge and independent band/cell guards. The enrolled-term clock precedes campus scope.

features/degree-explorer.R: build_degree_roadmap_view(catalog, roadmaps, catalog_id, math_start, english_start, start_season = "fall") and build_population_course_paths(students, population, groups, opt, description) assemble typed payloads, including complete enumerated course alternatives and option-specific prerequisite citations. degree_roadmap_tile_detail(view, node_id) resolves one tile’s popup content (citation, conditions, alternatives) from that payload. format_degree_explorer_preview(view) formats semesters; plot_grouped_student_paths(paths) plots already-suppressed aggregates.

File Main function(s) Takes cohort? Purpose
course-planning-history.R get_course_planning_history(sections, students, subject_courses, edges) — Source-covered seasonal frequency, seats and first-class-day seat pressure; retains delivery campus, college and session
bottleneck.R get_bottlenecks(cohort, students, opt) ✓ Waitlist pressure / unmet enrollment demand
stopout.R get_stopout(students, cohort, opt) ✓ Stop-out rate gap after DFW vs. passing
pathway.R get_course_timing(students, cohort, opt, students_full, term_credits) ✓ When population students take each course. The cohort parameter name is legacy; pass the build_population() output. opt$x_axis picks the axis; opt$subject_course restricts to an explicit course list; opt$group_campus = FALSE drops campus from the key (trajectory questions only — see the campus-policy exceptions above)
  plot_curriculum_map(timing_data, opt) — Heatmap of course timing
  get_course_pairs(students, cohort, opt) ✓ Ordered A→B course sequences
course-sequence-effect.R get_course_sequence_effect(students, programs, applicants, opt, term_credits, data_edges) — Observational: do students who took X before Y earn better grades in Y? Treatment/control via build_comparison(); Y is capped at the longitudinal grade edge
course-instructor-effect.R get_instructor_effect(students, programs, applicants, opt, term_credits, data_edges) — Descriptive downstream progression and outcomes by upstream instructor. Caps Y at the longitudinal grade edge, excludes right-censored X cohorts and strict-prior Y completers from the single-course continuation denominator, classifies grades canonically, and returns eligibility/unobserved-outcome audit counts for the UI. Outcomes attribute a student once to their first X instructor; course-order totals are instructor-neutral and aggregated by year. The balance diagnostic is optional context for comparing only the two largest instructor groups: it does not define, sample, match, or adjust the descriptive rates and belongs after those results in the UI
course-neighbors.R plot_course_sankey_by_term_with_flow_counts(to_courses, from_courses, opt) — Sankey diagram of before/after course flows
  plot_concurrent_course_treemap(concurrent_courses, opt) — Treemap of the most common same-campus, same-term companion courses
  get_gen_ed_planning_options(sections, history, gen_ed, season, slot_credits) — Latest matching-season lower-level Gen Ed examples, preserving campus/college/session, first-day suppression, source coverage and scheduled credit metadata
seatfinder.R seatfinder(students, courses, cedar_faculty, opt) — Seat availability analysis across terms; returns named list of course comparison tibbles
waitlist.R inspect_waitlist(students, opt, sections = NULL, enrl_base = NULL) — Waitlist counts by course/major; sections only needed if students lack course_title; enrl_base is the app’s precomputed cedar_cl_enrls_base (recomputed, scoped, when NULL)
course-outcomes.R get_course_outcomes(students, cedar_faculty, opt) — Returns named list: dfw_trend (DFW rate by term), instructor_dfw (per-instructor vs. course avg). cedar_faculty is optional; omitting it skips instructor breakdown
  get_course_persistence(students, degrees, opt, context = NULL) — Course Dynamics → Retention’s outcome table: selects the course’s rows in scope, then next_term_persistence()
  next_term_persistence(filtered, all_students, degrees, opt, context = NULL) — By outcome (pass, fail, late drop, early drop), share who returned next fall/spring. “Returned” is retention’s definition (registered or graduated), computed by .compute_retention(); pass the retention trend’s build_retention_context() to share it. Degrees are required
population-trend.R make_population_trend(programs, opt) — Entry type distribution over time
major-changes.R detect_major_changes(programs, cohort, opt) — moved to R/branches/major-change-detection.R ✓ Detect term-over-term major changes
  tag_major_changers(programs, cohort, opt) ✓ Boolean flag per student: ever changed?
  time_to_first_change(programs, cohort, opt) ✓ Terms from first enrollment to first change
  avg_credits_before_major(changes, opt) — Avg credits when arriving in each major
  majors_moved_out_of(changes, opt) — Most-departed majors by frequency
  major_change_pathways(changes, opt) — Common A→B transition pairs
  pathways_by_college(changes, opt) — A→B pathways broken out by college
  get_major_change_courses(changes, students, opt) — Courses taken during change terms
  get_pre_change_courses(changes, students, population, opt) — Courses taken in prev_term — the last term on the old major, before the switch posts — each reported against the course’s ordinary rate in the population. Returns a named list (courses, n_switches, n_switches_with_courses, n_students, n_baseline_terms). The two shares have different denominators: pct_before_switch is per switch; pct_other_terms is per student-term over the whole population (stayers included) minus switch-adjacent pairs. Pass the full analysis population — restricting it to changers silently converts the baseline into a within-person comparison. The baseline column is not optional garnish: on raw counts alone the table ranks the largest required courses for every population and reads as a finding
course-retention.R get_retention_comparison(students, opt, degrees) — Descriptive next-term retention rates compared across courses (raw rates, not treatment/control)
  get_retention_trend(students, opt, degrees) — One course’s retention rate over time
  get_dept_retention_trend(students, opt, degrees) — Dept-level retention trend
course-demographics.R get_course_demographics(students, opt), get_course_major_mix(students, programs, opt) — Major/classification breakdown per course; program mix of a course scope (opt$major_code_to_name optionally names enrollment-row codes with no program record)
sfr.R get_perm_faculty_count(cedar_faculty), get_sfr(programs, faculty), get_sfr_data_for_dept_report(programs, faculty, opt) — Permanent faculty FTE by dept; student–faculty ratios, college-wide and for one department (opt$dept_code, required). No app surface reads it today (see source-to-cedar-manifest.md §5)
cancellations.R get_cancellations(sections, opt) — Cancelled sections (section status “C”) plus summary tables for Explore > Cancellations; related non-active statuses counted separately for context
gen-ed-grads.R get_gen_ed_grad_cohort(students, degrees, opt) — Graduates of a department whose ENTIRE UNM record sits inside the data window (first enrolled after the data begins, awarded degree before it ends). Deliberately a small sample — read the block comment at the top of the file before using it
  get_gen_ed_grad_uptake(students, cohort, gen_ed_lu, opt) ✓ Share of that cohort taking each Gen Ed course, plus per-graduate course/area counts. Averages divide by the whole cohort, so a graduate with no recorded Gen Ed is a zero, not an omission. Also returns summary_dept — the same figures restricted to Gen Ed the graduates’ own unit teaches, plus dept_share_pct
gen-ed-conversion.R get_gen_ed_conversion(students, programs, opt) — Sankey flows from a student’s program at the time of a gen-ed course to their last recorded program (graduated / stopped-out labeled); flows below opt$min_n collapsed into “Other”
  get_course_major_associations(students, programs, opt) — Course → eventual-major association table
data-integrity.R check_student_id_integrity(spine, tables, opt) — Can the stored tables actually be joined on student_id? Compares each table term-by-term against a spine (pass cedar_students) and returns by_term, by_table, spine, n_tables_split. A term with records and exactly zero matches is the signature of a hash mismatch at ingest; a table covering a wider population sits partway in every term and never at zero, so only a mixture of zero-match and full-match terms is reported as "split". Surfaced in Data & Usage → Join Integrity. Read ISSUES.md I1 before interpreting a split verdict

Features — App-Facing Orchestrators (R/features/)

The offline shared-reference workflow uses branches/shared-requirements.R: read_shared_requirement_bundle(directory, source_directory = NULL) validates annual scoped rule files and optionally their original captured evidence; shared_requirement_nodes() preserves nested alternatives and inherited citations for display. Its feature companion exposes format_shared_requirement_preview(reference) and capture_shared_requirement_sources(reference, directory, fetch). These are reference/candidate artifacts, not runtime scheduling or student audits.

Offline catalog acquisition/review also uses this orchestration layer: catalog-capture.R exposes capture_degree_catalog(source, credentials, fields, directory, catalog_id = NULL, include_courses = TRUE, resume = FALSE, fetch = fetch_public_source, pause = 0.1) and verified catalog_capture_manifest(directory, require_complete = TRUE, verify_sources = TRUE). catalog-analysis.R exposes analyze_degree_catalog(directory, output) and compare_degree_catalog_scans(before, after, output) and verified read_catalog_analysis(path, read_sections = TRUE). These produce/read unreviewed artifacts, never runtime requirement or planning edits. catalog-review.R exposes list_catalog_review_scans(root), catalog_review_cache_key(root, scan_id), load_catalog_review(root, scan_id) and catalog_review_detail(payload, item_id). These discover local archives and retrieve full source fields through verified receipts and JSON pointers, including embedded concentrations. Review artifacts are verified before cache lookup; original source blobs are verified on Inspect. The read-only catalogReviewUI(id, catalog, roadmaps) / catalogReviewServer(id, root, active, catalog, roadmaps, review_root, shared) module mounts under Admin > Data & Usage. It defaults to degreePlanRulesUI/Server(id, catalog, roadmaps), using build_degree_plan_rules(catalog, roadmaps, view) for the actual graph. Optional catalogNormalizationUI(id) / catalogNormalizationServer(id, root, capture_root, active, draft_dir) is under Draft interpretations; legacy extraction diagnostics remain lazy. features/catalog-normalization.R provides prepare_catalog_normalization(payload, program_id, root, prompt, schema), load_catalog_normalization_program(root, key), import_catalog_normalization(root, unit, path, model), read_catalog_normalization_review(root, unit, imported), save_catalog_normalization_review(root, unit, imported, state, reviewer, expected_head), stage_catalog_normalization_drafts(root, directory, capture_root) and export_catalog_normalization(program, unit, imported, state). Source-bound packets, original AI responses and attributed review revisions are separate files; no model calls or runtime compilation. See catalog-normalization.md.

features/degree-explorer.R: build_degree_course_history() resolves exact tile components and assembles one typed popup table without guessing historical equivalences. build_degree_popup_history(sections, students, edges, catalog, roadmaps, gen_ed, selection) validates allowance selections and assembles seasonal Gen Ed examples; format_degree_allowance_preview(history) is its canonical aggregate text preview.

Features call multiple branches/cones and assemble payloads for visible app surfaces. They follow different rules than cones: they may call other cones. They do not contain Shiny UI/server wiring; that lives in R/modules/ or, for older surfaces not yet modularized, server.R.

File Main function(s) Purpose
admin.R build_admin_data_status(summary, current_term) Tiny freshness-table payload built only from the precomputed startup summary; never scans institutional tables
  build_mapping_worklist(files, programs, issues, audit, source_departments) Admin > Mappings decisions, each row with a group (programs, subjects, colleges) for its tab and a name that is only ever the code’s own name
  build_mapping_reference_tables(files) The mapping files as code-to-department tables with names: programs, subjects, units, colleges; every confirmed row
  build_counting_rules(files, programs, sections, students) The rules that place or drop rows without a file row, with what each touches in the loaded tables and where it is coded
  build_campus_reference(sections, students) Every campus code (those the institution’s campuses.csv defines plus any the data adds) with its group, default scope, and where it is counted
course-report.R create_course_base_data(data_objects, opt), compute_cr_flows_tab(), compute_cr_outcomes_tab(), prepare_downstream_outcomes_display(), prepare_course_snapshot_tables() Assembles enrollment and rollcall data for the Course Dynamics tab; flows/outcomes computed lazily per sub-tab. The snapshot adapter returns formatted table specs, one per campus, for cedar_snapshot_table() (R/modules/ui-helpers.R). The downstream display helper keeps the full analytical audit intact while presenting one sortable % (count) column per outcome and omitting instructor-level censoring/course-order fields already summarized above the table
gen-ed.R get_gen_ed_profile(students, sections, programs, degrees, opt) Gen Ed profile (scope filtering, outcome rates, grade distribution, major mix) for Explore > Gen Ed and the Dept Trends Gen Ed panel
  get_gen_ed_grad_profile(students, degrees, term_credits, opt) Gen Ed consumed by a department’s own graduates — cohort meta, a get_course_timing() heatmap on the unm_credit_band axis, and the uptake table — for the graduate sections of Dept Trends > Gen Ed. The rest of that subtab measures the department as a Gen Ed provider; this one flips the population, which is why it needs the strict cohort
    Returns the three views twice: timing/by_course/summary over all Gen Ed, and timing_dept/by_course_dept/summary_dept over the unit’s own. Both scopes are cut from one get_course_timing() run, not computed twice — n_eligible is built before that function applies its course filter, so narrowing the course list only removes rows and the two heatmaps stay comparable cell for cell. Pinned by a test in test-gen-ed-grads.R
dept-dashboard.R create_dept_dashboard_data(...) Dashboard metrics and plots for one dept (assembles headcount, enrl, credit-hour trends); dashboard_headcount_scope_facts() gives the headcount cards’ scope facts
  get_subject_current_stats(sections, subject, term) Lightweight current-term snapshot: returns list(n_sections, total_enrl) for a subject, crosslist-deduplicated. No full dashboard pipeline. Reusable in dashboard cards, comparison views, and RStudio analyses.
dept-trends.R create_dept_report_base(data_objects, opt), the compute_dept_*_tab() orchestrators, and matching rebuild_*() helpers Assembles the active Dept Trends web profile and reconstructs charts from cached analytical tables
regstats.R get_reg_stats(students, courses, opt) Enrollment anomaly detection (calls enrl, course-demographics, waitlist branches)
  filter_downstream_by_dept(downstream_df, dept, sections) Filters downstream registration signals (dest_course pairs) to only destinations in a given dept’s subjects. Pass empty/NULL dept to return all rows unchanged. Eliminates a DRY violation — was duplicated in two server.R render blocks. Reusable in any downstream signals display.
enrollment-projections.R build_enrollment_projection_bundle(...), build_enrollment_projection_view(bundle, opt) Builds and reads the published projection artifact. Spring and Fall targets only; Summer is refused
  find_enrollment_projection_bundles(output_dir) Every saved bundle as one row per target term, with its season. The season-aware replacement for “the highest saved target term”
  load_latest_enrollment_projection_bundle(output_dir, term_type), load_enrollment_projection_bundle(output_dir, target_term) Read one bundle. term_type has no default: a caller that does not name a season would silently switch seasons when the other one publishes
  format_enrollment_projection_preview(bundle, courses) Committed text formatter over the payload; the UI and tests read the typed payload, never this text
enrollment-projection-refresh.R resolve_enrollment_projection_refresh(config, students) Resolves the morning policy into one scope per target, nearest first. Returns a list, not a single scope
  enrollment_projection_model_drift(output_dir, base_dir) Deploy-time gate. Checks every saved season’s bundle against the deployed model source; loads no CEDAR table
enrollment-projection-scenario.R build_enrollment_projection_scenario(bundle, programs, opt) Grows one named population and reads the effect on published course demand. Arithmetic over saved rows only — year 1 is the published projection at any growth rate, later years are labeled Scenario and carry no accuracy axes
  format_enrollment_projection_scenario_preview(scenario, measure) Text preview over the scenario payload; measure is students, sections, or additional

Trunk Helpers — full function tables

Moved from AGENTS.md. Always check these before writing equivalent logic in a cone or branch.

R/trunk/source-snapshots.R: fetch_public_source(url) performs explicit HTTPS acquisition; capture_public_source(url, directory, kind, key, fetch, document_format) saves immutable decoded bytes and a receipt; read_captured_source(receipt, directory, json = TRUE) verifies hashes before reading. source_json_pointer(document, pointer) resolves exact saved fields, including embedded array records. source_sha256(), source_json_bytes(), write_source_json() and read_source_json() supply the shared content-hash/JSON infrastructure.

R/trunk/utils.R

Function Purpose
add_next_term_col(df, term_col, summer=FALSE) Adds next_term column; required by get_stopout()
add_prev_term_col(df, term_col, summer=FALSE) Adds prev_term column
add_acad_year(df, term_col) Adds acad_year like "2024-2025"
add_term_type_col(df, term_col) Adds term_type: "spring", "fall", "summer"
add_term_bins(df, term_col) Groups terms into bins for trend analysis
term_diff(from, to, include_summer=FALSE) Number of terms between two term codes
fmt_term(term_code) 202580 → "Fall 2025"
term_code_to_str(term_code) Alternate term label formatter
academic_period_to_term(label) "Fall 2025" → 202580
make_term_sequence(start_year, end_year) Vector of term codes for a year range
course_level_from_number(subject_course) The one course-level rule (lower/upper/grad) for both transforms: leading digit of the course number via COURSE_LEVEL_BY_LEADING_DIGIT (institution/<id>/course_levels.csv), for 3- and 4-digit numbers alike. Defined in R/lists/course_numbering.R beside its lookup, so the Degree Explorer catalog validators can use it at load time
mark_plotly_terms(p, term_labels, text) Shades and labels given term categories on a plotly term axis; returns charts without those terms unchanged, so it can be applied to every chart on a page
get_dept_from_course(course) "BIOL 2310" → "BIOL"
validate_population(population, caller) Validates population has required columns; call at top of any cone that accepts a population argument
term_diff(from, to, include_summer) Count terms between two term codes (YYYYSS integers)
compute_trend(values, min_n=2, threshold=0) Canonical slope/direction helper: returns list(slope, direction, arrow) for an oldest→newest numeric vector (NAs dropped). Use instead of hand-rolling coef(lm(v ~ seq_along(v))). Note a perfectly flat series needs a small threshold to read as "stable" rather than float-noise up/down.
compute_windowed_trend(series, all_main_terms, top_n_terms) Computes recent_avg, pct_1yr/2yr/4yr, abs_change_1yr, is_emerging for a single time series (a tibble with term and value cols). Use with group_modify for per-course trend indicators — e.g. enrollment trend for each course in cedar_cl_enrls_base. Already used by credit-hours.R. Do not use with group_modify over course pairs (source→dest): thousands of groups × R closure overhead = multi-minute hang. For course-pair trends, use vectorized group_by + summarize instead.

R/trunk/filter.R

Function Purpose
filter_DESRs(sections, opt) Standard filter for cedar_sections (campus, college, dept, term, level, etc.)
filter_class_list(students, opt) Standard filter for cedar_students
filter_by_col(data, col, val) Generic single-column filter
filter_by_term(data, term, term_col) Filter to specific term(s)
filter_out_summer(data, term_col) Remove summer terms
filter_data(df, opt, opt_col_map) General-purpose opt-driven filter
keep_home_sections(sections) Crosslist de-dup: keep each group’s home/internal section + all non-crosslisted rows, so a course counts once. Use instead of inlining is.na(crosslist_group) \| crosslist_role %in% c("home","internal").

filter_class_list() handles the common pattern of filtering cedar_students by campus, dept, term, level, registration status, etc. Use it rather than reimplementing in cones.

branches/shared-requirements.R: degree_shared_coverage(view, roadmaps, reference) computes illustrative course/area allocation from explicit parameters; allocate_shared_degree_slots(view, coverage) earmarks existing workload without adding credits. features/degree-explorer.R loads the annual bundle at startup and assembles cards/rules/popups from that same coverage. Elective examples can include upper-level courses; prerequisites are not inferred from section history.


Back to top

CEDAR is open source software for higher education analytics.