Both came back schema-valid. Only one of them found the child.
Parent/guardian said Meera had fevers since last night and will probably be back tomorrow
- parent_confirmed_aware
- yes
- reason_category
- illness
- expected_return
- tomorrow
- spoke_with
- unknown
- a two-bucket systemresolvedcase closed
- firstbellresolvedThree fields the office can act on.
Recipient was unaware of the absence and said Nithya P left for school this morning
- parent_confirmed_aware
- no
- reason_category
- unknown
- expected_return
- unknown
- spoke_with
- unknown
- a two-bucket systemresolvedcase closed. Filed as reason_category unknown, parent_confirmed_aware no.
- firstbellescalatedheld open and escalated to a safeguarding lead.
What these two calls are, and what the two-bucket row is not
One school morning, modelled
Drag to turn it. Point at a tile for its slot in the morning.
41 absences in one morning at a school of 600, at the national rate. Every tile is a family somebody has to telephone before the register closes, and from the desk they are identical. One of them is not a child who stayed home. Where the number comes from, and what happens when the morning is longer than the cut-off →
What these calls are, who consented, and how the two systems differ
The guardian was not aware of the absence. That is the answer that matters, and it is the only answer the call got. Why the pupil was away came back unknown. When to expect them back came back unknown. Those two are what the office needs before it can act, so a system that counts contacts would mark this “family contacted” and close it. This one files it escalated and puts it on a safeguarding lead’s desk, inside thirty minutes.
Two calls above, played from their own recordings, out of 20 this software placed through CALL-E; the money is computed over the 12 pooled in evidence/recorded-calls.json; act 02 holds both conversations in full. The recordings are held outside this repository. Every call went to the author’s own line, scripted and consented, and the pupil names are fictional. Act 01 says what the region ceiling costs, and act 07 is the run that shows it.
Technical verification and audit trail
Nine acts, every one of them folded. Open any of them for the receipts behind the two calls above: the money against CALL-E’s own billing, every rule broken on purpose with the test that caught it, the limits this entry does not clear, and the whole run on one command.
- 12 real calls
- 11 answered
- 7 escalated to a person
- $0.40 a call, mean of 19
The problem
Answered is not the same as answered usefully.
A call that connects and learns nothing looks exactly like a success.
The three endingsWhat this does
Three endings, not two.
resolved closes the case. failed is retried. undetermined never closes: the call happened, it produced nothing usable, and the software says so instead of counting it.
What the third one costsWhat it changes
The office gets a list, not a percentage.
An attendance clerk opens a queue ordered worst first: safeguarding, then the children nobody reached, then the calls that learned nothing. Every row names the person it is waiting on.
Run it yourselfWhy it holds
853 tests, and every rule broken on purpose.
Every number on this page is computed from a recorded run rather than typed. Break one of the rules deliberately and a named test fails; the broken rules and what caught them are published.
Every rule, broken
The two-minute path
Six destinations, in the order they answer the question a judge is actually asking. Everything else on this page is the evidence behind them.
- 01Watch a row fill in
A real call, and what CALL-E returned for it: parent_confirmed_aware no, reason_category unknown. The fields fill in from the recording as it plays.
- 02One scenario, English and Tamil
A different pair of calls from the one above: two conversations of different lengths, and the four fields underneath each of them.
- 03Three endings, not two
What this software does with a call it could not get an answer to.
- 04What it costs, and against what
For a buyer: the price above which a person is cheaper, beside what a district already pays for the system this sits next to.
- 05Run it, here, now
The whole offline run is on the page: seven rows, three endings, and the totals. A button replays it line by line. No account, no key, nothing dialled.
- 06What a pilot would look like
Two schools, six weeks, the four numbers measured before switch-on, and the children this software is not allowed to telephone. Leaves this page.
Why an unanswered message is not information, and what the run prints about this one
The school knew nothing, and had no way to find out.
An unanswered absence message is not information. It is an absence of information, and it looks identical whether the child is at home with a fever or never arrived anywhere.
The call above is the second kind. At 21 seconds the person who answered is asked to confirm they know the child is absent, and says they did not know, and that she left for school that morning. Nobody on the call could say where she actually was. The reason for the absence came back unknown, and parent_confirmed_aware came back no.
A school would have to answer these within 30 minutes (this project's default, which no district has agreed to).
Printed by the run itself, above the cases it refuses to close. The whole queue is in act 08.
Same call. Whichever language the family speaks.
One scenario, performed once in English and once in Tamil. The two conversations are not the same; what the platform returned for them is.
The missing-child scenario, in English beside Tamil
- 0:00agentThis is an automated call from the school attendance office.
- 0:02recipientHello, who's this?
- 0:04agentI’m calling from the school attendance office.
- 0:06agentI’m calling about Nithya P, who was marked absent on September fourteenth,
- 0:10agenttwenty twenty-six; can you confirm you are aware of the absence?
- 0:21recipientWhat? No, I didn't know that. Well, actually, she left for school this morning.
- 0:22agentThanks.
- 0:23agentWhat was the reason for the absence?
- 0:31recipientUh, I, I don't know, I need to check on that.
- 0:32agentOkay.
- 0:32agentWhen should the school expect Nithya P back?
- 0:44recipientUh, after checking that, I'll let you know because I'm unaware that she is absent.
- 0:45agentOkay,
- 0:46agentI’ll note that you’re not aware of the absence. Anything you want to add in a brief note?
- 0:54recipientUh, no.
- 0:55agentNoted.
- 0:56agentThank you, bye.
CALL-E’s own noteRecipient was unaware of the absence and said Nithya P left for school this morning.
- 0:00agentஇது பள்ளி வருகைப் பதிவு அலுவலகத்திலிருந்து வரும் தானியங்கி அழைப்பு.This is an automated call from the school attendance office.
- 0:04agentநீங்கள் ஒரு நபருடன் அல்ல, AI உதவியாளருடன் பேசுகிறீர்கள். எந்த நேரத்திலும் பணியாளர் ஒருவருடன் பேச வேண்டும் என்று கேட்டால்,You are speaking with an AI assistant, not a person. If at any time you ask to speak with a staff member,
- 0:13agentநான் மீண்டும் அழைப்பை ஏற்பாடு செய்வேன்.I will arrange a callback.
- 0:19recipientஹலோ. ஓகே.Hello. Okay.
- 0:21agentலக்ஷ்மி வி இரண்டாயிரத்து இருபத்தாறு செப்டம்பர் பதினான்காம் தேதி வரவில்லை என பதிவு செய்யப்பட்டுள்ளார்;Lakshmi V has been marked absent on September fourteenth, twenty twenty-six;
- 0:28agentநீங்கள் அவர் வராதது பற்றி அறிந்திருக்கிறீர்களா?Are you aware of her absence?
- 0:39recipientஇல்லையே என்னச்சு சொல்றீங்க? எனக்கு கரெக்ட் டா தெரியலையே. காலைல ஸ்கூல் க்கு தான் கிளம்பி போனா அவ.No, what are you saying happened? I don't know for sure. In the morning she left for school only, she did.
- 0:41agentசரி.Okay.
- 0:42agentஅது ஏன் என்று சொல்ல முடியுமா?Can you say why that is?
- 0:53recipientகரெக்டா தெரியல நான் செக் பண்ணனும். ஏன்னா அதை மோர்னிங் காலைல கிளம்பி தான் போனா ஸ்கூல் க்கு.Don't know for sure, I need to check. Because that morning in the morning she only left and went to school.
- 0:53agentநான் காத்திருக்கிறேன்.I am waiting.
- 1:00agentநான் காத்திருப்பேன்.I will wait.
- 1:05recipientபுரியல.Don't understand.
- 1:07agentஎந்த காரணத்தால் வரவில்லை என்று தெரியுமா?Do you know for what reason she did not come?
- 1:10agentஉதாரணமாக உடல்நலம், குடும்ப காரணம், அல்லது வேறு ஏதாவது?For example health, family reason, or anything else?
- 1:15recipientஇல்ல இல்ல அதான் இது.No no, that's what it is.
- 1:17agentசரி, நன்றி.Okay, thank you.
- 1:19agentஅவர் எப்போது மீண்டும் பள்ளிக்கு வருவார்?When will she come back to school?
- 1:21recipientஅதான் எனக்கு தெரியல. நான் செக் பண்ணனும். ஏன்னா அவன் மோர்னிங் ஸ்கூல் க்கு போனான்.That's what I don't know. I need to check. Because he went to school in the morning.
- 1:23agentசரி, புரிகிறது.Okay, understood.
- 1:25agentலக்ஷ்மி எப்போது திரும்ப வருவார்?When will Lakshmi come back?
- 1:37recipientஅது செக் பண்ணா தான் தெரியும். ஏன்னா மோர்னிங் ஸ்கூல் க்கு போனது மட்டும் தான் எனக்கு தெரியும். பட் இப்ப நீங்க வரலன்னு சொல்றீங்க.That will only be known if I check. Because that she went to school in the morning is all I know. But now you are saying she didn't come.
- 1:38agentசரி,Okay,
- 1:39agentநான் இதை மீண்டும் சரிபார்க்க சொல்லுகிறேன்; இன்று ஒரு பள்ளி பணியாளர் உங்களை பின்னர் அழைப்பார் நன்றி,I will tell them to check this again; a school staff member will call you later today thank you,
- 1:46agentவணக்கம்.Goodbye.
Each Tamil line is followed by its English. The Tamil is what CALL-E heard and returned. The English was written afterwards from that text, with a language model reading only the Tamil, and nobody spoke it on the call.
CALL-E’s own noteGuardian was not aware of the reported absence and said the student had left for school that morning; they need to check what happened.
Different words, different lengths, 4 of 4 fields identical.
There is no Tamil-specific code in this app. Language is one column in the work file and one string in the request.
All sixteen comparisons, counted before the phone rang: 13 of 16 matched
Four scenarios, each performed twice, four enumerated fields per pair. The family was committed before any call was placed, so which comparisons get reported could not be chosen afterwards. All three mismatches are the speaker saying different things in the two calls, which a person recalling their own script from memory will do.
| scenario | en-IN | ta-IN | agreed |
|---|---|---|---|
| illness, returns tomorrow | S-4101 | S-4102 | 3/4 |
| family emergency, no return date | S-4103 | S-4104 | 2/4 |
| parent did not know | S-4105 | S-4106 | 4/4 |
| refusal | S-4107 | S-4108 | 4/4 |
The third ending is the one everyone gets wrong.
One call. Three filings. Three different coverage numbers.
- wrongresolveda system with two buckets, closing anything that came back schema-validthe dashboard reports every family contacted, for a child nobody reached
- wrongfaileda system with two buckets, discarding anything short of a full answera call that did reach the parent is thrown away with the ones that never connected
- oursundeterminedthe call happened and produced no usable answerthe row stays open under a name, recovers no funding, and is never counted as coverage
One committed run. 7 calls placed, 7 answered, 3 closed with a usable reason. A call that connected and produced nothing usable is the difference, and it is not coverage.
7 of 7 contacted is what the same run reports with nowhere to put the middle four.
An automated dialler with no safeguarding triage does not close cases. It closes the only record that a case existed.
CALL-E filed a missing child as a routine transport absence. That call is S-3103. Its transcript travels with this page, with the school it names replaced by [school name redacted]; its recording is not played here. So did this software, until 2026-09-11.
This app made the first mistake itself.
The queue that comes out of it, named, with what each line costs
6
cases need a person. Nothing here is closed.
The language on 6 of these rows is read from the script of the call's own transcript, because this receipt predates the roster field that records it. 3 of the 6 were conducted in Tamil, so this queue needs a Tamil speaker on the rota rather than whoever is free. Each carries a 30-minute callback window and this receipt records no per-call end time, so the deadline is not shown. The field is written now, it was not on 4 September, and a countdown computed from the moment this page was built would be a deadline against nothing.
S-4102
The parent confirmed they knew, and the call never established when the child is coming back.
Speak to this family first.
safeguarding
Tamil · 1 number tried
S-4103
The parent confirmed they knew, and the call never established when the child is coming back.
Speak to this family first.
safeguarding
English · 1 number tried
S-4105
The parent did not confirm they already knew their child was absent. The call also ended without an answer the office can use.
Speak to this family first.
safeguarding
English · 1 number tried
S-4106
The parent did not confirm they already knew their child was absent. The call also ended without an answer the office can use.
Speak to this family first.
safeguarding
Tamil · 1 number tried
S-4107
The parent did not confirm they already knew their child was absent. The call also ended without an answer the office can use.
Speak to this family first.
safeguarding
English · 1 number tried
S-4108
The parent did not confirm they already knew their child was absent. The call also ended without an answer the office can use.
Speak to this family first.
safeguarding
Tamil · 1 number tried
Every row is a real call from 06-locale-matched-pairs.json, sorted by the same rule the program uses. Nothing here was arranged for the picture. One of them is the call this page opens on, and it plays up there; the recordings of the rest are held with the receipts, and the receipt file is on neither this page nor in the repository, for the reason evidence/README.md gives. The count holds without it: evidence/recorded-calls.json records that receipt’s 7 calls and the 6 of them that needed a human, which is the 6 rows here, and it carries the counts behind every money figure on this page.
This app made the first mistake itself. A parent refused to talk, CALL-E returned a schema-valid result with every required field set to "unknown", and the row was recorded as resolved. The receipt stays as it was written, uncorrected, because a corrected copy would record a run that never happened. What changed is the code, and a test now fails if the distinction collapses again.
Counts read from one recorded run of 7 calls, 06-locale-matched-pairs.json, a receipt held outside this repository and published nowhere, whose counts are committed in evidence/recorded-calls.json. 4 of 7 rows are still open and every one of them is named. The rate is resolved over attempted, so an open row can only ever pull it down.
Check us against CALL-E’s own billing.
CALL-E can match every row here against their own records, and they have no stake in these claims. The API returns one call identifier and the billing dashboard is keyed on another, so both are here, shortened at both ends, beside the structured answer each call brought back. A reader who is not CALL-E can check the count instead: it is committed in evidence/recorded-calls.json, and a note below says why the identifiers are cut.
$157,664
a year, for the system this would sit beside
$35.51
one student, one day, where funding follows attendance
$0.40
a call on the meter, averaged over the 19 CALL-E has billed since it repriced. The desk time one call removes is worth at most $0.35: a ceiling, not a saving
Where each of those figures comes from, and what would move it
$157,664 a yearOne named district’s student records bundle, on its own board record, for 11,353 students. $13.89 a student a year. One price on the record, not a market average. Chapel Hill-Carrboro City Schools Board of Education
$35.51 a student-dayTexas funds $6,215 per student in average daily attendance, over a 175-day year. Seven states funded on attendance as of 2022. Explaining an absence does not make a student present, so this run claims none of it. Texas Education Agency
$0.40 a callCALL-E publishes no price, and the one it charges moved while this page was being written. The left figure is the mean of the 19 rows it has billed this account since it moved the dashboard to credits: $0.06 to $1.36 a call, with 7 of them at the $0.06 floor. The 13 rows before that were $0.05 each, $0.65 over a month, and CALL-E’s own panel now labels them Legacy pricing. Nothing on this account was bought: the $8.20 it has spent came out of two grants worth $11.00, and the larger one was issued as 200 free calls, which is $0.05 each and buys 25 at the rate above. The right figure is the demo run: 4 of 8 attempts came off a desk at $23.55 an hour at three minutes each, less the safeguarding callbacks at $37.40. Not a saving: a ceiling. And not a measurement. That run answers against a test double, and its outcome mix is written down in firstbell/scenario.py: anybody can reproduce it with one command, and somebody chose it. The measured figure is below, over every call pooled in evidence/recorded-calls.json.
- The most one call can save
- $0.08
- Where that becomes a loss
- 22.9 per 100 answered calls
- What 11 answered calls cannot rule out
- 47 net-new per 100
- The same bound if every escalation is a callback
- 86 per 100
The sample is every call pooled in evidence/recorded-calls.json, which is the sample this page was fixed on before any of it was measured, and these three rates are per answered call, because one of those calls reached nobody. The widest of them prices all 7 escalated calls as callbacks rather than only the ones this software says it created. That is 64 per 100 measured and 86 that this many calls cannot rule out, both above the 22.9 where the saving stops, so on that assumption this is a cost and not a saving. Quote the $0.08 above rather than the demo run’s $0.35: it is the smaller of the two, and it is measured over every call this page publishes rather than over a run. The demo run is the figure one command reproduces, and it is the higher of the two, so it is not the one to quote. Plan against the $0.70 a call this becomes if every escalated call is priced as a callback, which is the reading this entry holds itself to. The calls themselves were billed at a mean of $0.40 each over the 19 rows CALL-E has charged since it repriced, and at $0.05 each on the 13 before it, which its panel now calls legacy. Which of those two a district is living in is what the first week of a pilot measures, and nothing before that week can settle it. The paragraph below is the same figures with the objections they answer, and the demo run’s own numbers are in the two cards above.
$0.05 is one account’s billing on hackathon credit and not a price CALL-E stands behind, so a district confirms its own. Every one of those calls ran between 0m35s and 1m50s, all under two minutes, so they cannot tell a flat price from a per-minute one rounded up. This page’s receipt is a third run: 1 of 7 attempts removed, 2 of 7 answered calls became new work for the safeguarding lead, though 6 carry the safeguarding mark: net-new counts only a call that would have closed on its own, and a call already going to a person was going there anyway. 7 calls cannot rule out 66 per 100, against a crossover of 9.0 per 100: above that rate the callbacks this software creates cost a district more than the attempts it removes, which is the sentence a school board asks for and the one a vendor deck leaves out. At the far end of the bound the callbacks cost more than the calls save, and which end it is, is what a pilot measures in week one. Across all 12 calls this software has placed against the production API, the net ceiling is $0.08 and the crossover is 22.9 per 100, with 2 of 11 answered calls measured at 18.2. The safeguarding rule marked 7, and pricing every one of those as a callback rather than only the ones this software says it created turns that into a cost of $0.70 a call. That bound over-counts on purpose and it is the number to hold this entry to. python tools/money_across_runs.py prints every run’s figures from one piece of arithmetic. How many unanswered notifications a district handles in a morning is still a number a school office has and we do not, which is why every figure here is per call rather than per year. For scale only: the United States has 13,303 regular school districts and 99,297 public schools (National Center for Education Statistics). That is the size of the problem, not a claim about adoption.
What a pilot would look like: two schools, six weeks, and the four numbers measured before this software telephones anybody.
Every one of the twelve calls, with both identifiers, and what is held where
| call id (API, then dashboard) | parent_ | reason_ | expected_ | spoke_ | outcome |
|---|---|---|---|---|---|
| call_ 15c7…1acc | yes | illness | tomorrow | · | resolved |
| call_ 6a76…d845 | yes | illness | tomorrow | · | resolved |
| call_ f09a…52df | · | · | · | · | failed |
| call_ b9ef…1fae | unknown | unknown | unknown | · | resolvedclosed on nothing |
| call_ 49c1…4be0 | yes | illness | tomorrow | · | resolved |
| call_ ec5c…26d5 | yes | illness | unknown | · | resolved |
| call_ f50c…508e | yes | family_emergency | unknown | · | resolved |
| call_ 392a…b406 | yes | other | later_this_week | · | resolved |
| call_ db78…f215 | no | unknown | unknown | · | undetermined |
| call_ 13f2…c77a | no | unknown | unknown | · | undetermined |
| call_ 2043…4ba5 | unknown | unknown | unknown | · | undetermined |
| call_ 5f10…13e3 | unknown | unknown | unknown | · | undetermined |
6 of 6 committed receipts reached the production API and 12 of 12 calls carry the provider identifier. The rest had it recovered afterwards with a GET, which places no call.
The identifiers are shortened on purpose. A live call id is not a credential, because another account’s key cannot read our call, but it is an artifact of a real call to a real number and this repository asks contributors to keep those out of what they publish. CALL-E hold the billing records this table invites a check against and can match a row from what is shown; the unshortened list travels with the submission rather than on a public page.
| transcripts, waveforms, the audio, and the unshortened identifiers | not in the repository. On this page in full, apart from the identifiers, which are shortened |
| the rules those calls produced, and the tests that hold them | in the repository |
The maintainer of this list requires committed real-call artifacts to be removed, and has said so even where the people on the call were team members playing a part on reserved numbers, which describes these calls exactly. So the recordings live here, the reasoning lives there, and tests/test_privacy.py fails the build if one crosses over.
Every rule, broken on purpose.
Every safety rule is verified against simulated failures.
How each rule is checked, and the defect it found
Each row is a change made to working code to check that a specific test notices. Every one was reverted and the suite returned to green. The number beside a row is how many tests failed while the change was in.
reached_production_api was computed from the configured base URL alone. A run whose every attempt died at the transport layer would still have published that it reached production.All 358 changes, and the tests that caught each one
| # | the change | tests that failed |
|---|---|---|
| 2 | Turn the consent check off, and the software phones a family that never agreed to be phoned.
| 8 |
| 49 | Turn the safeguarding rule off, and a parent who did not know their child was missing is filed as handled and nobody is told. Make | 13 |
| 53 | Count the money from calls that were answered instead of calls that were closed, and the funding figure goes up every time a child cannot be accounted for. Compute funding recovered from | 2 |
| 57 | Plant a real Indian mobile number where the privacy scan was not looking. This is the one row no test caught, and it is in the table for that reason. Plant an assignable Indian mobile in | 0 |
| 98 | Remove the check on how a family can be reached, and a guardian who is deaf is phoned, reaches nobody, and is recorded as unreachable. Remove the gate that refuses to dial a family recorded as unreachable by telephone, so a guardian who is deaf or hard of hearing is called, reaches nothing, and is filed under nobody answered | 5 |
The other 353, in the same shape
| # | the change | tests that failed |
|---|---|---|
| 1 | max_workers=self._concurrency becomes max_workers=None, removing the concurrency cap | 4 |
| 3 | Drop insufficient_balance from the double's API_ERROR_CODES | 4 |
| 4 | Match the production host by substring instead of hostname, so api.heycall-e.com.example.net passes | 2 |
| 5 | Write the transcript into every receipt instead of only when --include-transcript is given | 1 |
| 6 | Prefer the attempt's raw SIP code over the task's symbolic one, putting 603 in front of an administrator | 1 |
| 7 | Delete the SIP translation table, so a queue row reads the call failed with 603 | 7 |
| 8 | Stop falling back to the task-level structured_result, which is the defect a real call exposed | 22 |
| 9 | Allow that fallback for fan-out too, which would file one family's answer against another family's child | 1 |
| 10 | Remove the check for a result whose required fields are all uninformative | 1 |
| 11 | Flag a result if any required field is unknown rather than all of them | 1 |
| 12 | Report placed when the response carries no usable created_at, instead of reporting unknown | 1 |
| 13 | Drop the clock-skew guard, so a service clock hours ahead reads as a freshly placed call | 1 |
| 14 | Read provider_call_id off the first attempt instead of the last, so a call that fell back to a second number cites the id of the attempt that did not connect | 1 |
| 15 | Change the test count stated in the README, which is what a reader runs and compares | 1 |
| 16 | Blank api_base_url on a receipt that still claims reached_production_api | 1 |
| 17 | Commit a receipt that no line of evidence/README.md describes | 1 |
| 18 | Compute reached_production_api from the configured base URL alone, so a run that exchanged no bytes with CALL-E still reports that it reached production | 1 |
| 19 | Credit every attempt to the machine instead of only the attempts behind records it closed, so calls that left a family unreached still count as staff time saved | 4 |
| 20 | Report a break-even of 0.00 rather than nothing when a run billed no attempts, turning could-not-compute into a free-looking number | 4 |
| 21 | Wrap the citation like prose, so the source URL breaks mid-path and the reader cannot open the thing the number came from | 3 |
| 22 | Drop source from the wage validation, so a staff cost can be asserted with no provenance at all | 1 |
| 23 | Shift one cited line number by one, the way any edit above it would | 1 |
| 24 | Keep a cited line number and change the symbol the sentence claims is on it | 1 |
| 25 | Point the ten-minute reading order at a file that does not exist | 1 |
| 26 | Delete the runtime anchors entirely, which a check written as "every anchor resolves" passes on an empty list | 1 |
| 27 | Put the extracted result back on the recipient when no per-recipient schema was asked for | 2 |
| 28 | Drop two task-level fields the production API returns on every response | 2 |
| 29 | Give an attempt our symbolic name for the outcome instead of the wire code the API sends | 7 |
| 30 | Commit an image rendered from the call recordings, which no text check can read | 1 |
| 31 | Store a vendor error message unchanged, when that message quotes the number it rejected | 2 |
| 32 | Leave the completion poll unprotected, so one failed read discards a call that was placed | 4 |
| 33 | Put one backspace byte inside a committed source file, which no editor or diff displays | 1 |
| 34 | Leave a real CALL-E error code in none of the three classification sets | 1 |
| 35 | Let one dispatcher instance run twice, inheriting the first run's cancellation | 1 |
| 36 | Accept two work items sharing an id, so one idempotency key covers both | 2 |
| 37 | Read a service clock an hour behind ours as a definite replay rather than unknown | 1 |
| 38 | Write the structured result to the receipt unmasked, which is how it shipped until this was fixed | 1 |
| 39 | Drop the comma from the separator class, so a number a vendor groups with commas is left whole | 3 |
| 40 | Let a calls.create timeout fall through to the catch-all, which is how it shipped until this was fixed: no retry, and a call that may have been placed recorded as FAILED | 2 |
| 41 | Cite in docs/images/README.md the line the caption used to name, which is how both stills shipped | 1 |
| 42 | Type a window bound back into the still generator instead of looking it up | 1 |
| 43 | Accept RetryPolicy(max_attempts=0), whose create loop never runs, so every item comes back FAILED with an empty reason about a run that dialled nobody | 1 |
| 44 | Stop escaping < in the JSON embedded in the page's <script> block, so a transcript turn containing </script> ends the data early and the rest of the page is parsed as markup | 1 |
| 45 | Delete the refusal that keeps a production key off every origin but https://api.heycall-e.com, so CALLE_BASE_URL can send the live bearer token to any host that is listening | 1 |
| 46 | Invert that refusal so it stops every destination, which would leave a tool that can never place a real call | 1 |
| 47 | Compare the base URL by hostname again instead of by origin, so http://api.heycall-e.com is filed in the receipt as an ordinary live call | 1 |
| 48 | Drop the scheme when normalising an origin, so a plaintext destination compares equal to the trusted HTTPS one | 1 |
| 50 | Ask the rule whether the answer is no rather than whether it is yes, which closes the missing and the unknown case as though either were a confirmation | 4 |
| 51 | Derive ItemResult.needs_a_human from the resolution alone again, so an escalated case never reaches the human queue | 6 |
| 52 | Stop sorting the queue, so a safeguarding case can sit below every ordinary callback and be reached last | 3 |
| 54 | Compute the resolution rate from resolved rather than closed, so the headline improves when the app finds something serious | 3 |
| 55 | Fail open when a caller's escalation rule raises, dropping the case the rule was written to catch on the one run where the rule was broken | 2 |
| 56 | Drop escalation= from the schema-valid branch, so the flag is computed correctly and then not carried | 7 |
| 58 | The same number with the gate scoped to every path this contribution adds | 1 |
| 59 | Point CONTRIBUTION_PATHS at a directory that no longer exists, which is what a rename looks like from inside the gate. Reported as 10 errors rather than 10 failures, because the guard sits in the helper every one of them calls | 10 |
| 60 | Have mask_id hand back the identifier it was given, so every call id on the page is whole again | 1 |
| 61 | Print the API id straight into the identifier table, shortening only the provider id beside it | 1 |
| 62 | Assign _call[_key] = _call[_key] in the loop that shortens the embedded call data, which is a masking loop that masks nothing | 1 |
| 63 | Have the README promise eight results on the page when the page carries eleven Needs the built page. | 1 |
| 64 | Change one unknown answer in the built page to yes, so four of the five countable non-yes answers remain Needs the built page. | 1 |
| 65 | Leave one whole provider id in the built page, in a comment the layout never shows, which is what a leak looks like when it is not in a visible column Needs the built page. | 1 |
| 66 | Teach another gate to skip and declare it nowhere, which is how a gate stops running without anybody deciding that it should | 1 |
| 67 | Drop a gate that still skips out of the register, so the suite goes quiet about one it already knew about | 1 |
| 68 | Declare a gate as unable to run when it runs perfectly well, because a register nobody prunes becomes a list of excuses | 1 |
| 69 | State a mutation count in the app README that the table does not have | 1 |
| 70 | State a different one in evidence/README.md, which is where this drift actually was: the index said forty-four while the table held sixty-eight | 1 |
| 71 | Round the published alert rate down from 45% to 35%, which is the direction somebody would round it if they were rounding on purpose Needs the built page. | 1 |
| 72 | Change one no answer on the built page to yes, so the page no longer supports the rate the README states beside it Needs the built page. | 1 |
| 73 | Put the wrong England absence figure back, which is the defect this gate was written after rather than a defect imagined for it | 1 |
| 74 | Add a plausible new percentage to the sourced section with no entry behind it, which is how the first one got in | 1 |
| 75 | Drop the source link and leave the figure bare, so it reads as sourced without being checkable | 1 |
| 76 | Plant a call id inside tests/test_privacy.py itself, where the module's own exemption used to hide it | 1 |
| 77 | State a kill count in README.md that the mutation table disagrees with | 1 |
| 78 | State a kill count in this file's prose that the row it names disagrees with | 1 |
| 79 | Say nine rows of the browser table record a state the page was really in, when seven carry the marker that says so | 1 |
| 80 | Take the marker off one browser row, so a failure the page really had reads as an invented one | 1 |
| 81 | Point a citation in call-e-feedback.md at the wrong lines of README.md | 1 |
| 82 | Shift a citation into another app so it names lines that exist and say something else | 1 |
| 83 | Reintroduce a stale gate count into evidence/README.md, the second file that states it | 1 |
| 84 | Switch a gate off with @pytest.mark.skipif rather than a call to pytest.skip | 1 |
| 85 | Switch a whole test file off from module scope with pytestmark | 1 |
| 86 | Make the masking loop assign each identifier to itself, checked against a page built from an authored fixture rather than the published one | 2 |
| 87 | Publish an answer in the register that the record behind it does not hold | 1 |
| 88 | Drop every field but the first from the register the page prints | 1 |
| 89 | Take the marker off one of the rows that needs a built page, so the note above the table counts more of them than the table carries | 1 |
| 90 | State a classifier test count in README.md that the module in the other language does not have, which is the count that was already wrong once | 1 |
| 91 | Put the credential guard back the way it was, refusing a key that starts with iams_live_ instead of requiring one that starts with iams_test_, so any key shape it does not recognise is sent to whatever host CALLE_BASE_URL names | 4 |
| 92 | Replace the retry backoff with return 0.0, so a failing upstream is retried at a family's number as fast as the network allows | 7 |
| 93 | Return the base delay for every attempt, so the policy retries at a fixed rate and never backs off | 2 |
| 94 | Remove the ceiling from the backoff, so attempt twelve waits half an hour and the policy becomes a way of never calling back | 2 |
| 95 | Have is_valid answer True for everything, which is what it did for every test in this suite before this row existed: it is exported in dispatch's __all__ and no code inside this app calls it | 1 |
| 96 | Have is_valid answer False for everything, so a schema-valid result is rejected | 1 |
| 97 | Drop the negation, so is_valid returns true exactly when the value is invalid | 1 |
| 99 | Keep the gate but stop the row claiming it needs a person, so the family is not dialled, is not a failure, and is also not on anyone's queue, which is the quietest of the three ways to lose them | 2 |
| 100 | Read an explicit voice=no as yes, so the column exists, is filled in correctly by the office, and changes nothing | 1 |
| 101 | Read a blank voice cell as no, so every family in a file that does not use the column stops being called | 10 |
| 102 | Ask the channel before consent, so a family that refused to be called is recorded as work owed to them on another channel | 1 |
| 103 | Stop excluding voice from context, which puts a disability record into the sentence the agent reads aloud on the call | 1 |
| 104 | Treat a voice value the reader does not recognise as reachable instead of raising, so a typo in that column silently decides that somebody gets telephoned | 1 |
| 105 | Put the skip counting back the way it was, skipped_no_consent=counts[Resolution.SKIPPED], so a run that was cancelled reports its unstarted rows as families who refused to be called | 2 |
| 106 | Stop counting the skips that are neither consent nor channel, so a reason added later disappears from the summary instead of showing up as unattributed | 2 |
| 107 | Put back a contrast pair naming a token page.css no longer declares, so the tool reports it unmeasured and the page keeps telling a reader that an unmeasured pair cannot read as a pass | 1 |
| 108 | Remove the pair covering a scoped re-cut of an ink token, so the colour a reader actually looks at inside a panel is measured by nothing | 1 |
| 109 | Put the locale back into lang="..." unescaped in the browser-side transcript renderer, the way it shipped, so a locale carrying a double quote closes the attribute and opens whatever follows it | 1 |
| 110 | Narrow esc to &, < and >, which leaves the check on the line above passing while the value it escapes can still close a quoted attribute | 1 |
| 111 | Rebuild the same attribute as a template literal with the value interpolated raw, which is how the hole survives a rewrite that touches nothing else | 1 |
| 112 | Retype the count under the browser-gate table rather than leave it to be counted, so the prose says eight rows record a state the page was really in where nine carry the marker | 1 |
| 113 | Drop the flattening from as_data and keep the length cap, so a roster field carrying a line break adds a paragraph to the instruction the agent reads on a call to a parent | 3 |
| 114 | Drop the length cap from as_data and keep the flattening, so one line is all a roster field needs and the line can be a brief | 1 |
| 115 | Return the roster value from as_data untouched, which is how build_task read it until this was fixed | 5 |
| 116 | Remove the sentence in build_task naming the three values as record fields, leaving a flattened injection to read as an aside the agent was told nothing about | 1 |
| 117 | Stop stepping the internal scroll boxes in the contrast gate, so the transcript's lower turns go back to being declined every run | 1 |
| 118 | Report the contrast census as zero instead of its real size, which is the number that makes an unmeasured count of zero mean anything | 1 |
| 119 | Take no census at all, so a run the probe never reached leaves no trace again | 1 |
| 120 | Identify a text run by its class and the first thirty characters of its text again, which folds two elements that share both into one and measures only one of them | 2 |
| 121 | Type the mutation count into the take-away card instead of counting the rows, which is the defect a reviewer found on the deployed page before this suite did | 2 |
| 122 | Put back The offline default never reaches it, the sentence that told a reader the default run does not use CALL-E when it executes three of the four anchored lines | 1 |
| 123 | Move calle-ai out of the runtime requirements, which would leave the README's reason the offline default runs CALL-E's own code true and beside the point | 1 |
| 124 | Type the size of the mutation table into the act 06 margin note again, the one of that page's three statements of it that the first version of this gate did not read | 1 |
| 125 | Say five real calls under a register that renders four, which is the shape a fifth receipt arriving would produce on its own | 1 |
| 126 | Change the enumerated field count in the locale fold so its own arithmetic stops reaching the comparison total it claims above | 1 |
| 127 | Stop sending X-Content-Type-Options, leaving the browser free to guess a type the deployment declared correctly | 1 |
| 128 | Open frame-ancestors from 'none' to 'self', which is the whole difference between a page that cannot be framed and one that can | 1 |
| 129 | Let style-src fall back to 'unsafe-inline', which grants every inline block and makes the three hashes beside it decorative | 1 |
| 130 | Grant script-src an origin the page never names, the shape a third-party allowance takes after the script it was added for is dropped | 1 |
| 131 | Change one character of the inline stylesheet's hash, which is what a policy describing an earlier build looks like | 1 |
| 132 | Narrow the header rule from every path to /index.html, so the modules and the eight audio clips are served with no policy at all | 5 |
| 133 | Hang a second inline event handler on the page, so 'unsafe-hashes' is widening the policy for something nobody decided to allow | 2 |
| 134 | Move the live ceiling from more than to at or more than, so a run of exactly the size the operator was told is allowed gets refused | 2 |
| 135 | Count rows rather than the calls a run would place, so a file of families who never consented is refused for spend it was never going to cost | 1 |
| 136 | Apply the live ceiling to the offline run, which phones nobody, capping a demonstration instead of a bill | 1 |
| 137 | Accept --max-calls and then ignore it, so the one deliberate way past the ceiling silently does nothing | 1 |
| 138 | Drop the number of families from the refusal, leaving an operator who is told the run was too big and not how big | 2 |
| 139 | Ask safeguarding_escalation only of rows whose resolution is resolved, so the four escalating cases in the run the page draws render as ordinary callbacks in the office queue | 1 |
| 140 | Let the report say the safeguarding window is this project's default whatever window was passed, so a district reads its own agreed clock into a number nobody chose | 1 |
| 141 | Accept --webhook-url and stop forwarding it to CALL-E, so a district's endpoint is promised an event that is never asked for | 1 |
| 142 | Let is_loopback answer yes to every address, so the double binds to a network on a flag nobody had to type | 1 |
| 143 | Parse --i-know-this-is-open and never consult it, leaving a guard that is written down and not run | 1 |
| 144 | Drop the override from the refusal text, so an operator with a real reason to open the port reads a wall instead of a choice | 1 |
| 145 | Put the animation data back behind a URL, so the policy refuses the fetch and the figure never plays | 1 |
| 146 | Hide the replaced still with element.hidden, which SVG does not implement, leaving it in the layout beside the animation | 1 |
| 147 | Size the animation to twice the still it replaces, so the page under it moves | 1 |
| 148 | Read a consent value nobody defined as a no, so a district whose export writes consented has every family dropped and reported as having refused | 1 |
| 149 | Read a row with fewer cells than its header, so a truncated export line becomes a family with no consent | 2 |
| 150 | Read a row with more cells than its header, so the surplus travels into the spoken instruction under the key None | 1 |
| 151 | Accept a column that appears twice, silently discarding one of the two values, which for phones or consent is the one that decides whether a family is called | 1 |
| 152 | Let a file that is not the promised encoding raise UnicodeDecodeError instead of naming the encoding it tried | 1 |
| 153 | Read a file containing a NUL byte, so a half-written export is treated as text and a child's name is spoken with a gap in it | 1 |
| 154 | Let a cell past the CSV field limit raise _csv.Error, which names neither the file nor the cause | 1 |
| 155 | Call from an export older than the window, which telephones the families of children who are in school today | 2 |
| 156 | Call from an export already called from, telephoning every family in it twice | 2 |
| 157 | Key the processed ledger on the filename rather than the content, so a job that rewrites the same rows under a new date stamp gets through | 1 |
| 158 | Record an export as called-from before its rows are known to be readable, which strands the operator who fixes it | 1 |
| 159 | Drop the sentence in the ledger header saying what deleting a line permits | 1 |
| 160 | Restore call["id"] on a create response that carries no id, so a request CALL-E accepted raises KeyError and is reported as a call nobody answered | 1 |
| 161 | Let a response shape the classifier does not model raise out of the handler after the id has left the in-flight set, so a placed, completed, billed call is reported FAILED with its id nowhere | 3 |
| 162 | Stop retrying a 5xx whose body is not JSON, which is the shape a proxy's own bad-gateway page has and the one class of failure a retry exists to absorb | 1 |
| 163 | Stop naming an unaccountable call in the run summary unless the run was cancelled, which is the branch that does not happen by itself | 1 |
| 164 | Stop printing the block that names a call this run placed and cannot account for | 1 |
| 165 | Drop not_recallable from --json, leaving a machine reader unable to see what the run left behind | 1 |
| 166 | Print the unaccountable call's id with no row beside it, so nobody can say which family it was for | 1 |
| 167 | Put back the n8n recipe's hardcoded escalation: "none" on the all-unknown branch, so the same call is a safeguarding case in Python and an ordinary callback in the workflow | 1 |
| 168 | Remove the schema check from the n8n recipe, so a value outside the enum closes a record there and does not here | 1 |
| 169 | Accept a nested object schema at construction, which problems() never recurses into, so every rule inside it is ignored and the answer is reported valid | 1 |
| 170 | Accept an array property, which has no items support, so a list of anything at all is reported valid | 1 |
| 171 | Accept an empty --again label, so a family is called a second time in one morning with no reason on the record | 1 |
| 172 | Stop normalising the label, so Locale Fix and locale-fix are two keys for one correction and the fix runs twice | 2 |
| 173 | Accept the label and never put it in the idempotency key, so the corrected run is refused exactly as the uncorrected one was | 1 |
| 174 | Stop printing the way out of a reused key, leaving a refusal that reads as a dead end until tomorrow | 1 |
| 175 | Stop recording the correction in the receipt | 1 |
| 176 | Stamp the double's created_at off one shared clock that advances 30 seconds a step and is never pulled back, so a run of 150 rows reports 27 of them with an unknown provenance | 1 |
| 177 | Ignore a pinned clock, so a test that asked for determinism stops getting it | 1 |
| 178 | Call phone.startswith("+") E.164 again in the double, so +91 5550 000001 is accepted and dialled offline where production would refuse it | 6 |
| 179 | Hardcode an off-palette accent in the README's path figure, so the drawing keeps a colour the page has moved on from | 1 |
| 180 | Drop the mono fallback chain from the path figure, so a reader without the webfont gets the browser default at a different width | 1 |
| 181 | Gut the path figure's desc, leaving a diagram a screen reader cannot report | 1 |
| 182 | Hand-edit the committed path figure, so the README shows something its generator does not write | 1 |
| 183 | Set an ending's second line in the palest ink the palette holds, on its own coloured plate, so a label on the page's own figure drops below WCAG AA | 1 |
| 184 | Put the escalation panel's dark ink on a mid-grey plate, which is the pairing a drawing loses track of because the ink and the ground are set in two different places in the file | 1 |
| 185 | Serve a document page with its markdown link left as written for the tree (receipt-provenance.md beside it), which is what all eight of them did on the deployment | 1 |
| 186 | Point an in-page anchor at an id that is not on the page, so the click scrolls nowhere and reports nothing | 1 |
| 187 | Give a published page an href in a scheme the link gate does not classify, to check it is counted unmeasured rather than quietly skipped | 1 |
| 188 | Make a gate raise instead of returning, by pointing a rail link at a deleted element, to check the run still reports the other fifteen | 1 |
| 189 | Stop a withdrawn consent record from refusing the call, which is the one misreading here that telephones a family who asked not to be telephoned | 4 |
| 190 | Make a record expiring today stop covering today, off by one at the boundary an expiry exists to define | 1 |
| 191 | Let one family's consent record cover any row that points at it, which turns a register with one good record into a permission for the roster | 1 |
| 192 | Ignore an unrecognised key on a consent record instead of refusing it, so a misspelled withdrawn_at reads as a record nobody withdrew | 1 |
| 193 | Count a row refused on a dated record by exact reason rather than by prefix, which files a family who withdrew consent under the bucket for a cancelled run | 1 |
| 194 | Resolve a header row matching two export formats by order instead of refusing it, so which column is the identifier is decided by the order this file lists formats in | 1 |
| 195 | Let a recognised export with no consent column dial anyway, which is the reading of a missing permission this software exists to refuse | 5 |
| 196 | Take only the first source column for a phone number, so a row carrying a number under sms alone has none | 2 |
| 197 | Hold a sibling behind a row nobody was going to dial, which reports a call saved that was never going to be placed | 3 |
| 198 | Drop the id fallback on an unparseable number, which collects every row whose number is punctuation into one household | 1 |
| 199 | Dial the last row of a household instead of the one the export put first, so a receipt cannot be read against the district's own file | 6 |
| 200 | Stop telling the dialled row who else in the house is absent, which asks a parent about one child while two more of hers are held | 1 |
| 201 | Count held rows in no bucket, which reports a household the run grouped as a run somebody cancelled | 1 |
| 202 | Stop checking who answered before reading what they said, so a brother saying the child is ill closes a record only a guardian can close | 4 |
| 203 | Read a call that did not record who answered as a call answered by somebody who is not the guardian, which invents a fact about a call while trying to be careful | 7 |
| 204 | Read everybody who answers as the guardian, which is the state this was written to leave | 7 |
| 205 | Report closures made with nobody recorded as zero, which hides the exposure by publishing a total that looks clean | 3 |
| 206 | Put the attempt count back under the word calls placed, six lines under a line saying six rows were attempted | 4 |
| 207 | Count a row this run dialled but made no attempt on as a call | 1 |
| 208 | Multiply an escalation bound that does not exist, which is what killed the whole page build on a run that answered nothing | 1 |
| 209 | Dial a row carrying a number the record does not name | 2 |
| 210 | Compare telephone numbers as text, so a register a person typed covers nothing | 2 |
| 211 | Read a comma-joined string as one telephone number | 1 |
| 212 | Count a refused row as a call that rested on a record naming no number | 1 |
| 213 | Stop printing how many dialled rows nobody can point at a number for | 2 |
| 214 | Record a refused row as exposure, which reports a family nobody rang | 1 |
| 215 | Build a forge URL for a cited file that is not in the tree | 2 |
| 216 | Ignore an unknown key in a scenario file | 1 |
| 217 | Load a scenario that binds nothing | 1 |
| 218 | Export a scenario without its transcripts | 2 |
| 219 | Accept a transcript turn that is not a speaker and a line | 1 |
| 220 | Take --outcomes and bind none of it | 1 |
| 221 | Report the exported scenario as current whatever is on disk | 1 |
| 222 | Default a scenario entry to nobody picking up | 1 |
| 223 | Compare a number with no digits in it as equal to another | 1 |
| 224 | Load a consent record whose phone entry is a word | 1 |
| 225 | Keep a work file phone entry that is a word and dial it | 1 |
| 226 | Shorten an identifier too short to have a middle | 1 |
| 227 | Load a scenario that answers on a negative index | 1 |
| 228 | Report every authorised call as one whose number was named | 1 |
| 229 | Label the two-file node --test command on the take-away card with the classifier file's own count, so the card offers 27 for a command that runs 35 Needs the built page. | 1 |
| 230 | Drop the cd from that command, so it names two files that are not under the directory this page puts a reader in and runs nothing at all Needs the built page. | 1 |
| 231 | Label double_conformance.py --check with a test count, which is what it carried before: that command runs no tests and prints one line Needs the built page. | 1 |
| 232 | State the node suite as 32 passing in the plugin's manifest.json | 1 |
| 233 | State the classifier's own count as 24 in that manifest | 1 |
| 234 | State the node suite as 32 passing in the plugin README | 1 |
| 235 | Say the receipts are on the evidence page in evidence/README.md, with a pronoun carrying the subject across the full stop, which is how the sentence was written | 1 |
| 236 | Say it in the README's money paragraph | 1 |
| 237 | Say it in the README's reading list | 1 |
| 238 | Say it in the README's privacy paragraph, eighty lines below the other one | 1 |
| 239 | Say it of the replay receipt in docs/receipt-provenance.md, which is the receipt carrying the claim that no telephone rang | 1 |
| 240 | Say it in the provenance line make_shape_fixtures.py stamps inside every generated fixture | 2 |
| 241 | Say it in that file's own docstring | 1 |
| 242 | Say it in the comment over the generated response fixtures in tests/test_dispatch.py | 1 |
| 243 | Say it in the footer under the escalation queue, with the page named first and the receipts after it, which is the wording the first version of the gate walked past Needs the built page. | 2 |
| 244 | Say it in the caption under act 03, which is the page telling a reader that a file is on the page Needs the built page. | 1 |
| 245 | Print one more queue row in the footer than the page drew Needs the built page. | 2 |
| 246 | Take the row the telephone cannot reach out of the district export, returning the channel gate to being demonstrated by nothing | 2 |
| 247 | Rename the channel column in that export, so every row reads as reachable | 2 |
| 248 | State the collected test count flat on the stat card, where two of them skip Needs the built page. | 2 |
| 249 | Point the transcript provenance at a document that is in no clone of this repository Needs the built page. | 2 |
| 250 | Have the transcript provenance call the waveforms the only audio that ships, on a build that ships the recordings and plays them Needs the built page. | 2 |
| 251 | State four runtime call sites above a list of five | 2 |
| 252 | Drop the directory from act 08, so neither of the two commands it prints runs from the root of a fresh clone Needs the built page. | 2 |
| 253 | Take the language ceiling off the page, which is what a reword of act 01 does to it now that it is no longer welded to the masthead Needs the built page. | 1 |
| 254 | Point the language ceiling at an act this page does not have, so the one limit a school trustee can check names no demonstration Needs the built page. | 1 |
| 255 | Put the language promise back in the masthead, now that the limit answering it has moved one screen down Needs the built page. | 1 |
| 256 | Declare --receipts required again in tools/throughput.py, so a reviewer running the documented command is told they used the tool wrongly | 1 |
| 257 | Report the missing recordings from tools/video_facts.py as a SystemExit, which exits 1 and reads as a check that failed | 1 |
| 258 | Take the shared first word off the page builder's own answer, so four tools report the third outcome in one word and the fifth in its own | 1 |
| 259 | Strip the flag, the environment variable and the committed file out of one COULD-NOT-MEASURE message, leaving a reviewer told what is missing and nowhere to go for it | 1 |
| 260 | Say in the README that the OneRoster run prints the platform refusing Spanish on a real call, when no call has been placed in Spanish and the refusal is the double's | 1 |
| 261 | Say the same in the caption under act 01, in the words the reviewer who asked for that caption wrote it in Needs the built page. | 1 |
| 262 | State the escalation count the receipts recorded before the correction as the current one, in the file that narrates the correction two paragraphs below it | 1 |
| 263 | Offer the calls placed as the sample in all three rows of a table whose column is a rate per answered call | 1 |
| 264 | Call the sample twelve calls in the sentence a district is told to take from that table, where the figures are over the eleven that answered | 1 |
| 265 | Label the bound on the money card with the calls placed rather than the calls answered, eleven lines above a paragraph that reads it correctly out of the same record Needs the built page. | 1 |
| 266 | Label the bound on the money card with the sample it was measured on and not the quantity it bounds, so 24 per 100 reads as what eleven calls cannot rule out about escalations, when the escalation rate they measured is about twice it Needs the built page. | 1 |
| 267 | Drop the escalation rate's own bound from the money card while the sentence under it still counts three rates, leaving the wider of the two readings unpublished Needs the built page. | 2 |
| 268 | State the wrong number of rates in the sentence generated beside them, so the card's own summary of itself is off by one Needs the built page. | 1 |
| 269 | Put the escalation bound in the column headed net-new per 100 answered calls, which is the mistake this document records making once with 24 against 50.4: two right figures and a comparison that is not one | 1 |
| 270 | Drift the cost the pessimistic reading prices out to by a cent in the money document, away from what the tool computes | 1 |
| 271 | Compute the escalation rate's bound off the net-new count, so the two bounds are the same number and the card publishes the narrow reading twice while calling one of them the widest Needs the built page. | 3 |
| 272 | Drift the derived absence rate by one per thousand in the line that shows the arithmetic, so the document publishes a rate its own registered inputs do not produce | 1 |
| 273 | Round the headline volume up to a number the derivation does not reach, which is the figure a reader carries away and the only one most will remember | 1 |
| 274 | State the wrong rate for a 175-day school year, hiding how much the largest lever on this figure actually moves it | 1 |
| 275 | Remove the publisher's definition of unexcused, which is the sentence that makes the volume figure a ceiling on what this software would call about rather than a measure of it | 1 |
| 276 | Publish the annual saving and drop the annual cost the widest reading of the same calls produces, which is the vendor move this entry was built to argue against | 1 |
| 277 | Close a record by reading a reassuring phrase out of the transcript, which is the improvement somebody would plausibly make to this tool and is the exact defect the rest of this entry exists to catch | 1 |
| 278 | Decide the outcome here instead of calling the function the live path calls, so a district adopting this over its own dialler gets a second rule that agrees with the first only until one of them changes | 1 |
| 279 | Silently ignore a result field the schema does not define, so a district that mistypes one field in its mapping gets records filed undetermined for a reason nothing on the output names | 1 |
| 280 | Abort instead of reporting could-not-measure when there is nothing to read, folding a third outcome back into a failure | 1 |
| 281 | Audit another dialler's calls without passing the numbers they were placed to, so a consent record covering a different number than the one dialled passes. Consent attaches to the number called | 1 |
| 282 | Judge a call nobody answered on the result attached to it, and treat a record that does not say whether it was answered as though nobody was there | 1 |
| 283 | Escape the limits list in act 07 with the escaper that escapes everything, so the two commands that section tells a reader to run reach the page as literal backticks instead of code Needs the built page. | 1 |
| 284 | Write the markup into the limits data as well, which is the shape act 07 really shipped: the command a reader is told to run arrives with its code tags visible as text around it, and an apostrophe arrives as a numeric character reference Needs the built page. | 4 |
| 285 | Promote the backticks in a mutation row and stop, which is what the page did for as long as the table has existed: twenty-six rows show the marker under this table with its asterisks Needs the built page. | 1 |
| 286 | Promote bold and stop, so the one row drawing a distinction between any required field and all of them shows the emphasis as punctuation instead Needs the built page. | 1 |
| 287 | Label the ceiling on the money card as what a call can save, eighty lines from a README that calls the same figure a ceiling and not a saving Needs the built page. | 1 |
| 288 | Drop the sentence naming which of the four money figures to quote and which to plan against, leaving a reader to pick Needs the built page. | 1 |
| 289 | Mark a drop directory's export as one calls have been placed from at the moment it is read, which is before the confirmation flag, before the key check, before the credential origin, before the call ceiling, and on every offline run | 2 |
| 290 | Mark the export whatever the run did, so a rehearsal against the bundled double, which rings no house, burns the file the morning's real calls come from | 2 |
| 291 | Mark the export on a wave that dialled nobody, where every row was held for a person on consent, a shared household number or a language this cannot speak, and those rows are tomorrow's work out of the same file | 1 |
| 292 | Record that the run stopped without setting the flag every worker reads before it dials again, so an operator's Ctrl-C is written on the receipt and the wave carries on out of the queue and out of the backoffs | 3 |
| 293 | Exit zero from a run that was stopped part way, which is what a cron job wrapping this reads as a morning where every family was called | 1 |
| 294 | Count the spend ceiling on consent and reachability alone, which is two of the four things that stop a row being dialled, so a file placing two calls is refused as four families and the refusal names the wrong number to raise it to | 1 |
| 295 | Read a record's answered as yes on any word, so a call nobody picked up is closed on the result sitting beside it, which is this entry's founding defect arriving through the adoption path | 3 |
| 296 | Iterate a single telephone number written as a string, so a consent refusal tells an attendance officer the record covers one number and the row carries twelve | 1 |
| 297 | Accept a CSV naming one column twice, where the reader keeps the last value silently, so column order decides whether a child's absence is closed | 1 |
| 298 | Crash on a records file that is not UTF-8, taking the exit code this tool reserves for a consent finding, which a district exporting from a Windows codepage hits on the first accented surname | 1 |
| 299 | Crash on a consent register that does not validate, so a script cannot tell one of these calls resting on nothing from a typo in the register file | 1 |
| 300 | Exit zero from --fail-on-uncovered on a call resting on a bare boolean, while the line above the exit reads on a boolean and the flag's help says exit one when a call rests on no consent record | 1 |
| 301 | Print the closed rows inside the queue, under a heading about what needs a person, each carrying the sentence that nothing here needs one | 1 |
| 302 | Publish the absence volume and the escalation rate and never multiply them, which is what a district buyer said was worth more than any figure already on the page | 1 |
| 303 | Understate the escalations a morning's volume produces, so a pilot is sized on the calls rather than on the callbacks and the queue it creates is blamed on the software | 1 |
| 304 | State the commit-provenance disclosure as an exact pair, which both halves of change on every push and which nothing recounts, making the entry's one honesty disclosure the one claim it does not check | 1 |
| 305 | Read the pair on the page's first screen out of a sentence in the README instead of the measurement sitting beside it, so a stale sentence and a stale card agree with each other and disagree with the suite | 1 |
| 306 | Name records in a fixture's own comment that the fixture does not contain, so a reader following the comment finds neither | 1 |
| 307 | Print the other N where N is all of them, so a sentence says the rule marked five calls and the other five gave nothing usable | 1 |
| 308 | Annualise the ceiling without subtracting what the calls cost, against a loss on the same line that is already stated net, which runs in this entry's favour on the one page a board reads | 1 |
| 309 | Read the cancel flag before the first attempt only, so an item whose first attempt timed out waits out its backoff and telephones the family after the operator has pressed Ctrl-C, holding a request that may already have started that same telephone ringing | 2 |
| 310 | Take the pair on the page's first screen off the recorded pass count rather than the tests the tree can run, which is a number the gate holding the file against the page lowers by failing, so a stale card has no value it can correct itself to | 1 |
| 311 | Read a placed call's id out of the poll response rather than out of the create that returned it, so a body answering a poll without one produces a queue row carrying no id beside a receipt naming the call, and the row a clerk reads says nobody was telephoned | 1 |
| 312 | Put one of two records for the same pupil in the closed pile while the other says a person has to ring back, so the pile a clerk stops reading at holds a child whose absence nobody has explained | 1 |
| 313 | Answer a spreadsheet that exported its header and no rows with a sentence about blank and commented lines, which a spreadsheet has neither of, leaving the district the right exit code and no idea what to fix | 1 |
| 314 | Set the count in the sentence under the money card next to the row that makes it true, so the two cannot disagree, and the gate written to catch them disagreeing cannot fail | 1 |
| 315 | State twenty-eight unexplained absences per 1,000 as the figure to use rather than a ceiling on it, which is the sentence that stops a reader multiplying the per-call money by every absence a district records | 1 |
| 316 | Call a string method on the path argparse hands back, so a records file with nothing in it raises rather than printing could-not-measure, which turns the one outcome this tool reserves for what it cannot judge into a traceback | 1 |
| 317 | Blank the English on one Tamil turn in the gloss file, so a line a reader is promised a translation of gets an empty one, which renders as the Tamil alone with a gap under it | 1 |
| 318 | Leave a Tamil word inside an English gloss, so the translation a reader was given to read is partly the thing they could not read | 1 |
| 319 | Add a gloss row for a line that holds no Tamil, so the file that exists to say which lines were translated starts claiming a line nobody needed translated | 1 |
| 320 | Empty the gloss file's statement of what wrote the English, so a reader deciding how much to trust a translation has nothing to decide from | 1 |
| 321 | Stop the builder refusing a Tamil line the gloss file has no English for, so the page publishes one untranslated line in the middle of a scroller and nothing says so | 2 |
| 322 | Stop the builder refusing a call in another language that the gloss file does not name, so a call added later reaches the page with none of its turns translated | 1 |
| 323 | Look each gloss up by its position in the list rather than by what the line says, so a transcript the transcriber split differently puts every English sentence under the wrong Tamil one, with a gloss present on every line | 1 |
| 324 | Decide which turns need English from the call's locale rather than from each line's own text, so a call labelled ta-IN that opens with an English announcement demands a translation of English, and the authored fixture the suite builds a page from stops building at all | 1 |
| 325 | Drop the English span from a rendered turn while leaving it in the published data, so the transcript a reader with no JavaScript meets is the one version of it with no translation | 2 |
| 326 | Drop the note under a translated transcript saying the English was written afterwards, so a page presenting a translation stops saying it is one, which is a claim about what was on the recording | 1 |
| 327 | Retype one consonant of the Tamil quoted in docs/the-legal-surface.md, which is the defect that was actually in the tree: the fourth word of the opening announcement carried the wrong one of two similar letters, inside the paragraph whose whole argument is that the disclosure a parent hears is the disclosure on the recording | 1 |
| 328 | Remove the English under a Tamil line in a document, so one file in the submitted tree prints two sentences of Tamil with no translation anywhere near them, which is where this started | 1 |
| 329 | Delete the attrs row from the runtime table, which is the defect that was actually in the tree: a direct requirement of the CALL-E SDK with no licence recorded, under a sentence saying nothing else was needed at runtime | 1 |
| 330 | State a version for httpx that is not the version installed, so the file describes a dependency tree that a reader checking it would not find | 1 |
| 331 | Call certifi MIT. It is MPL-2.0, and it is the only weak-copyleft row in the runtime table, so this is the mistake an author makes by assuming a licence rather than reading one | 1 |
| 332 | Say the browser-gate lock file resolves forty packages when it resolves eighty-three, so a count nobody could check sits next to a claim that all of them are permissive | 1 |
| 333 | Let one browser-gate dependency arrive under GPL while the file still says none is copyleft, which is how a licence claim goes stale: not by being written wrongly, but by a lock file moving under it | 1 |
| 334 | Remove the note explaining the AGPL dependency while requirements-dev.txt still pins it, so a reviewer of an MIT repository meets an AGPL import with nothing written about it anywhere | 1 |
| 335 | Put a kill count of 1 back beside the substring row in docs/proving-a-gate-fires.md, which is the defect that was actually in the tree: the document a reader is told to reproduce the mutations from copied a row whole and disagreed with the table it copied from, and the gate that checks these counts read only the README | 1 |
| 336 | State a kill count in the README that the table does not measure for the substring row. The sentence used to name a test instead of a number, which is why nothing checked it while its three neighbours were checked | 1 |
| 337 | State a call count on the first-screen dateline that evidence/recorded-calls.json does not measure, so the one number a reviewer meets before the fold is the one nothing checks Needs the built page. | 1 |
| 338 | State a price on the dateline that the account was never billed, against the figure read off the usage panel on 2026-09-07 Needs the built page. | 1 |
| 339 | Write the dateline's four numbers into the builder as literals instead of computing them. This is the failure the gate exists for: four values that are right the day they are typed and silently stop being right | 1 |
| 340 | Render the dateline when no receipts are on the machine, so the first screen carries four numbers no reader of that build can check | 1 |
| 341 | Guard the sibling sentence on the raw roster value while rendering the sanitised one. This is the defect that was in the tree: str.strip() leaves a zero-width space where as_data removes it, so a name made only of format characters passed the guard and the instruction that would have reached a real call asked why nobody was absent | 1 |
| 342 | Take the sanitiser off the sibling names, so a format character in a roster cell reaches the words CALL-E speaks | 2 |
| 343 | Use the singular verb however many siblings there are, so a call about two children asks why they is absent | 1 |
| 344 | Drop the sibling sentence entirely, so a guardian with three absent children is asked about one and the other two records are held on an answer nobody gave | 3 |
| 345 | Match committed transcript text by the key name transcript_turns instead of by the shape of a turn. This is the defect that was in the tree, and it is the worst kind: tools/glosses.json holds 53 turns of four real calls under turns, so the one committed file carrying real conversation was the single file this gate could not see, and the suite was green because the gate was looking in the wrong place | 1 |
| 346 | Count a turn only when it carries both text and speaker, so the Tamil and English pairs the gloss file is made of stop reading as dialogue | 1 |
| 347 | Empty the declared exception list while the file it names is still tracked, so real conversation sits in the tree with nothing recording that anybody decided it could | 2 |
| 348 | Stop the gate walking into nested objects, so a conversation one level below the root of a committed document passes | 1 |
| 349 | Render the documents with commonmark alone, which has no tables, so six documents publish their table rows as paragraphs of pipe characters. This is the defect that was in the tree: what-a-pilot-would-look-like opened its Shape section with eleven rows of | Scale | Two schools in one district. | set as running prose, on the page the money card sends a reader to | 3 |
| 350 | Skip the table pass entirely, so no cell carries the name of its column and an empty header row stays on the page as a rule above a band of nothing | 2 |
| 351 | Treat a column with no name in the header as an ordinary value rather than the term the row is about, so the money document's first column loses the mark that stacks it first and sets it in the label face | 2 |
| 352 | Take the header row off every table rather than only off one whose cells are all empty, so a table that names its columns loses the names | 2 |
| 353 | Return to what this module did for as long as it existed: keep the set of allowed tags as a comment and check nothing against it, so any tag the renderer emits reaches a public page with no style written for it | 1 |
| 354 | Take one document off the published list while it is still cited by name from another page, which is how docs/district-ingest.md and docs/consent-record.md came to be unreachable | 1 |
| 355 | Accept a name in the withheld register with no reason written beside it, so a document can be kept off the site by an empty string | 1 |
| 356 | Leave a document table with only the roles a stylesheet leaves it, so the stacked form under 38rem is a run of blocks to a screen reader: no row, no column, and no header attached to any cell | 2 |
| 357 | Take scope off the header cells of the page's five tables, so a header stops saying whether it runs down a column or across a row at the width where the stylesheet has already taken the implicit answer away Needs the built page. | 1 |
| 358 | Take the caption off one table, so it is announced by its size and nothing else Needs the built page. | 1 |
A test that has never been observed to fail has not been shown to test anything.
Two things worth taking, whatever you are building.
Record the identifier the vendor is keyed on
The id an API returns and the id its billing page shows are not always the same one. Recording only the first makes a receipt uncheckable by anyone outside the repository that wrote it.
Make the safety rules prove themselves
Deterministic safety triage guarantees no unconfirmed call slips through: a call that came back without a confirmed answer is owned by a person, not closed by a model.
How that is checked
358 deliberate changes, each reverted, each recorded with the number of tests that failed. Row 57 is the one no test caught, and finding out why is what this table is for.
What is not true.
Five limits, each with what would close it, reported here without complaint.
Five limits, and what would close each one
CALL-E offers English and no other language in the United States. Every figure priced on this page is American, and the language column cannot be delivered to a United States number today. Every call this project has placed went to an Indian number, where Tamil and Hindi are available.
Nothing in this app changes it. Run
python -m firstbell --work-file examples/absences-oneroster.csvand the second row prints the refusal in the platform's own words. Until it changes, the part of this that works in a United States district is the three outcomes, the consent gate and the structured reason, over whichever dialler the district already owns. That is a command and not a consolation:python tools/adopt_call_records.py --records examples/other-dialler-records.jsonl --consent-register examples/other-dialler-consent.jsonfiles six calls this software never placed, says why each landed where it did, and audits all six against the district's own consent register. One of them carries a transcript in which a parent says plainly that the child is at home with her, and it still goes to a person, because reading a guardian’s confirmation out of prose is the defect this entry was built to catch wearing better clothes. It also narrows the ceiling above: it binds while CALL-E places the call, and a district with Spanish-speaking families can keep the multilingual dialler it already pays for and take this layer over what that dialler returns. Nothing in that tool reads the language of a call, because it never reads the call.Calls to India arrived from a United States caller identity, shown as Oakland, California. A family will not answer an unknown foreign number about their child.
Fixable by the operator with a local number on the account. Nothing in this app changes it.
CALL-E has no cancel endpoint. Once a call is placed there is no route to stop it.
The concurrency cap is the only brake that exists, so it is set low and the run reports what was already in flight when a stop was requested.
The agent does not enforce its own exit. On one call it announced it was ending, then restarted its opening disclosure.
Reported to the vendor. The transcript is committed.
The locale result rests on one bilingual speaker who knew what was being tested, one language pair and one region.
It is a pilot, and it is written up as one. The pre-registered comparison count is committed so nobody has to take the framing on trust.
Run the whole thing with no account.
Test our verified system offline right now, with no API key and no account.
cd apps/python/firstbell
pip install -r requirements-dev.txt
python -m firstbell --work-file examples/absences.csv
Watch that exact command run, line by line
The local double is mounted as an httpx transport underneath a real calle.CalleClient.
Produced by running exactly that when this page was built, and it is all below. Watch it run to see the rows land one at a time.
OFFLINE. No telephone call will be placed and no CALL-E account is needed.
The CALL-E SDK is running: this is a real calle.CalleClient with the local double
mounted on its transport, so every request and every error is CALL-E's own code.
7 row(s) from examples\absences.csv, concurrency 3.
[ok ] S-1041 schema-valid answer received
[ok ] S-1042 schema-valid answer received
[ok ] S-1043 schema-valid answer received
[HUMAN] S-1044 the call completed but returned no structured result
[skip ] S-1045 no recorded consent to be called
[HUMAN] S-1046 nobody answered after trying 2 number(s)
[SAFEG] S-1047 schema-valid answer received, escalated as safeguarding and not closed automatically
What this run was worth
attempted 6
resolved 4 schema-valid reason on record
of those, escalated 1 answer received, still not closed
undetermined 1 call happened, no usable answer, needs a person
failed 1 nobody reached on any number
skipped, no consent 1
attempts placed 8 on 6 call(s): a row with two numbers can take two
(no telephone call was placed)
resolution rate 50% closed, not merely answered
consent
on a record 0 dated, voice, attendance, not withdrawn
on a boolean 6 a column that says yes, which is not a record
docs/consent-record.md is the schema that replaces it
this run used none. For the path with records:
python -m firstbell --work-file examples/absences-with-consent.csv \
--consent-records examples/consent-register.json
who answered, on the records this run closed
a guardian 3 the call recorded a parent or guardian on the line
reached in-language
en-IN 1
hi-IN 1
ta-IN 1
non-English families 2 of 3 resolved
still open, by language
en-IN 1 needs a person
ta-IN 2 needs a person
funding recovered not claimed
Explaining an absence does not make a student
present, so no attendance funding is recovered by
this call. Seven US states funded on daily
attendance as of 2022 (PPIC, citing the Urban
Institute). Pass --funding-rate with a source
if your jurisdiction is one of them.
staff time avoided
attempts billed 8
attempts removed 4 behind the 3 record(s) this run closed
attempts still open 4 on somebody's desk, so not counted as saved
break-even $0.20 per call, for every minute one manual attempt takes
so cheaper than the desk below $0.59 a call at 3 minutes an attempt
$23.55/hour, from $48,980 over 2,080 h. Secretaries and administrative
assistants, Educational services; state, local, and private, 2025.
Source: US Bureau of Labor Statistics, Occupational Outlook Handbook
https://www.bls.gov/ooh/office-and-administrative-support/secretaries-and-administrative-assistants.htm
work this run adds
net-new escalations 1 of 5 answered call(s) would have closed
without the safeguarding rule, so they are work
that did not exist before this run
added $0.08 per billed attempt, for every minute one
callback takes the safeguarding lead
ceiling after it $0.35 a call, at 3 minutes for each of the two
(from $0.59: the line above ignores this)
4 attempt(s) removed at 3 minutes is $4.71 of desk time,
less 1 callback(s) at 3 minutes, $1.87 of counsellor time,
over the 8 attempt(s) billed
saving ends at 50.4 net-new per 100 answered calls. Above that,
the callbacks this rule creates cost more than the
attempts the run removes. This run measured 20.0.
$37.40/hour, from $77,800 over 2,080 h. School and career counselors and
advisors, Elementary and secondary schools; local, 2025. Source: US
Bureau of Labor Statistics, Occupational Outlook Handbook
https://www.bls.gov/ooh/community-and-social-service/school-and-career-counselors.htm
3 case(s) need a person. Nothing here is closed:
1 of those cases is safeguarding: the parent did not confirm they already knew.
A school would have to answer these within 30 minutes (this project's default, which no district has agreed to).
!! S-1047 schema-valid answer received, escalated as safeguarding and not closed automatically
S-1044 the call completed but returned no structured result
S-1046 nobody answered after trying 2 number(s)Source, tests and receipts: a pull request into CALLE-AI/awesome-phone-call-agents, under apps/python/firstbell. The branch was not pushed when this page was built, so the pull request is in the submission form rather than linked here.
A demo film runs 2 min 44 and is measured in evidence/film.json, which records its length, its shot count, how much of it carries sound and the digest of the file. It was not uploaded when this page was built, so its link is in the submission form too.
Where to go next
Everything this rests on, and how to leave this page to check it.
Two pieces of this you can take
A CALL-E written from the published API, mounted on the SDK's own transport, so the client under test is the shipped one. Every offline run in this entry is measured against it, and the record proving it matches production compares 11 recorded responses path by path and type by type.
cd apps/python/firstbell && python tools/double_conformance.py --check38 API paths, 0 missingThe same rule as an n8n recipe
The three-outcome classifier is not locked inside a Python CLI. It ships as an importable n8n workflow, generated from the tested module by a committed script so the two cannot drift. It imports inactive, and its dry run places no calls and needs no API key.
cd plugins/firstbell-absence-calls && node --test examples/classify.test.mjs examples/workflow-shape.test.mjs35 tests, no n8n installed
Every document, and every outside figure with its publisher
- What a pilot would look like
Two schools, six weeks, the four numbers measured before switch-on, and the children this software is not allowed to call.
- The money, in full
Why the headline figure is a ceiling and not a saving, what the safeguarding rule costs at the grade it lands on, and the rate above which this software costs a district money.
- The file your district already exports
OneRoster, Clever or a header nobody here has seen, read without editing it. The two columns no export carries, what filling them costs, and why three children in one house are one telephone call.
- The legal surface
Seven questions a district's counsel asks before this software telephones a parent. FERPA, the TCPA, retention, and which four of them are still open.
- The consent record
A column that says yes is not a record of permission. The shape of one, the eight checks a call passes before a telephone rings, and the three decisions that stay with the district.
- Locale is not only a hint
Why the same call in Tamil is one column in a work file and not a second code path, and where that stops being true.
- Proving a gate fires
How each check in this repository was broken on purpose to confirm it notices, and what that costs when it is skipped.
- Where a receipt comes from
What is in a receipt, what was added afterwards, and how to tell a real call from a replay without trusting this page.
- The offline CALL-E, and how to take it
A CALL-E that dials nobody, written from the published API and checked against 11 recorded production responses. Two ways to mount it, and the three things about it that are not true.
The outside figures, and who published them
- 14 million United States students chronically absent in the 2021-22 school year, which the publisher defines as missing at least 10 percent of school days
Institute of Education Sciences, read at source 2026-09-07
- 17.63% persistent absence rate across the autumn and spring terms of 2024/25 in England
Department for Education, read at source 2026-09-06
- 19.23% the same rate a year earlier, autumn and spring terms 2023/24
Department for Education, read at source 2026-09-06
- 10.53% the pre-pandemic rate, autumn and spring terms 2018/19
Department for Education, read at source 2026-09-06
- 78.3% share of the United States population aged 5 and over who spoke only English at home, 2018-2022 American Community Survey five-year estimates
US Census Bureau, read at source 2026-09-05
- 21.7% the remainder, who speak a language other than English at home
US Census Bureau, read at source 2026-09-05
- 99,297 Operating public elementary and secondary schools in the United States, school year 2023-24
National Center for Education Statistics, Common Core of Data, read at source 2026-09-07
- 13,303 Operating regular school districts in the United States, school year 2023-24
National Center for Education Statistics, Common Core of Data, read at source 2026-09-07
- 157,664 Total purchase cost approved by one North Carolina school district for its annual PowerSchool contract renewal, 2024-25, paid from the capital outlay technology budget
Chapel Hill-Carrboro City Schools Board of Education, Agenda Abstract, 15 August 2024, read at source 2026-09-07
- 11,353 students enrolled in Chapel Hill-Carrboro City Schools, North Carolina, in the 2024-25 school year, which is the year of the system renewal priced above it
National Center for Education Statistics, Common Core of Data, US Department of Education, read at source 2026-09-07
- 6,215 Texas Basic Allotment per student in average daily attendance, school year 2025-26
Texas Education Agency, read at source 2026-09-07
- 48,980 US dollars, median annual wage for secretaries and administrative assistants in educational services, which is the grade of the work this app takes off a school office desk
US Bureau of Labor Statistics, read at source 2026-09-07
- 77,800 US dollars, median annual wage for school and career counselors and advisors in local elementary and secondary schools, which is the grade the work this app creates lands on
US Bureau of Labor Statistics, read at source 2026-09-07
- 5,958,444 California students in the 2023-24 eligible cumulative enrolment, which the publisher defines as non-exempt students expected to attend more than 30 days. This is the denominator the absence-volume figure in docs/what-a-pilot-would-look-like.md is divided by
California Department of Education, read at source 2026-09-08
- 5,481,732 California students who missed one or more days of school between 1 July 2023 and 30 June 2024. The publisher calculates Total Days Absent from this count and not from enrolment, so the derivation has to as well
California Department of Education, read at source 2026-09-08
- 13.1 average days absent in California in 2023-24, which the publisher defines as Total Days Absent divided by the count of students with one or more absences
California Department of Education, read at source 2026-09-08
- 41.4% the share of all California absence days in 2023-24 that were unexcused, which the publisher defines as days a student was absent without a valid excuse, excluding out-of-school suspension
California Department of Education, read at source 2026-09-08
- 180 days of instruction a California school district is penalised for offering less than, used as the length of the school year the per-day figure divides by
California Legislature, read at source 2026-09-08