2026-02-30 looks like a date, but that day does not exist. 2028-02-29 does. An automated test was configured to check 36 subcases with made-up data in one AI-built sample app for listing supplies and space to prepare. This is a record of one build and one repair, not a failure rate for other apps.

Here, “handle” means accepting values that meet the experiment’s preset rules, refusing to save those that do not, explaining the correction, retaining other entries, and allowing one corrected save. The repaired version had no observed failures, but some interface outcomes remained unverified. That does not establish that the whole app was verified.
The evaluation rules were set before generation. Titles must contain 1–40 characters after ordinary leading and trailing spaces are removed. Notes may be empty and can contain 0–200 characters. The evaluation unit was Unicode code points, which do not always correspond to what a reader sees as one character. The test used A and the precomposed Korean syllable 가, each one code point; these boundary tests do not establish how the app counts other character sequences. Dates must be real calendar dates in YYYY-MM-DD format, within 2026–2028. Only four preset category/subcategory pairs are allowed. Matching trimmed title, date, category, and subcategory make a duplicate even if the note differs. When editing, the record itself is excluded. These are choices for this experiment, not standards for every app.
In this article
Guidance used: format, meaning, and correction
The OWASP Input Validation Cheat Sheet describes checking both an input’s structure and its meaning in context. Drawing on that distinction, this experiment separately checked the date’s format, calendar validity, and allowed year. Interface checks cannot replace checks by the code that saves the record. Neither the citation nor these results establish security.
W3C’s error-identification guidance explains that automatically detected input errors require identifying the affected item and describing the error in text. Its error-suggestion guidance calls for suggesting a correction when one is known, unless that would compromise security or the content’s purpose. These sources informed the assessment; actionable instructions, retained entries, and one corrected save were this experiment’s particular criteria. This was not an accessibility-conformance assessment.
Recorded observations: one build and one repair
The September 27, 2026 run asked the AI coding tool Codex CLI to build a preparation list with input, saving, and editing. The run plan designated gpt-6-astra, with reasoning set to high; an event-level model header did not independently confirm that identity. Local HTML, Python, SQLite, the category list, and a ban on executing entered text as code or formulas were specified from the start. Labels and error messages were in Korean. A text field replaced a date picker so exact invalid date strings could reach the app. The interface date results below concern that field; they neither show the same failure in a native picker nor recommend avoiding pickers.
The initial build, B0, did not receive the detailed evaluation rules. Its mismatches therefore cannot be described as failures to follow instructions it had been given. The same Codex session then received the rules, the complete scoring key containing every expected stored state, and failure records to produce repair R1. The initial request including setup constraints was 720 bytes; the repair request was 255,841 bytes. All records were synthetic; this is not an example of sending real records for repair. R1’s matrix and final replay reused the same frozen cases. They do not test generalization to unseen inputs or prompt effectiveness in two independent groups.
The automated test reset the app to two made-up records for each case and was configured to check 36 subcases through each route: the interface and direct save requests (API). Blocking a value on screen does not establish whether the saving code rejects it. Cases where exact interface entry or a later action could not be completed remained unverified. Browser prevention was kept separate from rejection by the saving code, and actual SQLite records were compared as well. The denominators below include unverified results. These are 36 conditions applied to one app, not 36 independent replications.
This table covers stored state, one of nine interface criteria, rather than overall quality.
| Does the actual stored state match the expectation? | Met | Failed | Unverified | Applicable |
|---|---|---|---|---|
B0 interface |
14 |
14 |
8 |
36 |
B0 direct request |
20 |
16 |
0 |
36 |
R1 interface |
32 |
0 |
4 |
36 |
R1 direct request |
36 |
0 |
0 |
36 |
On direct requests, 16 failed cases became met. On the interface, 14 failures became met and four previously unverified cases became observable: three edits reachable by record identifier and one blank-subcategory case that became submittable. The separate list-and-reopening criterion moved from 13 unverified cases in B0 to 13 met in R1. That is expanded observation coverage, not evidence that a person could not click B0’s edit button.
Of 23 applicable error-explanation cases, B0 had 2 met, 14 failed, and 7 unverified; R1 had 19 met, 0 failed, and 4 unverified. Recovery after correction had the same denominator: B0 0/13/10 and R1 18/0/5, in met/failed/unverified order. Zero observed failures in R1 does not mean every criterion was verified. These scores are not W3C conformance findings.
B0 saved the nonexistent dates 2026-02-30 and 2026-02-29 through both routes; 2026 is not a leap year. R1 rejected both. After the automated tester replaced each with the predetermined correction, 2026-02-28, R1 saved the corrected value. Both versions accepted 2028-02-29, the comparison date that should be accepted, unchanged. B0 also saved 03/04/2026 and 2026-2-03; R1 rejected them with format guidance. The first string leaves the order ambiguous: 4 March or 3 April. The corrected dates were chosen by the tester, not guessed by R1. Direct-request results separately checked the save boundary without relying on the text field.
B0 accepted both duplicate-creation cases; R1 rejected them. Both versions accepted titles made by repeating A or 가 40 times. B0 saved both 41-character values, while R1 rejected them without truncating and saving them. Both versions stored an empty note, the same title with a different date, and the literal text =1+1, which looks like a spreadsheet formula, unchanged. Direct requests with invalid categories or combinations were already rejected in B0. Among assessed items, no false rejection of valid values or change to unrelated records was observed.
Acceptance and stored values could differ. B0 accepted Workshop cards , meeting the handling criterion, but stored its edge spaces too, missing the expected stored value. R1 removed those ordinary edge spaces and disclosed the change. This explains why B0 had 21 direct-request handling passes but 20 stored-state passes.
When the title was empty and the date impossible together, B0’s browser stopped at the empty title. It did not meet the experiment’s rule requiring both problems to be explained on the first submission; downstream saving-code handling for that interface submission remained unverified. This is not a W3C violation finding. Direct requests were rejected in both versions. R1’s interface explained both problems and retained the note keep this note and selected values. The automated test corrected the two fields, saved once, and checked the reopened values. This was one confirmed scene within the 23 recovery cases.
Missing observations and the separate replay
Two early attempts were excluded from app assessment: one encountered a browser launch restriction; the other failed during reset because the test tool omitted a required creation timestamp. Each had 72 planned observations and zero valid app observations. Neither was an app input error. The counted runs followed two harness fixes, detailed in the appendix.
Even in R1, four invalid category values or combinations could not be entered exactly through the interface. Such widget prevention was a planned observation, not automatically an app failure. Save-boundary rejection for those inputs was checked through direct requests. One blank-subcategory case was rejected on screen, but the tool did not finish the keyboard correction. Direct-request results were not used to fill interface gaps. A further repair, R2, was omitted because there was no observed app defect to repair. A separate replay of four cases per route—normal creation, an impossible date, a leap day, and a valid edit—met the applicable criteria in all eight observations. These were previously disclosed cases, not a full retest or unseen inputs.
Editorial judgment: check rules, storage, and recovery separately
The editorial judgment is that checking input rules, actual stored values, and recovery separately was useful in this case. Repairing one app in the same session cannot establish general AI reliability or productivity gains. To track the execution allowance conservatively, 76 minutes were charged through the final replay, including 25 minutes of preparation, failed attempts, repair, verification, and waiting. That is neither total human working time nor measured cost; subsequent record writing is additional. Token usage is also not a bill and is described separately in the appendix.
A small checklist for your own app
Use a practice copy or a new empty app containing no real data. As in this run, use your own computer’s local address, 127.0.0.1, and a separate synthetic database; avoid shared or production servers and real login credentials. This reusable form was assembled during editing; it is not proven to save time or establish overall quality. Start with one field.
- Field name / required or optional / allowed format and range: ______
- Value to accept / unusual but valid value / value to reject: ______ / ______ / ______
- Changes the app may make before saving (e.g., removing edge spaces) / duplicate rule: ______ / ______
- One row for each value: input / expected result / actual result: ______ / ______ / ______
- Does the app identify the affected field and problem in text? Yes / No / Unknown
- Does it explain how to correct the value under this app’s rules? Yes / No / Unknown
- Does it retain other entries? Yes / No / Unknown
- Can the affected fields be edited and then saved once after correction? Yes / No / Unknown
- Does creation add one record, and does editing change only the same record? Yes / No / Unknown
- Are the reopened values and unrelated records as expected? Yes / No / Unknown
Do not count “Unknown” as a pass. This checks known correction paths; it is not a W3C conformance checklist. Reopening is an interface check, not proof that the display matches the database. The automated test read storage separately and recorded values that could not be entered through the interface and outcomes that could not be verified.
Evidence appendix: full conditions and verification scope
Records for closer scrutiny of the single-app observations are retained separately; the materials include English prose and machine-readable files. The full experiment record, frozen inputs, B0 adjudication, and R1 adjudication preserve exact requests, values, correction procedures, screens, and before-and-after storage evidence. Counts below are subcases per version, per route, totaling 36. Each version has 36 interface and 36 direct-request slots, for 72 planned observations. “Accepted” describes input handling; it does not mean every criterion, including reopening through the interface, was met.
| Condition | Count | B0 → R1 observation |
|---|---|---|
C01 normal creation, Workshop cards |
1 |
Exact storage through both routes → retained; R1 interface reopening also verified |
C02 title empty or containing three spaces |
2 |
Interface prevention/rejection and direct-request rejection → R1 rejects through both routes; interface correction and reopening verified |
C03 empty note |
1 |
Empty value accepted through both routes → retained |
C04 title with two spaces at each end |
1 |
Spaces saved, with no trimming disclosure → only ordinary edge spaces removed, with disclosure |
C05 identical to existing Paper pack / edge spaces and a different note |
2 |
Duplicate creation accepted through both routes → all rejected |
C06 same title, with only the date changed to 2026-10-02 |
1 |
Separate record accepted through both routes → retained |
C07 empty date |
1 |
Saved through both routes → rejected |
C08 2026-02-30, 2026-02-29 |
2 |
Saved through both routes → rejected, then corrected to the prescribed date |
C09 2028-02-29 |
1 |
Exact storage through both routes → retained |
C10 03/04/2026, 2026-2-03 |
2 |
Saved through both routes → rejected; tester corrected them to 2026-03-04 and 2026-02-03, respectively |
C11 endpoints of the year range / one day outside each |
4 |
Acceptance of 2026-01-01 and 2028-12-31 retained; 2025-12-31 and 2029-01-01 saved → rejected |
C12 titles of 40/41 characters, using A and 가 separately |
4 |
Both routes continue accepting 40 characters; 41 characters saved → rejected |
C13 notes of 200/201 characters, using A and 가 separately |
4 |
Both routes continue accepting 200 characters; 201 characters saved → rejected. R1’s shortened list preview was checked against the full text on reopening |
C14 note =1+1 |
1 |
Stored as ordinary text through both routes → retained. Specific to this value in this app; export and other formula-like strings were not tested |
C15 category/subcategory each empty or other |
4 |
All direct requests remain rejected. Exact entry unavailable for all four B0 interface cases; unavailable for three in R1, with blank subcategory rejected but ability to correct and recovery unverified |
C16 mismatched supplies/chairs |
1 |
Direct-request rejection retained; exact combination unavailable through either version’s interface |
C17 edit an existing record’s date to 2026-02-30 |
1 |
B0 direct request saved it; interface unverified → R1 rejects through both routes and preserves the original record |
C18 edit to match another record’s title, date, and category pair |
1 |
B0 direct request saved it; interface unverified → R1 rejects through both routes |
C19 edit only the same record’s note to revised note |
1 |
B0 direct request updated the same ID; interface unverified → R1 updated the same ID through both routes |
C20 empty title + 2026-02-30, retaining the note |
1 |
B0 interface fails to explain both errors; direct request rejected → R1 rejects through both routes; interface explains both errors and one corrected save is verified |
The evaluation used a four-part duplicate key, but no valid control changed only the subcategory to isolate its role; the components were not independently tested. C04 checked removal of U+0020 edge spaces from Workshop cards with the remaining fields preserved. Repeated internal spaces, whitespace-only notes, and other edge-space characters were not separately tested.
Allowed category pairs are supplies/paper, supplies/pens, space/chairs, and space/tables. Notes are excluded from duplicate checking. Title trimming permits only ordinary spaces (U+0020) at the two ends; it does not permit arbitrary changes to case, internal spaces, or how Korean characters are encoded, composed or decomposed.
Denominators by criterion
Each result cell below is met / failed / unverified. Applicable counts include unverified cases. Interface-only criteria, such as explanations, preservation, and recovery, do not apply to direct requests; each has 36 “not applicable” cases on that route. Do not combine the criteria into a success rate.
| Interface criterion | Applicable | B0 | R1 |
|---|---|---|---|
Stored state |
36 |
14 / 14 / 8 |
32 / 0 / 4 |
Unrelated records preserved |
36 |
33 / 0 / 3 |
36 / 0 / 0 |
Acceptance/rejection handling |
36 |
13 / 13 / 10 |
32 / 0 / 4 |
List and reopened values |
13 |
0 / 0 / 13 |
13 / 0 / 0 |
Space-trimming disclosure |
1 |
0 / 1 / 0 |
1 / 0 / 0 |
Error explanation |
23 |
2 / 14 / 7 |
19 / 0 / 4 |
Entered values preserved |
23 |
3 / 13 / 7 |
19 / 0 / 4 |
Ability to correct |
23 |
16 / 0 / 7 |
18 / 0 / 5 |
Recovery after correction |
23 |
0 / 13 / 10 |
18 / 0 / 5 |
For the interface, not-applicable counts are 23 for display, 35 for trimming disclosure, and 13 each for explanation, preservation, ability to correct, and recovery. Three direct-request criteria have 36 applicable cases each: stored state changes from B0 20/16/0 to R1 36/0/0; acceptance/rejection from B0 21/15/0 to R1 36/0/0; unrelated-record preservation is 36/0/0 in both versions.
The test harness’s method of locating records by ID did not match B0’s interface, leaving three edit cases and reopening assessments unavailable. That is not evidence that a person could not click the edit button. In B0, downstream app handling after browser prevention also remained unverified for the empty-title-only and combined-error cases. Unchanged storage met the stored-state criterion without proving downstream handling. C04 had the opposite distinction: handling met, stored state failed. For R1’s four cases that could not be entered exactly through the interface, stored state, handling, explanation, preservation, ability to correct, and recovery remained unverified. For the one blank-subcategory case, ability to correct and recovery remained unverified. Later observations did not retroactively fill earlier gaps.
B0’s two C02 cases and C20 had the expected corrected database but no reopening evidence. They belong to the 10 unverified recovery cases, not the 13 failures. Those 13 failures initially saved inputs that should have been rejected; a later diagnostic correction did not erase the initial failure.
The separate final replay covered C01, the first C08 value, C09, and C19: four cases per route. Stored state, handling, and unrelated-record preservation each met 4/4 per route; interface display met 3/3; explanation, preservation, ability to correct, and recovery each met 1/1. There were no failures or unverified results; the remaining criteria were not applicable. Correction-save actions numbered 16 interface and 23 direct-request actions for B0, 18 interface and 23 direct-request actions for R1, and one through each route for the replay. An action does not necessarily mean an actual write, and it does not erase an initial failure.
A separate read-only environment check met 1 out of 1 criterion. The date 2028-02-29, saved under ko-KR / Asia/Seoul (Korean language settings and Seoul time), remained unchanged in the list, reopened field, and database when read under en-US / America/Los_Angeles (US English settings and Los Angeles time). There were zero save actions. Locale and timezone changed together, and the interface text remained Korean, so this does not establish English localization or either factor’s individual effect.
What was not measured or fully recorded
- The experiment recorder was Astra, an AI agent. These results come from automated testing and adjudication of retained records, not direct observation of human non-developers using the app.
- Before the counted B0 run, the harness was changed to remove Chrome’s loopback sandbox wrapper and launch installed Chrome directly. The app’s OS socket sandbox remained, but browser request interception does not prove OS isolation of background traffic. Reset was then amended to supply both required timestamps,
created_atandupdated_at, fixed to2026-09-27T00:00:00+00:00. Neither fix changed app code, frozen inputs, expected values, or denominators. - The environment was Mac/Darwin, headless Chrome through Playwright (without a visible browser window), version 153.0.8010.53, Node 24.19.0, SQLite 3.54.0, and a 1280×800 viewport. Retained metadata did not establish the exact macOS, Python, Playwright, or Codex CLI versions, remaining subscription usage, or actual billed amount. The designated model and settings come from the run plan; they were not independently confirmed by a model header in the events themselves.
- Recorded elapsed times were 7 minutes 37 seconds for generation, 5 minutes 55 seconds for repair, about 66 seconds for the valid B0 test, about 74 seconds for R1, and about 9 seconds for the replay. These do not establish a production-time figure excluding preparation and verification, or total human working time. The 76-minute charge is conservative budget accounting that includes 25 minutes of preparation and subsequent waiting. B0 recorded 183,610 input tokens (including 162,560 cached) and 14,479 output tokens; R1 recorded 890,898 input tokens (including 800,256 cached) and 11,173 output tokens. Separately recorded reasoning-output counters were 848 and 1,652; these were not summed into a cost. Zero cost, time savings, and comparative productivity were not measured. Budget accounting used the revised 65 minutes previously charged and 45 remaining; the replay log’s noncumulative balance was not used. This does not prove adherence to every originally estimated time window.
- This involved one designated model, one generation, and a same-session repair given the complete scoring key and known failures. Independent repetitions, other models, browsers or devices, actual non-developers’ usability, satisfaction or understanding, and comparisons of error-message timing were not tested. The builder’s reported automated tests—five for B0 and 45 for R1—are separate from this experiment’s observations collected apart from the builder. The cases share one app and evaluator rules; they are not statistically independent samples.
- Korean input-method composition (typed letters assembling into a syllable), decomposed Hangul (syllables stored as separate letter parts), emoji and counting what a reader sees as one character, mobile devices, native date pickers, screen readers, and broader locale/timezone coverage remain untested. No security or accessibility certification was performed.
- Concurrent saves or duplicate races, transient writes during saving or atomicity, disk failures, persistence after restart, deployment, authentication, access isolation, file import/export, and spreadsheet-formula safety were not verified. They fall outside the immediate before-and-after storage comparison.
AI assisted with research and drafting. The author reviewed the final manuscript and directed the revisions.
답글 남기기