IEP.software · Module-dark by default · live the day a district turns it on

Special education, run on refusals that hold, not a form that gets filled in.

The established IEP platforms are, at their core, a document generator wrapped around a spreadsheet: fill in the fields, print the form, watch a due-date column turn red. That trade genuinely works for a lot of districts. But a due-date column is a fact someone typed in, an access list is a role someone checked, and a service-minute total is whatever the last person who touched the spreadsheet believed. None of those are enforced by anything.

This is the enforcement. A deadline that re-derives itself from an immutable ledger of the events that actually happened, and refuses to be confident about a state whose rule nobody has confirmed. A team wall that denies a masthead title by construction, because we found the exact case where it did not and fixed it, on a dated line. A service-minute read that structurally cannot call zero minutes delivered “compliant.” A Medicaid claim that is un-writable, at the database itself, without a real parent’s real consent on file.

And it does not pretend to be more than that. It does not render your state’s form. It does not write your procedural-safeguards notice. It does not touch a team’s own decision with anything resembling AI. Those refusals are on the first screen, not the footnotes.

12engines called by a registered handler today — plan authoring, goals, progress, service minutes, the deadline clock, meeting notice, consent, 504, Prior Written Notice, Medicaid consent, and manifestation determination
7modules that are written and tested with no production caller, or one real access-control limitation — each named on this page by name rather than counted as a feature
0team-decision fields ever touched by AI. Eligibility, placement, a goal’s mastery verdict, and a meeting’s consent disposition are stored inputs, never generated
402test cases measured across the 26 files touching this domain by grepping every it()/test() block — a source-level count, not a curated highlight reel

The honest frame

What this is, and what it is not.

Special-education software is one of the categories where a confident-but-wrong answer is worse than an honest refusal. A due date that is wrong by three days is a finding in an OIG audit and a real child whose services lapsed while a spreadsheet said everything was fine. So this product was built the same way our other domain-specific engines are: the refusal comes before the feature.

It is an access-control, clock, and consent layer over the plan a team writes. The goal statement, the eligibility determination, the placement, the disability category, the present-levels narrative — every one of those is authored by a human team and carried through this system verbatim. There is no AI wiring anywhere in this domain that touches a team-decision field, and there will not be one added quietly.

It is not a form-filling service. It does not render a specific state’s IEP or 504 form layout, and it will not until a subject-matter expert signs off on that state’s rule — the form-rendering endpoint returns an honest descriptor saying exactly that rather than a plausible-looking but unvalidated document.

It is not a legal-services product. It does not write your procedural-safeguards notice. It does not give legal advice about a manifestation determination or an eligibility call — those surfaces are marked needs-counsel in their own return values, in those words.

It is not a Medicaid billing service. It proves whether a claim line could be billable given a real consent chain, and it prepares — never submits — a batch. Nothing here transmits to a state Medicaid agency.

And it is module-dark, not a promise. The code above is wired, tested, and hardened against a real defect we found and fixed. A district that has not turned the module on sees no difference from today; turning it on activates real code, not a mockup.

Built and reachable — a registered handler calls it

The engines that are actually wired.

Each of these is called by a registered API handler, module-dark behind a per-tenant flag. One honest bound on the whole section: reachable is a source-level claim. It means a handler calls the function. It does not mean every branch has been exercised against a live district’s data, and where a surface’s final access wall is not yet fully wired, the card says so.

Plan authoring & lifecycle

IEP and 504 plan authoring — Draft, Review, Final, Amending, Archived, and Final is edit-locked

A plan moves through a five-state machine and only the moves the regulation actually allows are legal: draft to review, review to final, final can open an amendment or archive, amending closes back to final. Every other move is rejected outright, not merely discouraged. Once a plan is Final its content is edit-locked; a real change happens through the amendment path, never a silent overwrite. Section 504 is not a stripped-down cousin of the IEP — it is a first-class sibling plan type sharing the same state machine, with its own finalize gate (an IEP needs the 34 CFR 300.320 schema complete; a 504 needs its own accommodation set). The fields a team decides — eligibility, placement, least-restrictive-environment — are carried through every update verbatim. The system never computes or overwrites a team’s own determination.

sch-iep-504.ts, iep-plan-lifecycle.ts Persisted. Every transition is re-checked against the legal transition table before the write.

Measurable annual goals

Structured goals, not a text box — and the system never marks one met

A goal is authored with a controlled goal area — academic, behavioral, communication, social-emotional, functional, motor, adaptive, transition, the 34 CFR 300.320(a)(2) vocabulary — a statement, and an optional baseline. It starts in draft. The type this compiles to structurally cannot represent the system setting a goal to met or not_met: that verdict is a stored team act, never derived. This writer shipped ready with its migration and then sat unwritten for a full release — the table existed, the pure function existed, and nothing called it. It is now wired to a route and persisted for real.

sch-iep-504.ts (addGoal) Persisted. A dead-to-live writer: the table had no caller until this shipped it one.

IEP team roster

The team roster, with a case-manager singleton the write itself enforces

A team member is added with a closed role — case manager, sped teacher, general teacher, school admin, parent/guardian, related-service provider, student, district rep, other, the 34 CFR 300.321(a) roster vocabulary — and the write enforces exactly one active case manager per plan inside a single transaction, so a race can never leave a plan with two or with zero. Rolling a member off is soft: the row is marked inactive, never deleted, because the row is itself part of the IDEA-required roster record. This is a second dead-to-live writer — the table shipped with its migration and had no writer at all until this.

sch-iep-504.ts (addTeamMember) Persisted. The read gate that will trust this roster is a separate, not-yet-flipped step — see below.

Goal progress monitoring

A trend for a human to read, from a type that cannot say “mastered”

Every progress data point — an observation, a probe, a work sample, a formal assessment, a rubric score, a frequency count — is recorded against a goal with a method and a date. From a run of points the system computes a direction: improving, regressing, flat, or insufficient data. “Mastered” is not a value that return type can hold, which is a structural fact rather than a policy someone has to remember to enforce — the function that reads the points cannot return a mastery verdict because that word is absent from its type. Mastery stays exactly where IDEA puts it: a team decision, recorded by the team, on the goal itself.

sch-iep-goal-progress.ts (goalProgressTrend) Advisory only. Never mutates the goal it describes.

Service-minute delivery log

Delivered vs. mandated minutes — and zero delivered is never read as clean

Speech-language, occupational therapy, physical therapy, counseling, psychological services, social work, specialized instruction, behavioral support, assistive technology, orientation and mobility, or another related service is logged with a date, minutes delivered, and minutes mandated. The read this produces is a discriminated union on purpose: a caller can only reach a compliant/non-compliant verdict after first narrowing on whether a real mandate basis existed at all. A child who received zero minutes of a mandated service produces zero log rows, and zero rows is exactly the state the union refuses to grade as clean. Absence of data is never evidence of compliance.

sch-iep-goal-progress.ts (logService, serviceDeliveryGap) Advisory surface over a persisted log. The gap is reported, never auto-remediated.

The IDEA deadline clock

A compliance clock re-derived from an event ledger, not a date someone typed into a field

The federal defaults are the floor: sixty calendar days from consent to complete an initial evaluation, thirty days from an eligibility determination to a finalized IEP, an annual review at most 365 days out, a triennial reevaluation at most three years out. Many states override that floor materially — DC uses 120 days; several states count in school days rather than calendar days; California excludes any vacation of five or more days from the count. The engine encodes that variance as a state-rule table rather than as branching code, and resolves the rule for the student’s SEA. A deadline is a re-derived projection of an append-only event ledger — consent received, eligibility determined, IEP finalized — so it can never go stale the way a hand-maintained spreadsheet date can, and every deadline carries the provenance of the exact ledger event it was computed from.

iep-deadline-engine.ts (resolvePlanDeadlines) A state whose rule is unconfirmed resolves provisional, not a confident date. Default-deny, never a guess.

Meeting notice & team completeness

Parent notice early enough to attend, and a checklist for who has to be in the room

The deadline clock answers by when an obligation must be met. This answers the two things that actually satisfy it: the parent notice that has to precede the meeting (34 CFR 300.322), and the required team membership that has to attend it (34 CFR 300.321). It consumes the deadline engine’s output as a type — it does not recompute the clock — and proposes a scheduling window, then separately reports which required roles are missing from a proposed roster. It never rules on an excusal; a 300.321(e) excusal needs the parent’s and the LEA’s written agreement, a human decision this module does not make. IDEA fixes no notice-day count, so the roughly-ten-day default returns marked, in the value itself, as provisional district practice, not a confirmed legal number.

iep-meeting-scheduling.ts A completeness checklist, not a legal determination.

Section 504 accommodation authoring

Four accommodation buckets, and a review cadence marked honestly provisional

A 504 plan’s accommodations sort into the four buckets the category actually uses — presentation, response, setting, timing and scheduling — rather than one flat list nothing can group or validate. On top sits a periodic review scheduler mirroring the same default-deny posture as the deadline engine: the commonly cited annual-review and three-year-reevaluation cadence is district and SEA policy, not one hard federal day count, so every date this produces is marked provisional pending a signer, never presented as a confirmed deadline. It composes the existing plan finalize gate rather than re-implementing it — one lifecycle rule, shared by both plan types.

plan-504-accommodation-authoring.ts Structural validation only. The cadence needs district/SEA sign-off before it is a real deadline.

Prior Written Notice

The 300.503 notice, assembled — with the legal boilerplate left honestly blank

Before an LEA proposes or refuses to change a child’s identification, evaluation, placement, or FAPE, IDEA requires written notice within a reasonable time (34 CFR 300.503). The composer assembles the notice from the plan’s own authored facts and refuses to produce a document at all when a required element is missing — it returns no document, never a document with a hole in it. One element it will never write for you: the statement of procedural-safeguards protections and how to obtain a copy, which is state and counsel-mandated legal language. That field ships as an explicit, named honest-off marker rather than invented text, because a fabricated paragraph of legal boilerplate is worse than an obviously blank one.

iep-pwn-compose.ts Honest-off on the one field that is legal text, by design, not by omission.

Manifestation determination

Discipline meets disability — flagged, never decided, by the system

When a disciplinary removal crosses the change-of-placement threshold — more than ten cumulative school days, or a pattern (34 CFR 300.530) — a manifestation determination review is required within ten school days. This surface detects that condition from the discipline record and confirms, against the student’s actual plan, that an MDR applies, then only flags it. The team’s own determination — was the behavior a manifestation of the disability, or the result of a failure to implement the IEP — is recorded verbatim, gated to an administrator, and marked needs-counsel in its own return value. It is wired directly into the discipline-incident routes, with its own read and record endpoints.

manifestation-determination.ts (apps/api domain), routes/behavior.ts Advisory detection + verbatim recording. No verdict is ever computed by the system.

Built, not switched on

Seven things with no production caller, or one real limitation. Here they are by name.

This table is the part of the page we would remove if we were selling harder. It is here because the characteristic dishonesty of a technical product page is to describe a green test suite as a working feature, and this codebase has seven places where that temptation exists. Six are modules: written, covered by tests, and imported by nothing outside their own siblings and their own test files. The seventh is not a module at all — it is a real, current gap in how far the team-authorization wall reaches, and we would rather name it precisely than let a district discover it.

WhatWhat it doesWhy it is not reachable, or not yet trusted
Medicaid per-encounter claim computeComputes a per-encounter Medicaid-reimbursable figure in exact integer cents from a unit count, a supplied rate, and the IEP-authorized unit ceiling, holding every encounter lacking consent at zero.No apps/api route imports it. The consent-as-constraint gate is wired and governs whether a claim can exist at all; this module would compute the dollar figure of one, and nothing calls it yet.
Medicaid claim-log-to-batch pipelineDerives claim candidates from a service log, assembles a batch partitioned into billable and blocked lines through the existing consent constraint, and produces an honest-off “prepared, not submitted” plan — there is deliberately no submit function anywhere in it.Its only caller, a related-service-provider caseload module, is itself not registered as a route in app.ts. Two unwired layers deep.
IDEA excess-cost minimum-average-amountThe 34 CFR 300.16 fiscal primitive: given total expenditures, the four allowed deductions, average daily membership, and the count of children with disabilities, computes the per-child minimum-average-amount floor and the aggregate excess-cost floor, with the division reconciling to the cent.No production caller. A correct fiscal calculator with nowhere to surface a result.
Compliance-ops deadline & shortfall summaryA policy layer meant to feed a state extract: on-time / late / due-soon / overdue deadline status, and a service-minute shortfall summary.Exported through the shared package’s surfaces barrel and nowhere else. No apps/api route imports it — the deadline clock and the service log above are the surfaces actually wired, and neither is this module.
The special-ed-read compliance resolverA second review-status resolver (current / due-soon / overdue / unknown) and a second team-based read gate, built to the same fail-closed standard as the ones actually wired.Not imported by the special-education route. The route implements its own hand-rolled gate instead; its own comments say the two mirror each other, but mirroring is not calling. Two independently-written gates enforcing the same rule is a real risk if they are ever allowed to drift — today only one of them runs.
The shared-package manifestation layerA second manifestation-determination engine, gated by the same team-authorization wall as plan authoring.No production caller. The manifestation determination that is actually live in the discipline routes is a separate, apps/api-level module (see the engine grid above). This one is exercised only by its own test file.
Per-student team-based authorization (the flip)The access gate’s branch for a teacher on a specific student’s IEP team, distinct from an admin admitted by role alone.The code is real and does fire — it is invoked inside every goal, team, progress and service write today. But the route currently passes it a literal false for the team predicate, because per-student team membership had no writer at all until this shipped one. Flipping the route to resolve the predicate from the now-real roster is a separate, deliberate, not-yet-taken step, named here rather than left for someone to discover.

The compliance clock

A deadline is not a date field. It is a projection of what actually happened.

The failure mode this engine was built to close is specific: a dashboard where someone typed “annual review due 3/14” into a field, and the field is now the only record of when the clock actually started. If the typed date is wrong, or nobody updates it after an amendment, the dashboard is confidently, silently wrong — and a confidently wrong compliance dashboard is worse than none at all, because nobody double-checks a green light.

So the deadline here is never typed in directly. It is computed fresh, every time, from an append-only ledger of the events that actually happened — consent received, eligibility determined, IEP finalized — and the SEA’s confirmed rule for that particular obligation. Change the ledger (a real amendment, a real re-finalize) and the deadline changes with it, automatically, because it was never a stored fact to begin with. It was always a re-derivation.

The same obligation, five different clocksRule
Federal default (34 CFR 300.324(b)(1))Annual review, at most365 days
District of ColumbiaA confirmed state override120 days
A school-day-counting stateCalendar days are not the unit -- school days areschool days only
CaliforniaExcludes any vacation of 5+ days from the countexcludes breaks
An unconfirmed stateNo signed rule on file yetprovisional

Illustration. A product that hard-codes “365 days” is silently wrong for the District of Columbia, wrong for every school-day-counting state, and wrong for California the moment a vacation crosses the line. Encoding the rule as data, per SEA, is what lets the clock be right instead of averaged.

The state-rule table is the second half of the design, and it is the part that keeps this honest rather than merely correct-looking. IDEA sets a federal floor, and a real number of states override it materially — different day counts, different units (school days instead of calendar days), different exclusions. Hard-coding “365 days” would be silently wrong for a meaningful share of the country. So the rule is data, resolved per SEA, and a state whose rule has not been confirmed — or a school-day rule with no instructional calendar supplied — resolves provisional, not a confident date. The caller is told, explicitly, not to rely on it. That is the same default-deny discipline as the consent gate, applied to a calendar instead of a name.

Who may see it, and who was found able to

The wall, and the defect we found and fixed in it.

Disability records are the most sensitive student data on the platform, and the access rule is meant to be simple: the student’s own IEP team, plus the roster-of-record administration, plus the student’s own proven guardian. Nobody else. Here is what that resolves to today, case by case.

District / school adminAdmitted

Admitted by role — the roster-of-record administration overseeing sped compliance.

A proven guardian of this studentAdmitted

Server-resolved, read-only, matching 34 CFR 99.10 — never a client-supplied claim.

The case manager / assigned sped teacherDenied

The code path exists (canAuthorIep branch 3) but the team predicate is pinned false today — see below.

A general teacher, not on this student’s teamDenied

Denied even though they are an educator, and even with a staff tier.

A yearbook or newsroom masthead titleDenied

The exact defect found and fixed — a title unrelated to special education, previously admitted, now denied.

A rep (account_manager) sessionDenied

Hard-denied first, before any other branch runs. The lone FERPA-walled session on the platform.

A student, or a minor holding any staff titleDenied

Denied outright, regardless of any other role the same person holds.

We are not naming the fourth row above because it is theoretical. It was a real defect in this exact route, and it is dated: the access gate previously admitted anyone holding the adviser or co_adviser staffRole — the yearbook and newsroom masthead, a title that has nothing to do with special education — because that title happened to sit on the same coarse teacher role the gate was checking. A school’s yearbook adviser, on no student’s IEP team, could read and author any student’s disability category and present-levels narrative. It was closed to admin-tier plus a server-proven guardian of the specific student being read. A second, subtler ordering defect followed a few weeks later and is worth naming too: a minor-staffer wall that ran before the guardian check meant a teen parent — a real, if unusual, case — could be denied their own 34 CFR 99.10 right to inspect their own child’s plan, because the wall for minors caught them first. The guardian branch was reordered above it. Neither fix weakened the wall it sits inside; both are described here rather than only in a private changelog.

The row we are most exact about is the third: the case manager and assigned sped teacher are not yet admitted by team membership. The code path is real — it fires today, inside every goal write, every team write, every progress point, every service log entry — but the route currently passes it a literal false for “is this teacher on this specific student’s team,” because until this build shipped a writer for the team-membership table, there was no real roster to check against; a per-student team check would have resolved false for everyone, which is a worse failure than an honest, visible admin-tier floor. That writer now exists. Flipping the gate to trust it is a deliberate, separate, not-yet-taken step, and we are naming it here rather than letting a district assume it is already live.

Section 504, as its own plan — not a lesser IEP

Broader eligibility, no measurable-goals requirement, and its own accommodation grammar.

A 504 plan is often treated in practice as a thin cousin of the IEP: fewer fields, less software attention, the same lifecycle bolted on as an afterthought. Here it is a first-class sibling plan type from the schema up. It shares the same Draft-Review-Final-Amending-Archived state machine as the IEP — one lifecycle rule, not two copies that can drift — but it has its own finalize gate, because a 504 has no measurable-goals requirement the way an IEP does; it requires an eligibility basis and at least one accommodation instead.

Accommodations sort into the four buckets the category actually reasons in — presentation, response, setting, timing and scheduling — rather than a flat list of strings nothing can group or validate. And the review cadence carries the same honesty as the IEP deadline clock: the commonly cited annual-review and three-year-reevaluation intervals are district and SEA policy and OCR guidance, not one hard federal day count, so every date this scheduler produces is marked provisional pending a signer.

The meeting, and the notice that has to precede it

A deadline is not the same thing as a meeting that satisfies it.

The deadline clock answers by when an obligation must be met. Two separate things actually satisfy it: the parent notice that has to go out early enough for real attendance (34 CFR 300.322), and the required team membership that has to be in the room (34 CFR 300.321). Those live in their own module, deliberately, and it consumes the deadline engine’s output as a type rather than recomputing the clock a second time in a slightly different way — the kind of quiet duplication that eventually disagrees with itself.

The completeness check is a checklist, not a verdict. It reports which required roles are absent from a proposed roster; it never decides whether an absence is excusable — a real 300.321(e) excusal needs the parent’s and the LEA’s written agreement, a human act this module leaves entirely to the humans. And because IDEA itself does not fix a notice-day count, the roughly-ten-day default this module proposes is returned marked as provisional district practice, not dressed up as a confirmed legal number.

Once a proposal or a refusal is decided, the Prior Written Notice is what makes it official (34 CFR 300.503). The composer will not produce a partial notice: any required element missing, and the result is no document at all, not a document with a silent gap. The one thing it will never write is the procedural-safeguards statement itself — state-mandated, counsel-approved legal language — which ships as an explicit [LEGAL_REVIEW] marker rather than an invented paragraph that would read like law without being law.

Medicaid, consent-as-constraint

A claim line that cannot exist without a real parent’s real consent.

IDEA lets a district bill Medicaid for a related service an IEP already requires — speech, OT, PT, counseling, and the rest — but only after a one-time written parental consent, plus an annual notice the regulation also requires (34 CFR 300.154). The failure mode this replaces is the checkbox a biller trusts once and never re-checks: audits routinely find services billed with no linked consent on file at all, and the clawback lands on the district months or years later.

Here the constraint is enforced twice, deliberately redundant. At the database, a claim-line row cannot be written at all without a linked, active consent record — the backstop the application layer cannot bypass even if a route above it had a bug. And before the app ever attempts that write, a pure pre-check walks the whole chain by itself: is the consent present, active, not revoked, not expired; is the service actually listed on the IEP; is the provider credentialed; is the encounter documented. Any missing link, and the route returns a clean, explained refusal — which link failed — instead of a raw database error a biller has to reverse-engineer. A parent may revoke consent at any time, and a revocation stops billing at both layers immediately, not at the next batch run.

What this does not do, said plainly: it does not build the per-encounter dollar figure of a claim, and it does not assemble or submit a batch to any state Medicaid agency. Both of those exist as written, tested modules — and both are in the built-not-switched-on table above, because nothing calls them yet. The state SPA transmission chain, the RMTS/MER time-study requirements, and any physician-order requirement are counsel-and-SME residuals this product does not attempt to fake.

Progress and service minutes

The refusal that matters most: absence of data is never evidence of compliance.

A progress-monitoring feature is easy to get subtly wrong in a way that looks like a convenience: let the software glance at a trend line and mark a goal met once it clears a target. This one cannot do that, structurally. The function that reads a run of progress points returns a direction — improving, regressing, flat, or insufficient data — and a soft proximity flag for the UI to render. “Mastered” is not a value its return type can hold. That is not a rule someone remembered to check before shipping; it is a fact about the type, which means it cannot regress the way a forgotten `if` statement can. Mastery is recorded once, by the team, on the goal itself.

The service-minute read is the sharper of the two, and it exists because of a real, specific failure this codebase’s own comments correct out loud: an earlier design assumed the delivered-minutes log could be checked against an authored IEP service grid, and it cannot — no such grid exists yet with a compatible shape. So the honest question the log can actually answer is narrower, and it is expressed as a discriminated union on purpose: a caller cannot reach a compliant field without first narrowing on whether a real mandate basis was present at all. A child who received zero minutes of a mandated service produces zero log rows — and zero rows, with no mandate basis supplied, reads as not monitorable, never as clean. Give the read a real mandate figure, though, and zero delivery reports the entire mandate as the gap: the alarming case, surfaced as an alarm, exactly where a shortfall is easiest to bury in a spreadsheet nobody re-reads.

The health office — the lane that actually persists

Not the same record as the IEP, and the one place this domain genuinely writes to a table.

Everything above this section is arithmetic and access control layered over content a team authors elsewhere. This section is the exception, and it is worth calling out precisely because so much of this page is honest about what does not yet persist.

A health care plan — an Individual Health Plan, a Section 504 health plan, or a condition action plan for asthma, diabetes, anaphylaxis, or seizure — is a clinician-owned protocol, distinct from the education IEP/504 record above it. It may reference an accommodation by an opaque id so the health office and the education team stay tied together, but it never re-derives an accommodation on its own. Recording one is real: it is called at a registered route, gated by the same health-office access rule the platform’s immunization-compliance surface already uses — no invented role — and it is genuinely written to a table through the store, not merely validated and discarded.

Access is deliberately narrow: the nurse or health-office capability, or a school/district admin. Everyone else, including a rep session, is denied outright. The student is referenced by an opaque reference string only, and disclosure of the plan to a family surface is separately consent-gated — a consent value that is not an explicit grant yields no disclosure. The default is not to disclose.

Before a plan exists — screening, RTI, and Extended School Year

The pipeline that feeds a referral, and the summer lane an IEP team gates.

A plan does not appear from nowhere. Universal screening produces a risk band; a fidelity check reports whether an intervention was actually delivered the way it was designed; a Response-to-Intervention decision suggests whether a student should move up a tier, stay, or be referred toward an evaluation; a dyslexia-specific screening path suggests a follow-up action; a high-dosage tutoring dosage rollup and progress summary feed the same pre-referral picture. Each of those is a pure, tested engine, imported directly into the same wired route as the plan-authoring surfaces above — the pre-referral pipeline and the plan pipeline are not two disconnected products.

Extended School Year sits on the other side of the plan, deliberately gated by it. ESY is not summer school for special-education students — it is its own IEP-team determination (34 CFR 300.106) about whether a student needs services beyond the regular term to receive a free appropriate public education, and an esy-typed session enrollment is refused outright without a recorded eligible verdict tied to an actual plan reference. A general summer_school enrollment requires none of that. The eligibility determination itself reuses the same team-authorization gate as the rest of this page, verbatim — not a second, similar-but-different rule that could drift from the first.

Against the established platforms

Nine rows. The established platforms win the first three, outright.

Most vendor comparison tables are a list of things the author is good at, and everyone reading knows it. So here are the three axes where an established, mature IEP platform beats this product, first, without qualification: a complete, ready-to-file, state-specific document; counsel-approved procedural-safeguards legal text; and a pre-confirmed compliance day-count library for every state. Those are real, valuable, and advertised, and if a district needs exactly those three today, this is not yet the right fit for that district.

The six rows underneath describe axes where we believe this product is ahead, and the discipline in how they are written matters more than the result. We describe our own behavior precisely, because we can read our own source. Where the other column would require asserting what another company’s code does internally, it says we have not established it — because we cannot, and a guess in the direction that flatters us is not a comparison.

The left column states our own measured behavior. The middle column states only what the category openly advertises, or that we could not establish it.
What you are buyingAn established IEP platformIEP.software
Renders a complete, ready-to-file, state-specific IEP or 504 document todayYes. State-specific form rendering, maintained for the forms a given SEA actually requires, is a standard advertised capability of an established IEP platform.No. We build the schema, the clock, and the lifecycle. The state form layout itself is marked NEEDS-SME and returns an honest descriptor rather than a guessed form.
Supplies the state-mandated procedural-safeguards notice, in counsel-approved languageYes. Counsel-reviewed procedural-safeguards text is a standard part of an established platform’s notice output.No. The notice composer assembles every structural element and refuses to fabricate this one — it ships as an explicit honest-off marker until a district’s own counsel-approved text is attached.
Ships pre-confirmed compliance day-count rules for every state, out of the boxYes, as an advertised, maintained feature of a mature national platform.Partial. The engine encodes any state’s rule as data and resolves per SEA — but a state not yet in the confirmed table resolves provisional, not confident, until someone validates it against that state’s actual law.
A title unrelated to special education can be denied by construction, not by policyNot established. We do not audit how another platform’s role model is built.Yes, tested against a real defect: a yearbook masthead title was found able to read and author IEP content, and the fix is dated and described on this page rather than only in a changelog.
Zero logged minutes of a mandated service reads as an alarm, never a clean reportNot established. We have not read another platform’s service-log math.Yes. The compliance read is a type that cannot report compliant without a real mandate basis first being present — a child who received nothing produces nothing to grade as clean.
Progress data can structurally never close a goal on its ownNot established.Yes. The trend function’s return type has no value meaning mastered. Mastery is always a stored team decision on the goal itself.
Billing Medicaid for a service is enforced closed at two independent layersNot established.Yes. A database constraint and a pure pre-check both refuse a claim absent a real, current, unrevoked parental consent, independently of each other.
The eligibility, deadline, and consent logic is source you can read, not a black boxNot established — we have not read another vendor’s internals and will not characterize them.Yes. Every rule on this page is a documented, typed, pure function in this repository, not a description of a black box.
A family’s photo opt-out can never be the reason a case manager loses access to a child’s IEPNot established.Yes, by construction. The consent gate reads only the actual special-education consent purpose and the platform-wide do-not-publish kill switch, never the separate photo/publication flag.

One note on the category, since this page makes a claim about it. The established special-education compliance and IEP-authoring market includes platforms sold as modules of a wider student information system, alongside dedicated compliance and case-management tools built specifically for this category. They are referenced here once, only as a factual category reference, and none of their code, copy, or design is used anywhere in this product. Nothing above is a claim about how any of them is built internally — we have not read their source and cannot, so every row of the table either cites our own measured behavior or says outright that we could not establish theirs.

Twenty-six files, 402 test cases — a measured slice shown below

What is actually proven, and what a passing suite does not prove.

The 402 figure is a grep of every it()/test() block across the 26 test files touching this domain, on the same afternoon this page was written — a source-level measurement, not a target. Fifteen representative suites are shown here rather than all twenty-six, chosen to cover the lifecycle, the clock, consent, meetings, Medicaid, 504, manifestation, PWN, security, and progress.

The bound is as important as the result. A green suite proves a function computes the right answer. It says nothing about whether anything calls that function — and three of the fifteen below exercise modules that have no production caller at all. Those are flagged in place, on the chip.

Gate 01 Plan lifecycle Only the legal Draft-Review-Final-Amending-Archived moves are accepted; every other transition is rejected.
Gate 02 Deadline clock State-rule variance resolves correctly, and an unconfirmed state resolves provisional, never confident.
Gate 03 Consent gate A missing consent record suppresses the subject; the do-not-publish kill switch is inherited; a photo opt-out never fires this gate.
Gate 04 Meeting notice & team Notice timing and required-role completeness are checked against a proposed roster and window.
Gate 05 Medicaid consent constraint A claim is blocked on missing, revoked, or expired consent, and on any missing chain link.
Gate 06 504 accommodation authoring The four-bucket taxonomy validates and the review cadence resolves provisional.
Gate 07 Manifestation (wired) An MDR trigger is detected from a real discipline removal, and the team verdict is recorded verbatim.
Gate 08 Prior Written Notice A notice with a missing required element returns no document at all.
Gate 09 Team-scope security The masthead-credential defect stays closed: a non-team, non-admin caller is denied end to end.
Gate 10 Write-close security An authoring write closes for every role outside admin-tier and the proven guardian-of-record exception.
Gate 11 Goal & progress engine A goal is never auto-mastered; a progress trend never returns a value meaning mastered.
Gate 12 Minor-staffer wall A minor holding any staff title, elected or not, is denied special-education and health-office access outright.
Gate 13 special-ed-read (unwired twin) The second review-status resolver is correct in isolation — and exercised only here, never by a route. Exercises a module with no production caller
Gate 14 Compliance-ops summary (unwired) Deadline status and service-minute shortfall summarize correctly, with no route calling the module that computes them. Exercises a module with no production caller
Gate 15 Manifestation (shared, unwired twin) A second manifestation engine is correct in isolation and has no production caller. Exercises a module with no production caller

Data, walls, and what we hold

The most sensitive student lane on the platform, and the wall around it.

IEP and 504 content — a disability category, a present-levels narrative, a service log, a Medicaid consent — is the single most sensitive class of student data this platform touches, and it is treated as the strictest lane in the codebase rather than a variant of an ordinary roster record. A rep session is hard-denied before any other check runs, unconditionally, on every gate described on this page. A general teacher, a masthead title, a student, and a parent-of-another-student are all denied, by design, and one specific case of that denial failing was found, fixed, and is dated on this page rather than buried in a private changelog.

A family’s photo or publication consent is a completely different decision from a family’s special-education-data consent, and the consent gate that governs emitting a name, a disability category, or a narrative is written to never conflate the two. It reads the actual special-education consent purpose, and the platform-wide do-not-publish kill switch that correctly overrides everything — and nothing else. An ordinary photo opt-out, or a lapsed school-photo grant, has no effect on whether a case manager can see the plan they are legally required to implement.

To be exact rather than flattering: this is not a claim that a district holds less data by using this product. A disability record is data, and among the most sensitive a school keeps. The honest claim is narrower — every emission of it runs through one chokepoint, every write runs through a fail-closed authorship gate, and where that gate does not yet reach as far as it should (the per-student team-membership branch), this page says so rather than describing it as finished.

Common questions

The questions a special-education director actually asks.

Does IEP.software write the IEP for us?

No, and there is no AI anywhere in this domain that touches a team-decision field. The goal statement, the eligibility determination, the placement, the disability category, the PLAAFP narrative, a goal’s mastery verdict, a meeting’s consent disposition — every one of those is authored by the team and carried through the system verbatim. The software provides the state machine, the clock, the access wall, and the progress math around what the team writes. It does not generate, infer, or suggest the content of the plan itself.

Can it print or file our state’s specific IEP form?

No. Building the schema, the deadline clock, and the lifecycle is buildable and built. Rendering a specific state’s form LAYOUT is a different, narrower problem that needs a subject-matter expert to sign off state by state, and we have not invented one. The form-rendering endpoint returns an honest descriptor saying so rather than a plausible-looking but unvalidated form.

Can a progress report ever mark a goal met on its own?

No, and this is not a policy someone has to remember — it is a fact about the type. The function that reads a goal’s progress points returns a trend direction (improving, regressing, flat, or insufficient data); “mastered” does not exist as a value that type can hold. A goal’s status is set once, by the team, on the goal record itself, and the progress engine never touches it.

What happens if a related service is under-delivered, or not delivered at all?

The service-log gap read is a discriminated union on purpose: a caller cannot reach a compliant verdict without first establishing that a real mandate existed. Zero delivered minutes against a real mandate reports the full mandate as the gap — the alarming case, reported plainly. And zero log rows with no mandate basis supplied reports as not-monitorable, not as compliant, because we cannot tell “nothing was owed” from “everything was owed and none of it happened” without a real mandate figure to compare against. Absence of data is never read as evidence of compliance.

Can a teacher who is not on a student’s IEP team read that student’s plan?

No — and we want to be specific about why we are confident saying so. A real defect was found and fixed in this exact wall: the route’s access gate previously admitted anyone holding the yearbook/newsroom masthead staffRole (adviser / co-adviser), which is not a special-education credential, meaning a school’s yearbook adviser could read and author any student’s IEP. That was closed to admin-tier plus a server-proven guardian of the specific student being read, and a second ordering defect (a teen parent’s own guardian right being blocked by an earlier-checked minor wall) was fixed a few weeks later. Both are dated on this page rather than left in a private changelog.

Does the per-student IEP team get its own read access today?

Not yet, and we would rather say that plainly than let it be discovered. The access gate’s team-membership branch is real code and fires today inside every goal, team, progress, and service write. But the route currently pins the team predicate to a literal false, because the roster table it would check had no writer at all until this repository shipped one. Until that gate is deliberately flipped to trust the new roster, the only two tiers that can actually author or read a plan are a proven admin, and — for reading only — a server-proven guardian of that specific student.

Does it bill Medicaid for us?

No. It proves, at two independent layers, whether a claim line COULD be billable given a real, current, unrevoked one-time parental consent and a complete documentation chain — and it holds every claim lacking that consent at zero. There is a separate, unwired module that would derive a claim batch and prepare (never submit) it; it has no route caller today and is named in the built-not-switched-on table on this page. Nothing here transmits a claim to any state Medicaid agency.

What about the Prior Written Notice and the procedural-safeguards statement?

The notice itself — who it is about, what is proposed or refused, why, what other options were considered — assembles from the plan’s authored facts and refuses to produce a document at all if a required element is missing. The one field it will never write is the procedural-safeguards statement, which is state and counsel-mandated legal language. That field ships as an explicit honest-off marker so a district attaches its own counsel-approved text, rather than receiving a fabricated paragraph that reads like law but is not.

Can a parent see their own child’s IEP, separately from the staff wall?

Yes. A server-proven guardian of the specific student being read — never a client-supplied claim — is admitted on a student-scoped read, independent of the staff/admin tier, matching a parent’s 34 CFR 99.10 inspection right. A guardian of a different student is not admitted by this branch; that would be a far worse hole than the one this branch closes.

Does this replace our student information system?

No. It is a special-education layer that a school’s roster, enrollment, and attendance already sit under on the wider platform, and it can be enabled independently of that. It is not sold as a document mill and is not trying to become one.

Is any of this touched by a family’s photo consent or publication opt-out?

No, and this is written into the gate on purpose. The consent chokepoint that decides whether a name, disability category, or narrative can be emitted reads only the actual special-education consent purpose and the platform-wide do-not-publish kill switch. It is deliberately never driven by an ordinary photo opt-out or a lapsed school-photo grant — a decision about pictures is not a decision about a disability record, and conflating the two would redact information from the team legally required to implement the plan over an unrelated family preference.

Is this live today, or is it a future promise?

It is live code behind a module flag. A district enables sis_iep, sis_504, sis_medicaid, or summer_school_esy per tenant; until then, nothing about the product is different from today, and turning it on does not invent or backfill a single record. The honest-off residuals named on this page — state form rendering, the legal notice text, the Medicaid transmission chain, unconfirmed state day-counts — stay honest-off regardless of the flag.

What does it cost?

There is no price on this page and no checkout anywhere on this site. The honest next step is a conversation about which module a district actually needs turned on, and which of the honest-off residuals matter for that district’s state.

Is IEP.software a school, a district, or a nonprofit?

No. It is a for-profit software product built by Stanley Studios. It is not a school, not a district, and not a nonprofit, and nothing here is a charitable gift of any kind.

Related surfaces

Adjacent products, each its own thing.

IEP.software is the special-education record, its clock, and its consent. These are the neighboring rails, kept as separate products rather than folded into one suite.

schedule.software

The scheduling engine a related-service provider’s caseload and a team meeting’s room and time sit alongside. Kept as its own product.

payroll.software

The arithmetic behind a related-service provider’s pay. Money out to staff is a different product from a record of a child’s services, and we keep them apart.

What this page is and is not claiming

The whole posture, in one paragraph.

IEP.software is module-dark: the engines described on this page are wired to registered routes and covered by 402 measured test cases, and a district that has not enabled the module sees no difference from today. It does not render a state-specific IEP or 504 form — that surface returns a named, honest descriptor rather than a guessed document. It does not supply procedural-safeguards legal text — the notice composer ships that one field as an explicit honest-off marker. It does not bill or transmit a Medicaid claim to any state agency — the consent constraint proves whether a claim line could be billable and stops there, at two independent fail-closed layers. Seven things are named on this page as built-with-no-production-caller or a real, current access-control limitation, by name, rather than counted as features. No AI touches a team-decision field anywhere in this domain: eligibility, placement, a goal’s mastery verdict, and a meeting’s consent disposition are stored, team-authored inputs. A real defect in the access wall — a masthead title able to read and author disability records — was found and fixed, and is dated on this page rather than only in a changelog. There are no adoption counts, no customers named, no testimonials, and no invented figures anywhere on this page; the only measurements quoted are twelve wired engines, seven named residuals, and 402 grepped test cases. There is no pricing and no checkout on this site. The honest next step is a conversation.

IEP.software is engineering-complete code sitting behind a per-tenant module flag. A district that has not enabled sis_iep, sis_504, sis_medicaid, or summer_school_esy sees no difference from today, and enabling it never backfills or invents a single record. What is honest-off is named on this page, by name: state-specific form rendering, the procedural-safeguards legal text, the Medicaid state transmission chain, and the per-state deadline day-count for any state not yet confirmed against real statute. Every one of those returns a clear refusal today, not a plausible guess.