8.0 KiB
LTJT Adapter Design Principles
Runtime Principle
Production order creation must not depend on AI/LLM decisions.
AI may be used during discovery to inspect pages, draft schema notes, and propose mappings, but the runtime adapter must be deterministic, testable, and auditable.
The user's own business system and database are the upstream source of truth for pending LTJT input fields. They are expected to maintain customer/product/order/passenger/pricing/status data and emit a validated standard operation object. The LTJT adapter consumes that object; it does not infer missing business facts from chat text at runtime.
Recommended Architecture
-
Session manager
- Maintains an approved LTJT browser/session context.
- Detects login-expired scripts and permission-alert scripts.
- Never stores raw passwords in adapter logs.
-
Page-context loader
- Opens
/System/Business/orders_add.aspin a controlled browser context. - Waits for lookup data and page JavaScript initialization to finish.
- Avoids coordinate-based or visual clicking.
- Opens
-
Standard data mapper
- Converts a user-owned standard order object from the business system/database into explicit
ListFormfield assignments. - Uses a versioned mapping table from standard fields to LTJT field names.
- Does not ask an AI model what to fill at runtime.
- Converts a user-owned standard order object from the business system/database into explicit
-
Lookup resolver
- Resolves customer, product, staff, route, fee item, and resource fields using the page's own lookup endpoints.
- Uses exact-match or configured matching rules.
- Fails closed when a lookup is ambiguous.
-
Dry-run serializer
- Fills the page in a controlled context.
- Reads
ListForm.serialize(). - Validates required fields, passenger counts, hidden ids, currency/unit metadata, and expected generated fields.
- Produces an audit payload before submission.
-
Submitter
- Disabled by default until a test workflow is approved.
- Submits
Act=DoInfoJH&plus the serialized form only after deterministic validation passes. - Records request fingerprint, response classification, and created order identifier if returned.
Non-Goals
- No AI/LLM in the production decision path.
- No OCR/visual coordinate automation for normal operation.
- No privilege bypass or hidden permission escalation.
- No blind POSTs without first building and validating the browser-form payload.
Current Build Artifacts
The first deterministic contract and local dry-run artifacts are in place:
schemas/standard_system_operation.schema.jsonmappings/orders_add.mapping.jsontools/dry_run_order_create.mjstools/browser_order_add_dry_run.mjstools/browser_order_add_preflight.mjssamples/team_order_create.dry-run.example.json
The local dry-run script outputs the Act=DoInfoJH&... request body without submitting. The browser dry-run helper has now matched a live orders_add.asp ListForm.serialize() field set with fake-only sample values: 822 local fields, 822 live browser fields, zero mapped-field mismatches. It redacts session_id by default and never clicks submit.
Important correction: serializer compatibility is not enough for production. Many fields are LTJT SelectBox widgets, where values must be chosen from existing rows and the page's SetVal rules auto-fill linked fields. The adapter must run deterministic lookup validation before browser serialization or submit.
Next Build Artifact
Build the deterministic lookup resolver:
- resolve customer, route, product, OP, and salesperson through LTJT lookup data/widgets
- enforce exact-match or configured alias rules
- populate hidden metadata such as
zutuansheid, customer currency/contact fields, route-derivedtuanxuhao1, and product pricing metadata - compare browser
ListForm.serialize()after lookup resolution against the dry-run payload - keep live submit disabled
New helper scripts:
tools/inspect_orders_add_selectboxes.mjsrecords SelectBox bindings, endpoints, row/column counts, and linked fields without storing option values.tools/validate_order_add_lookups.mjschecks a standard operation against existing LTJT options and blocks zero/multiple matches.tools/resolve_order_add_lookups.mjsapplies exact-match SelectBox rows to LTJTSetValrules and can emit actual resolved field patches only when explicitly requested with--resolved-out.tools/inspect_order_add_product_effect.mjsexecutes the productFind_product()/GetProduct(cpm)side effect in the browser without submitting and stores only redacted field-change metadata.tools/browser_order_add_preflight.mjsis the new closest-to-submit dry run: it exact-matches LTJT lookups, executes product side effects, validates product-template consistency, clears/rewrites standard-owned receivable rows, then serializes the live browser form without clicking submit.tools/browser_order_add_submit_intercept.mjsinstalls an AJAX intercept before calling the page'sSubmitInfoForm(), so the page's own validation and submit branch can be tested while preventingDoInfoJHfrom reaching the network.tools/browser_order_add_template_selftest.mjsuses a real existing LTJT product template in browser memory only, fills obviousAI-DRYRUN-NO-SUBMITmarkers, and proves the end-to-end non-writing page path can pass with actual SelectBox values.tools/browser_order_add_submit_approved.mjsis the guarded live-submit tool. It refuses before browser access unless a real preflight report and a separate submit-intercept report both pass and have the same payload hash, plus--execute-live-submitand the exact approval token.tools/verify_order_marker.mjsverifies the submitted test marker throughJH_OrderListwithout storing business row values.
Controlled Submit Evidence
A controlled live test was previously completed for the independent-team order-create path. The detailed report files and test-record identifiers were intentionally removed during the repository cleanup because they were historical validation artifacts, not current contracts.
The result does not constitute permanent production approval. Any future write must produce a new temporary report and pass the lookup, product-side-effect, browser preflight, submit-intercept, approved-submit, and post-operation re-query gates below. The reports/ directory is an output location only and is not a maintained evidence archive.
Required pipeline before a formal production write:
validate_order_add_lookups.mjsorresolve_order_add_lookups.mjsmust pass for the real standard operation so zero/multiple matches are blocked early.browser_order_add_preflight.mjs --input <real-operation> --open-formmust pass in the logged-in browser. This is the authoritative pre-submit payload path because it runs LTJT's own product-template script.- Product-template output must be consistent with the standard operation for product, trip, route, route prefix, customer, and customer id. Mismatch blocks submit.
- Standard-owned rows such as receivables must be cleared/rebuilt after product side effects so product defaults do not silently leak into the submit payload.
browser_order_add_submit_intercept.mjs --call-submitshould capture exactly one interceptedDoInfoJHrequest with no validation alerts andDoInfoJH_network_prevented=true.browser_order_add_submit_approved.mjsmay be used only when the real preflight approved payload hash equals the real submit-intercept hash, and only with the explicit approval tokenAPPROVE-LTJT-DOINFOJH-SUBMIT.- After submit,
verify_order_marker.mjsor an equivalent order-list/detail verification should prove the created/updated order is visible and marked as intended.
The earlier dry_run_order_create.mjs and browser_order_add_dry_run.mjs remain useful for schema and serializer compatibility checks, but they are no longer sufficient as the final production submit gate because a real product selection can mutate more than 100 form fields.
See system_operation_scope.md for the business-action to LTJT-system-operation boundary.