FormsRefresh

Evidence

The measured numbers behind the write-up, with the files they come from. All runs used Oracle Forms and Infrastructure 14.1.2 under Oracle's trial licence on one evaluation host, Oracle Database Free, and the Forms Standalone Launcher on a virtual display. The migrated apps ran on .NET 10 and PostgreSQL, and again on the original Oracle schemas in Oracle Database XE.

What the check caught

Every conversion of the demo apps was written by a coding agent, and every one was checked against recordings of the running original. What the check found that the agent had missed:

ConversionCaughtBy causeRepair
Retail: the agent's .NET/PostgreSQL build, once it had passed the independent database and API checks9 defects, 71 values, in the first scenario checkedorder number not drawn on opening (11 values), order date saved with the clock time instead of NULL (4), line keys drawn by the app instead of typed (26), line total computed while typing (5), earlier totals blanked when a line is added (3), no alerts on save (10), a status text Forms does not show (10), focus after opening (1), Tab order (1)1 round
Retail: the same build with those 9 repaired, all 17 scenarios403 values in 164 groups, 12 causesmain menu start-up state, keys typed by the user drawn from sequences, record navigation and its messages, Add, Save and Delete semantics, date display, an exit alert, ORDERS opening on a query instead of a new numbered record, the three-button save question, the refused delete of an order with lines, the messages of a failed save, an added order that cannot be saved, the messages after a query1 round
HR: written from the Forms source alone73 values in 13 of 17 scenarios: 52 misses, 21 now waivers52 misses: the record counter (40 values), focus after alerts and tab clicks (6), the message line (4), the new employee id (2). 21 values the customer decides on: APEX links that fail in the original (13, waiver H1), a stale department number (8, waiver H2)1 round
CareWell: written from the Forms source alone244 values in 22 of 22 scenarios: 81 misses, 163 now waivers81 misses: every save of a new appointment or payment failed on the key's sequence draw (41 values), a fetched record refused by validation did not stop the query (14), a defaulted payment row after an empty detail query (8), Enter Query (7), POST-QUERY and the cursor after a delete or a failed save (6), validation from a list without a match (3), the record counter (2). 163 values the customer decides on: the collected-today gauge (114, waiver C2), Oracle's frame title before sign-in (46, C1), three single values (C3 to C5)1 round
Student forms: written from the Forms source alone1134 values in all 15 scenarios, 12 causesrows in key order where the original returns storage order (941 values), dates shown DD-MON-YY instead of DD-MON-YYYY (120), windows Forms shows at start-up (32), the record counter (19), audit dates saved with the time of day (9), the sequence a new course number comes from (2), the message line not cleared when the cursor moves (2), and one value each for a record key, the focus after a failed save, a list-of-values message and the list's row order; 5 values are a screen-reader announcement, now waiver S12 rounds
Angular front ends of the four appsretail, CareWell and student nothing; HR: the page rendered nothingretail 17 of 17, CareWell 22 of 22 and student 15 of 15 on the first run. HR: the first run found the page empty; a zoneless Angular refresh redraws only views marked as changed, and the HR view state is plain dataHR: 1 fix
Oracle data layer of the four apps (the database kept)retail and HR nothing: 17 of 17 each on the first run; CareWell: tied rows, a localised error; student: the row orderretail and HR none; 155 retail values tolerated on PostgreSQL (5000.00 for 5000) are exact matches on Oracle. CareWell: two patients of the same name came back in the other order (the query now ends with the key), and Oracle's localised error text hid the constraint name the library's message depends on. Student: in some runs the student list started at another student; the app read in rowid order, which a table's extents need not follow, and now reads with no ORDER BY, as the forms doCareWell: 2 fixes; student: 1 fix
Restyle and navigation rewrites of both appsnothing: diffs byte-identicalnone: every diff byte-identical to the evidence before the change, so the check confirmed that nothing the user or the database sees had changednone

Three of the causes in plain words:

Why this matters at scale. These are small sample apps, retail with 6 forms, HR with 3, CareWell with 5 and the student forms with 3, and agents still missed behaviour like this. A large application maintained for many years carries far more undocumented behaviour, and nobody has a full list of it. That is where checking against the running original pays off: the recording is the list.

Migration trails

TrailStatusEvidence
Forms to .NET web on PostgreSQLproven, liveevery scenario of each app: 17 of 17 retail, 17 of 17 HR, 22 of 22 CareWell, 15 of 15 student
Oracle stays: Forms to .NET web on the original Oracle schemaproven, evidence only17 of 17 retail and 17 of 17 HR, three runs, 0 defects on the first run: parity, every difference from PostgreSQL explained; 22 of 22 CareWell, three runs (summary), after two fixes its runs found; 15 of 15 student, diffs byte-identical to PostgreSQL's (summary)
Angular front end on the same back endproven, liveevery scenario, diffs byte-identical to the default front end's: 17 of 17 retail (summary), 17 of 17 HR (summary), 22 of 22 CareWell (summary), 15 of 15 student (summary); HR needed one fix on its first run
Oracle stays, Forms becomes APEXprovenall four apps rebuilt from native APEX components on their original Oracle schemas, every scenario at parity with 0 defects, differences from Forms proposed as waivers: APEX
React or Blazor front endadapter plug point documenteda front end is a mapping variant; the steps to add one are written down
SQL Serveron requestthe database is a plug point of the harness and of the targets' data layer; a third adapter is not built

Rewrites that changed nothing

Both apps were later restyled, and their navigation rewritten (a visible call stack, Back as the way out of a called form). Three fresh-database runs of every scenario after each change gave diffs byte-identical to the evidence before it: the check confirmed that nothing the user or the database sees had changed. Files: restyle retail, HR; navigation retail, HR.

What database and API checks missed

An independent evaluator checked a .NET/PostgreSQL rebuild of the retail app, written by an ordinary coding agent, through its database and its API: it passed four of five finding groups (13 of 16 SQL observations, 7 of 10 API checks). The first recorded scenario (create an order with two lines, change a quantity, save) replayed against the same build found 9 defects, covering 71 values, none of them among the evaluator's findings:

  1. No order ID on open. Forms draws ORD_SEQ on opening, shows 16 and saves 17; the target shows nothing until save and saves 16. (11 values)
  2. ORDER_DATA saved with the clock time. Forms stores NULL; the target lets the column default apply. (4 values)
  3. ITEM_ID cannot be entered; the target draws it from item_seq. Stored values agree only because the fresh sequence starts at 1. (26 values)
  4. Line total computed while typing, not when the quantity is validated. (5 values)
  5. Adding a line blanks the total of the earlier lines. (3 values)
  6. Save shows no alerts. Forms shows FRM-40400, then the trigger's success message. (10 values)
  7. Status line shows 'No records...' from opening until save; Forms' message line is empty. (10 values)
  8. Focus after opening stays on the menu button; Forms puts it on CUSTOMER_ID. (1 values)
  9. Tab from QUANTITY goes to UNIT_PRICE; in Forms it goes to ITEM_ID. (1 values)

Further ORDERS scenarios found data-level faults in the same build: it overwrote an existing order instead of inserting a new one, saved an order Forms refuses (a required field empty), and updated a line where Forms rejects a duplicate key.

Which number is which. The 9 defects (71 values) are one scenario, order-two-lines, against the agent's first build. They were repaired first; the repaired build then became round 0 of the retail rounds, where all 17 scenarios found 403 defect values (164 groups) in the other 16. The 403 in the write-up is that round 0.

Retail: coverage

ModuleTriggersProgram unitsCoveredUnreachableBlocked
MAIN_MENU70700
ORDERS1431700
CATEGORIES_FORM90900
CUSTOMERS_FORM90900
EMPLOYEES_FORM90900
PRODUCT_FORM90900
total5736000

Decision branches: 18, of which 14 covered, 2 unreachable (retirement candidates) and 2 blocked. Database PL/SQL: 1 unit(s) in the coverage report, 1 of 1 blocks covered. Exit check: PASS.

Every branch with its class
Trigger or unitBranchClassScenarios or reason
ORDERS/ORDERS.PUSH_BUTTON10/WHEN-BUTTON-PRESSEDcommit succeeded (FORM_SUCCESS TRUE)coveredorder-two-lines
ORDERS/ORDERS.PUSH_BUTTON10/WHEN-BUTTON-PRESSEDcommit failed (FORM_SUCCESS FALSE)coveredorders-add-new, orders-save-fails
ORDERS/ORDERS/ON-CHECK-DELETE-MASTERdetail rows exist, delete refusedcoveredorders-delete-refused
ORDERS/ORDERS/ON-CHECK-DELETE-MASTERno detail rows, delete goes aheadcoveredorders-delete-empty
ORDERS/ORDERS/ON-POPULATE-DETAILSmaster record NEW or INSERT (or ORDER_ID null) - no detail querycoveredorders-add-new
ORDERS/ORDERS/ON-POPULATE-DETAILSdetail queriedcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/ORDERS/ON-POPULATE-DETAILScursor moved by the query, returned to the start itemcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/ORDERS/ON-POPULATE-DETAILScursor still on the start item after the queryunreachableThe relation is not deferred, so QUERY_MASTER_DETAILS always does GO_BLOCK('ORDER_ITEMS') and the cursor always leaves the master item it started on.
ORDERS/unit:QUERY_MASTER_DETAILSrelation not deferred - GO_BLOCK and EXECUTE_QUERYcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/unit:QUERY_MASTER_DETAILSrelation deferred - SET_BLOCK_PROPERTY non-coordinatedunreachableThe only relation (ORDERS_ORDER_ITEMS) is not deferred and nothing changes that at run time.
ORDERS/unit:QUERY_MASTER_DETAILSGO_BLOCK to the detail failed - exception handlerblockedNeeds GO_BLOCK('ORDER_ITEMS') to fail during master coordination. The block has no PRE-BLOCK, WHEN-NEW-BLOCK-INSTANCE or record-level validation that can refuse entry, and the master record was validated before coordination began; no input found that makes it fail. FRD would show it as CHECK_PACKAGE_FAILURE with FORM_SUCCESS FALSE.
ORDERS/unit:CHECK_PACKAGE_FAILUREprevious built-in succeededcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/unit:CHECK_PACKAGE_FAILUREprevious built-in failed - raise FORM_TRIGGER_FAILUREblockedCalled after GO_BLOCK and GO_ITEM in the relation code. Needs one of those navigations to fail, the same condition as the QUERY_MASTER_DETAILS exception branch; no input found.
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSdetail block NEW - nothing to clearcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSdetail block queried - CLEAR_BLOCK(NO_VALIDATE), cursor returnedcoveredorders-add-new, orders-browse, orders-delete-empty
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSchanged block below the master found (First_Changed_Block_Below)coveredorders-navigate-unsaved
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSchanges - CLEAR_BLOCK(ASK_COMMIT), user discards or saves, detail clearedcoveredorders-navigate-unsaved
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSchanges - CLEAR_BLOCK(ASK_COMMIT), user cancels, FORM_TRIGGER_FAILURE, cursor returnedcoveredorders-navigate-unsaved
Database PL/SQL units
UnitTypeBlocksCoveredClass
TRG_CALC_ITEM_TOTALTRIGGER11covered

Report: retail-coverage.md.

HR: coverage

ModuleTriggersProgram unitsCoveredUnreachableBlocked
CONSOLE50500
EMPLOYEES1431700
LOGIN20200
total2132400

Decision branches: 32, of which 24 covered, 4 unreachable (retirement candidates) and 4 blocked. Database PL/SQL: 11 unit(s) in the coverage report, 13 of 13 blocks covered. Exit check: PASS.

Every branch with its class
Trigger or unitBranchClassScenarios or reason
LOGIN/LOGIN.LOGIN/WHEN-BUTTON-PRESSEDuser and password match - console openscoveredconsole-apex, console-logout, employees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-open, employees-search, login-ok
LOGIN/LOGIN.LOGIN/WHEN-BUTTON-PRESSEDno matching user - ALERT_FAILUREcoveredlogin-fail
CONSOLE/CONSOLE.EMPLOYEES/WHEN-BUTTON-PRESSEDEMPLOYEES not open - OPEN_FORMcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-open, employees-search
CONSOLE/CONSOLE.EMPLOYEES/WHEN-BUTTON-PRESSEDEMPLOYEES already open - GO_FORMblockedNeeds the CONSOLE button pressed while EMPLOYEES is open. OPEN_FORM(ACTIVATE) puts the EMPLOYEES window over the console, and the way back is the FSAL "Window" menu, which is a client menu with no Forms name (LWMenu1); the runner only clicks named elements. Harness limit.
EMPLOYEES/BUTTONS.SAVE_BUTTON/WHEN-BUTTON-PRESSEDblock changed - commitcoveredemployees-change-department, employees-change-job, employees-create
EMPLOYEES/BUTTONS.SAVE_BUTTON/WHEN-BUTTON-PRESSEDnothing changed - no commitcoveredemployees-details
EMPLOYEES/BUTTONS.DELETE_BUTTON/WHEN-BUTTON-PRESSEDconfirmed - delete and commitcoveredemployees-delete
EMPLOYEES/BUTTONS.DELETE_BUTTON/WHEN-BUTTON-PRESSEDcancelled - nothing deletedcoveredemployees-delete-refused
EMPLOYEES/BUTTONS.CLEAR_BUTTON/WHEN-BUTTON-PRESSEDchanged, confirmed - changes discarded and requeriedcoveredemployees-clear
EMPLOYEES/BUTTONS.CLEAR_BUTTON/WHEN-BUTTON-PRESSEDchanged, cancelled - changes keptcoveredemployees-clear
EMPLOYEES/BUTTONS.CLEAR_BUTTON/WHEN-BUTTON-PRESSEDnothing changed - no questioncoveredemployees-clear
EMPLOYEES/EMPLOYEES/ON-CHECK-DELETE-MASTERjob history exists, delete refusedcoveredemployees-delete-refused
EMPLOYEES/EMPLOYEES/ON-CHECK-DELETE-MASTERno job history, delete goes aheadcoveredemployees-delete
EMPLOYEES/EMPLOYEES/ON-POPULATE-DETAILSmaster record NEW or INSERT - no detail querycoveredemployees-clear, employees-create
EMPLOYEES/EMPLOYEES/ON-POPULATE-DETAILSDEPARTMENT_ID set - department queriedcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-open, employees-search
EMPLOYEES/EMPLOYEES/ON-POPULATE-DETAILSDEPARTMENT_ID null - no department querycoveredemployees-search
EMPLOYEES/EMPLOYEES/ON-POPULATE-DETAILSMANAGER_ID set - manager queriedcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-delete, employees-delete-refused, employees-details, employees-search
EMPLOYEES/EMPLOYEES/ON-POPULATE-DETAILSMANAGER_ID null - no manager querycoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-open, employees-search
EMPLOYEES/EMPLOYEES/ON-POPULATE-DETAILSEMPLOYEE_ID set - history queriedcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-open, employees-search
EMPLOYEES/EMPLOYEES/ON-POPULATE-DETAILSEMPLOYEE_ID null on a queried record - no history queryunreachableEMPLOYEE_ID is the primary key of EMPLOYEES, so a queried record always has it; NEW and INSERT records return before this point.
EMPLOYEES/EMPLOYEES/ON-POPULATE-DETAILScursor moved by the queries, returned to the start itemcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-open, employees-search
EMPLOYEES/EMPLOYEES/ON-POPULATE-DETAILScursor still on the start item after the queriesunreachableEvery relation is not deferred, so each detail query does GO_BLOCK to the detail and the cursor always leaves the master item; HISTORY is always queried (EMPLOYEE_ID is the key).
EMPLOYEES/unit:QUERY_MASTER_DETAILSrelation not deferred - GO_BLOCK and EXECUTE_QUERYcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-open, employees-search
EMPLOYEES/unit:QUERY_MASTER_DETAILSrelation deferred - SET_BLOCK_PROPERTY non-coordinatedunreachableNo relation of EMPLOYEES is deferred and nothing changes that at run time.
EMPLOYEES/unit:QUERY_MASTER_DETAILSGO_BLOCK to the detail failed - exception handlerblockedNeeds GO_BLOCK to a detail block to fail during coordination. The detail blocks have no PRE-BLOCK, WHEN-NEW-BLOCK-INSTANCE or validation that can refuse entry; no input found that makes it fail.
EMPLOYEES/unit:CHECK_PACKAGE_FAILUREprevious built-in succeededcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-open, employees-search
EMPLOYEES/unit:CHECK_PACKAGE_FAILUREprevious built-in failed - raise FORM_TRIGGER_FAILUREblockedCalled after GO_BLOCK and GO_ITEM in the coordination units; no input found that makes these fail (see the QUERY_MASTER_DETAILS exception branch).
EMPLOYEES/unit:CLEAR_ALL_MASTER_DETAILSa detail block holds rows - cleared without validationcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-search
EMPLOYEES/unit:CLEAR_ALL_MASTER_DETAILSevery detail block empty - nothing clearedcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-open, employees-search
EMPLOYEES/unit:CLEAR_ALL_MASTER_DETAILScursor moved by the clearing, returned to the start itemcoveredemployees-apex, employees-change-department, employees-change-job, employees-clear, employees-close, employees-create, employees-delete, employees-delete-refused, employees-details, employees-search
EMPLOYEES/unit:CLEAR_ALL_MASTER_DETAILSchanged detail block below the master - ask to commitunreachableDEPARTMENT, MANAGER and HISTORY allow no insert, update or delete, so a detail block is never CHANGED.
EMPLOYEES/unit:CLEAR_ALL_MASTER_DETAILSa detail block not cleared - raise FORM_TRIGGER_FAILUREblockedNeeds CLEAR_BLOCK(NO_VALIDATE) on a read-only detail block to leave rows behind; no input found that makes it fail.
Database PL/SQL units
UnitTypeBlocksCoveredClass
COMPOSE_URLFUNCTION33covered
GENERATE_TOKENFUNCTION55covered
VALIDATE_TOKENFUNCTIONNone0unreachable
ADD_JOB_HISTORYPROCEDURE11covered
INSERT_LOGPROCEDURENone0unreachable
SECURE_DMLPROCEDURENone0unreachable
APEX_TRG_01TRIGGERNone0unreachable
REQUESTS_TRG_01TRIGGERNone0unreachable
SECURE_EMPLOYEESTRIGGERNone0unreachable
UPDATE_JOB_HISTORYTRIGGER44covered
USERS_TRG_01TRIGGERNone0unreachable

Report: hr-coverage.md. Of the schema's 11 PL/SQL units, the four the Forms app runs are fully covered (13 of 13 blocks); the other seven cannot run from Forms (a policy function that ships disabled, its helper, the APEX side and audit triggers on tables the app never writes).

CareWell: coverage

ModuleTriggersProgram unitsCoveredUnreachableBlocked
CW_APPOINTMENTS931200
CW_BILLING1041310
CW_LOGIN10100
CW_MAIN52700
CW_PATIENTS51510
CW_APP1201200
CW_LIB130850
total55105870

Decision branches: 30, of which 24 covered, 5 unreachable (retirement candidates) and 1 blocked. Database PL/SQL: 2 unit(s) in the coverage report, 0 of 0 blocks covered. Exit check: PASS.

Every branch with its class
Trigger or unitBranchClassScenarios or reason
CW_LIB/unit:CW_SEC.ALLOWrole may not use the item - disabledcoveredappointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-no-patient, appointments-return, billing-delete-refused, billing-patient, billing-pay, billing-return, billing-unsaved, login-billing, login-lov, navigation, patients-find, patients-query
CW_LIB/unit:CW_SEC.ALLOWrole may use the item - left enabledcoveredappointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-no-patient, appointments-return, billing-delete-refused, billing-patient, billing-pay, billing-return, billing-unsaved, login-billing, login-lov, navigation, patients-find, patients-query
CW_LIB/unit:CW_SEC.LOGINknown user - signed incoveredappointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-no-patient, appointments-return, billing-delete-refused, billing-patient, billing-pay, billing-return, billing-unsaved, login-billing, login-lov, login-ok, main-about, main-print-schedule, navigation, patients-find, patients-query
CW_LIB/unit:CW_SEC.LOGINunknown or inactive user - stop alertunreachablesee CW_LIB/unit:CW_MSG.FAIL
CW_LIB/unit:CW_NAV.OPEN_MODULEform not open - OPEN_FORMcoveredappointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-return, billing-delete-refused, billing-patient, billing-pay, billing-unsaved, login-billing, login-lov, navigation, patients-find, patients-query
CW_LIB/unit:CW_NAV.OPEN_MODULEform open - GO_FORMcoverednavigation
CW_LIB/unit:CW_ERR.ON_ERRORcheck constraint APPOINTMENTS_DUR_CK - translatedcoveredappointments-invalid-duration
CW_LIB/unit:CW_ERR.ON_ERRORchild records (ORA-02292) - translatedcoveredappointments-delete-refused
CW_LIB/unit:CW_ERR.ON_ERRORother error - Forms' own messagecoveredbilling-delete-refused
CW_LIB/unit:CW_ERR.ON_ERRORduplicate key (ORA-00001) - translatedunreachableEvery key the forms insert comes from a sequence in PRE-INSERT (APPOINTMENTS_SEQ, PAYMENTS_SEQ).
CW_LIB/unit:CW_ERR.ON_ERRORNOT NULL column (ORA-01400) - translatedunreachableEvery NOT NULL column the forms insert is a Required item (FRM-40202 first), has an initial value or is set in PRE-INSERT.
CW_LIB/unit:CW_ERR.ON_ERRORAPPOINTMENTS_PATIENT_FK or APPOINTMENTS_DOCTOR_FK - translatedunreachablePATIENT_ID comes from CTL.PATIENT_ID (a queried patient) and DOCTOR_ID from LOV_DOCTORS; neither is typed, and the forms delete no patient or doctor.
CW_APPOINTMENTS/unit:CHECK_DOUBLE_BOOKINGoverlap - refusedcoveredappointments-double-booking, navigation
CW_APPOINTMENTS/unit:CHECK_DOUBLE_BOOKINGno overlap or cancelled - acceptedcoveredappointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-return, billing-patient, navigation
CW_APPOINTMENTS/unit:LOAD_PATIENTno patient chosen - messagecoveredappointments-no-patient
CW_APPOINTMENTS/unit:LOAD_PATIENTanother patient - querycoveredappointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-return, billing-patient, navigation
CW_APPOINTMENTS/unit:LOAD_PATIENTsame patient - nothingcoveredappointments-return
CW_BILLING/unit:LOAD_INVOICESno patient - invoices to be paidcoveredbilling-delete-refused, billing-pay, billing-return, billing-unsaved
CW_BILLING/unit:LOAD_INVOICESalready showing - nothingcoveredbilling-return
CW_BILLING/unit:LOAD_INVOICESa patient - that patient's invoicescoveredbilling-patient
CW_BILLING/KEY-COMMITsaved - requery and messagecoveredbilling-pay
CW_BILLING/KEY-COMMITnot saved - no messagecoveredbilling-pay
CW_MAIN/unit:PRINT_SCHEDULEreport finishedblockedNeeds Oracle Reports: the PoC host runs Forms without a Reports server, so RUN_REPORT_OBJECT fails (FRM-41214) and the job never finishes. Missing resource, not a harness limit.
CW_MAIN/unit:PRINT_SCHEDULEreport not finishedcoveredmain-print-schedule
CW_BILLING/unit:QUERY_MASTER_DETAILSimmediate relation - detail queriedcoveredbilling-delete-refused, billing-patient, billing-pay, billing-return, billing-unsaved
CW_BILLING/unit:QUERY_MASTER_DETAILSdeferred relationunreachableBoth relations of INVOICES (INVOICES_LINES, INVOICES_PAYMENTS) have Deferred No.
CW_BILLING/unit:CLEAR_ALL_MASTER_DETAILSunchanged details - CLEAR_BLOCK(NO_VALIDATE)coveredbilling-delete-refused, billing-pay, billing-unsaved
CW_BILLING/unit:CLEAR_ALL_MASTER_DETAILSchanged details - CLEAR_BLOCK(ASK_COMMIT)coveredbilling-unsaved
CW_PATIENTS/unit:FIND_PATIENTSno search fields - every patientcoveredappointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-return, billing-patient, login-billing, login-lov, navigation, patients-find, patients-query
CW_PATIENTS/unit:FIND_PATIENTSsearch fields filled - filteredcoveredpatients-find
Database PL/SQL units
UnitTypeBlocksCoveredClass
CW_APIPACKAGE BODYNone0unreachable
CW_FEE_APIPACKAGE BODYNone0unreachable

Report: carewell-coverage.md. The menu module's items and the library's units are counted with the forms' triggers.

Student: coverage

ModuleTriggersProgram unitsCoveredUnreachableBlocked
QAFE_FORM130300
QAFE_FORM21131310
QAFE_FORM381900
total2242510

Decision branches: 14, of which 10 covered, 4 unreachable (retirement candidates) and 0 blocked. Database PL/SQL: 10 unit(s) in the coverage report, 2 of 3 blocks covered. Exit check: PASS.

Every branch with its class
Trigger or unitBranchClassScenarios or reason
QAFE_FORM2/COURSE/ON-POPULATE-DETAILSqueried course - sections queriedcoveredform2-course-delete-refused, form2-courses
QAFE_FORM2/COURSE/ON-POPULATE-DETAILSnew course record - nothingunreachableFORM2's COURSE block has Insert Allowed No, so it never holds a NEW or INSERT record.
QAFE_FORM2/unit:QUERY_MASTER_DETAILSimmediate relation - detail queriedcoveredform2-course-delete-refused, form2-courses
QAFE_FORM2/unit:QUERY_MASTER_DETAILSdeferred relation - detail marked non-coordinatedunreachableCOURSE_SECTION, FORM2's only relation, has Deferred No.
QAFE_FORM2/unit:CLEAR_ALL_MASTER_DETAILSunchanged details - CLEAR_BLOCK(NO_VALIDATE)coveredform2-courses
QAFE_FORM2/unit:CLEAR_ALL_MASTER_DETAILSchanged detail - CLEAR_BLOCK(ASK_COMMIT)unreachableThe detail block SECTION has Insert, Update and Delete Allowed No (typing gives FRM-40200), so it is never CHANGED.
QAFE_FORM2/unit:CHECK_PACKAGE_FAILUREprevious built-in succeededcoveredform2-course-delete-refused, form2-courses
QAFE_FORM2/unit:CHECK_PACKAGE_FAILUREprevious built-in failed - raiseunreachableIt follows GO_BLOCK and GO_ITEM to SECTION or back to the starting item; FORM2 has no navigation or validation trigger that could make them fail, and SECTION is never changed.
QAFE_FORM3/COURSE.COST/WHEN-VALIDATE-ITEMcost below 5 - refusedcoveredform3-cost-invalid
QAFE_FORM3/COURSE.COST/WHEN-VALIDATE-ITEMcost 5 or more - acceptedcoveredform3-cost-invalid
QAFE_FORM3/SECTION.COURSE_NO/WHEN-VALIDATE-ITEMunknown course - refusedcoveredform3-section-course
QAFE_FORM3/SECTION.COURSE_NO/WHEN-VALIDATE-ITEMexisting course - acceptedcoveredform3-section-course
QAFE_FORM3/COURSE.HIDESTUDENTCOUNT/WHEN-BUTTON-PRESSEDvisible - hiddencoveredform3-browse
QAFE_FORM3/COURSE.HIDESTUDENTCOUNT/WHEN-BUTTON-PRESSEDhidden - showncoveredform3-browse
Database PL/SQL units
UnitTypeBlocksCoveredClass
ADF_EX10_01_TRIGGERSPACKAGE BODYNone0unreachable
STUDENTPACKAGE BODYNone0unreachable
STUDENTPKGPACKAGE BODYNone0unreachable
TRIGGER_STUDENT_BEFORE_INSERTTRIGGERNone0unreachable
TRIGGER_STUDENT_BEFORE_UPDATETRIGGER32partly covered
V_EX01_01_STUDENT_TRGTRIGGERNone0unreachable
V_EX10_01_STUDENT_TRGTRIGGERNone0unreachable
V_QAFE_FORM1_COURSE_TRGTRIGGERNone0unreachable
V_QAFE_FORM2_INSTRUCTOR_TRGTRIGGERNone0unreachable
V_QAFE_FORM2_STUDENT_TRGTRIGGERNone0unreachable

Report: student-coverage.md.

Repeatability

Every golden record was recorded three times from the restored baseline, and the three were byte-identical for all 17 retail, all 17 HR, all 22 CareWell and all 15 student scenarios: retail, HR, CareWell, student. Clock and run-date values are masked; the masks were checked by recording on another day (17 of 17 retail records equal) and with the Forms runtime's clock moved ten days ahead (one scenario per app). Every replay against a migrated app was also run three times from a fresh database, with byte-identical diffs: retail, HR, CareWell, student.

Retail: from first conversion to parity

RoundScenarios at parityDefect valuesDefect groupsTarget changeElapsed
0 (first build, order-two-lines repaired)1 of 17403164-replay 950 s
117 of 17004 files, +414 / -205 linesrepair 19 min, replay 896 s

The 164 defect groups came down to twelve findings, among them: the main menu's start-up state, keys typed by the user instead of drawn from sequences, record navigation and its messages, Add, Save and Delete semantics, date display, ORDERS opening on a new record with a drawn order number, the three-button save question, the refused delete of an order with lines, and the messages of a failed save. All were repaired in one round by an agent that had the diffs and golden records but not the Forms source. Files: round 0, round 1.

HR: from first conversion to parity

The HR app was converted to .NET 10 and PostgreSQL from its Forms source by one coding agent in about 20 minutes (12 files, 1809 lines), without access to the scenarios or golden records.

RoundScenarios cleanDefect valuesTarget changeElapsed
0 (as converted)4 of 1773 in 13 scenarios-replay 5 min 04 s
117 of 170 (52 repaired, 21 waived)3 files, +37 / -21 linesrepair about 4 min, replay 5 min 18 s

Round 0 defects by kind: the record indicator (40 values), focus after alerts and tab clicks (6), the message line (4), the generated employee id (2), the APEX links (13, waiver H1) and a stale department number (8, waiver H2). Files: round 0 summary, round 0 defects, round 1 summary, round 1 repair diff, final three runs. The APEX token's signing key was later moved from the source's literal to configuration; the two scenarios that use it give byte-identical diffs (re-run).

CareWell: from first conversion to parity

CareWell was converted to .NET 10 and PostgreSQL from its Forms source (the XML exports of five forms, the menu module and the library, and the schema and seed SQL) by one coding agent in about 35 minutes (9 files, 2690 lines besides the seed data), without access to the scenarios or golden records.

RoundScenarios cleanDefect valuesTarget changeElapsed
0 (as converted)0 of 22244 in 22 scenarios-replay 35 min
122 of 220 (81 repaired, 163 waived)5 files, +69 / -32 linesrepair about 30 min, replay 32 min

Round 0 by cause: the key's sequence draw, which made every save of a new appointment or payment fail (41 values); a record refused by validation as it is fetched, which stops the query in Forms (14); a payment row defaulted after an empty detail query (8); Enter Query (7); POST-QUERY and the cursor after a delete or a failed save (6); validation from a list without a match (3); the record counter (2); and 163 values of the five waivers (the collected-today gauge 114, the frame title before sign-in 46, three single values). The Oracle run later found two more: two patients of the same name came back in the other order, because the conversion's query left them tied (fixed by ordering on the key, as the original returns them), and the database's localised error text hid the constraint name the library's error message depends on. A run after midnight found a third: a new payment took its date from the browser, a day ahead of the database clock (now from the database, as Forms' server clock). Files: round 0 summary, round 0 causes, round 1 summary, round 1 repair diff, final three runs.

Student: from first conversion to parity

The three student forms were converted to .NET 10 and PostgreSQL from their Forms source by one coding agent in about 39 minutes, without access to the scenarios or golden records. The same agent then wrote the mapping and the fixture and repaired from the diffs.

RoundScenarios cleanDefect valuesChangeReplay
0 (as converted)0 of 151134-17 min
17 of 15662app.js 54 lines, Program.cs 18, schema.sql 8, the fixture reordered by its generator14 min
214 of 151app.js 4 lines, the fixture's STUDENT rows rotated to the original's storage order14 min
3 (final)15 of 150 (5 waived, S1)the harness: a generated value in a view-based block gets its label from the source database16 min

Round 0 by cause: rows in key order where Forms shows storage order (941 values), the date format (120), the windows Forms shows at start-up (32), the record counter (19), audit dates with the time of day (9), a screen-reader announcement (5, waiver S1), the new course number's sequence (2), the message line (2) and four single values. Round 1 left the STUDENT table's storage order (the original's starts at student 385, 651 values) and a regression in the save (11). Files: round 0 summary and causes; round 1 summary, causes and repair; round 2 summary, causes and repair; final three runs.

Onboarding a new application

The HR app was the first application the harness had not been built on. One agent took 2 h 39 min from receiving the source to a passing coverage report:

PhaseElapsed
Find and pin the application, check its licence9 min
Host setup: schema, APEX runtime, compile, Forms Services sections9 min
Application profile and name-locator checks on three modules10 min
17 scenarios, branch classification and generic harness adjustments1 h 32 min
First coverage loop with a passing exit check48 min

The full loop (recording pass, diagnostics replay, three runs) takes 169 s per scenario on average.

Limits of this evidence