Skip to content

Ask about a fee waiver a month out, not on submit day - #56

Merged
DanialBeg merged 1 commit into
mainfrom
feat/fee-waiver-lead-time
Oct 1, 2026
Merged

DanialBeg merged 1 commit into
mainfrom
feat/fee-waiver-lead-time

Conversation

@DanialBeg

Copy link
Copy Markdown
Member

"people might need to start working on submitting fee waivers a month or so before their application"

Right, and the checklist was actively working against that.

The problem

One task carried both jobs:

Pay the application fee (or apply for a waiver) — Submit phase

Paying belongs at submit. Asking does not. The request goes through the counselor, who is confirming eligibility for a whole cohort through October and November, and a student who reaches that task on the day they submit has already missed it.

What I found in the data

I pulled the fee columns out of the Common App requirements grid (the same PDF behind the deadline ingest — it carries US fee, Int'l fee and fee waiver alongside the dates I already parse):

Schools with a fee listed 1,128
Charging $0 to apply 611 (54%)
Median fee $0
90th percentile $70
Highest $150
Fee waiver Accepted 541
U.S. only 90
Not accepted 29

Two things follow. More than half of schools charge nothing, so a waiver step on every school is noise. And where a fee does exist, waivers are near-universally accepted — so the question is never whether, only in time.

The change

Two tasks. "Ask your counselor about a fee waiver" in Before you apply; "Pay the application fee, if one is owed" at Submit.

The date box opens on a month before that school's deadline rather than on nothing, with the reason beside it (ask ~30 days ahead). Nothing is written until the student saves it — it is a starting point, not a decision made for them.

It is one request, not one per school. A granted Common App waiver applies at every Common App school on the list, so it joins recommendations, the transcript and the CSS Profile as a shared task. Paying stays per school — which is what the old comment was right about, and precisely why the two had to come apart.

Community colleges and trade schools do not get it, per the data above.

The migration this needed

A saved checklist is now topped up with any default task it lacks. Default tasks cannot be deleted — only custom ones can — so a list without one was simply saved before that task existed. Without this, only students adding a school from today would ever see the waiver step, and everyone with an existing list would be left on the old combined task forever.

That is read-repair rather than a one-off script: the list shown is always the complete default set, and it persists the next time anything writes.

Not done

Per-school fee amounts are not stored. The grid has them and the research above reads them, but putting $0 / $85 / "waiver accepted" on each college needs a migration, a parser extension and an ingest run. Worth doing — "this school is free to apply to" is a genuinely useful thing to show, and it would let the waiver task appear only where a fee actually exists — but it is its own change, not this one.

Testing

522 passing, lint and typecheck clean, build succeeds. New coverage: the phase split, that the waiver is shared and the fee is not, that two-year schools are skipped, that the 30-day count-back crosses a month boundary correctly, and that an old saved list gets topped up while a complete one is returned untouched.

One task carried both jobs: "Pay the application fee (or apply for a waiver)",
in the Submit phase. The paying belongs there. The asking does not — the
request goes through the counselor, who is confirming eligibility for a whole
cohort through October and November, and a student who reaches it on the day
they submit has already missed it.

They are two tasks now. "Ask your counselor about a fee waiver" sits in Before
you apply, and its date box opens on a month before that school's deadline
rather than on nothing, with the reason next to it. Nothing is written until
the student saves it.

The waiver is also one request, not one per school: a granted Common App
waiver applies at every Common App school on the list, so it joins
recommendations, the transcript and the CSS Profile as a shared task. Paying
stays per school, which is what the old comment was right about and why the
two had to come apart.

Community colleges and trade schools do not get it. Reading the fee column of
the Common App grid, 611 of its 1,128 schools charge nothing to apply at all,
and two-year schools are overwhelmingly among them; a step about waiving a fee
that does not exist is noise on the one list that should be shortest.

A saved checklist is now topped up with any default task it lacks. Default
tasks cannot be deleted — only custom ones can — so a list without one was
saved before that task existed, and without this only students who add a
school from today would ever see the waiver step.
@vercel

vercel Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
webapp Ready Ready Preview Oct 1, 2026 6:10am UTC

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying timeline-prototype with  Cloudflare Pages  Cloudflare Pages

Latest commit: 984d574
Status: ✅  Deploy successful!
Preview URL: https://f9cf6bed.timeline-prototype.pages.dev
Branch Preview URL: https://feat-fee-waiver-lead-time.timeline-prototype.pages.dev

View logs

@DanialBeg
DanialBeg merged commit 0b17ca1 into main Oct 1, 2026
5 checks passed
@DanialBeg
DanialBeg deleted the feat/fee-waiver-lead-time branch October 1, 2026 20:37
@ZubairQazi

Copy link
Copy Markdown
Collaborator

Heads-up: this conflicts with #58 in tasksForEntry (web/src/data/applicationTasks.ts). Both PRs top up saved task lists with new default tasks.

Suggested combined version for whichever merges second:

Happy to do the merge on whichever side lands second.

@DanialBeg

Copy link
Copy Markdown
Member Author

Good catch, and the status half was already live — thanks.

I'd merged #56 (and #57 on top) before this landed, so I verified it on main: a submitted school with every task ticked read 10 of 11, with an unticked "Ask your counselor about a fee waiver" for an application already sent. Worse than a wrong count — it's an instruction that makes no sense.

Fixed in #59, which is just the isActive guard you described.

On the merge: since #56/#57 landed first, #58 is the one that merges second. I've tried to make that easier rather than harder — the status guard is now on main, so what's left is your two additions, the aid-task label refresh and the WeakMap cache, neither of which has an equivalent on my side.

I deliberately didn't pull your cache across. Doing so would have left you merging against a half-copy of your own work, which is worse than merging against a clean one. The top-up loop is otherwise unchanged: any missing default task, each spliced into its own phase.

One thing to know when you rebase — #57 added applicationFeeCents to ApplicationEntry and the waiver task is now gated on it rather than on school type, so defaultTasksFor has a chargesAFee(app) branch your aid-app push will sit next to.

ZubairQazi added a commit that referenced this pull request Oct 2, 2026
Merges #56, #57 and #59. tasksForEntry keeps main's version (any missing
default task, in its own phase, only while the application is still being
worked on) and adds the aid task's label refresh and the per-entry cache.

From review on #58: the aid-application task now goes to any school with
a guarantee, not just four-year ones, so Ohio State's regional campuses and
Emory's Oxford College get the task that wins theirs. The guarantee copy is
compared field by field rather than as JSON, which depended on key order.

This branch was successfully deployed

1 active deployment
Preview — 984d574f Deployed Oct 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants