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.