Files
LWLT-AI/adapter_design.md
2026-07-13 19:57:46 +08:00

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.

  1. Session manager

    • Maintains an approved LTJT browser/session context.
    • Detects login-expired scripts and permission-alert scripts.
    • Never stores raw passwords in adapter logs.
  2. Page-context loader

    • Opens /System/Business/orders_add.asp in a controlled browser context.
    • Waits for lookup data and page JavaScript initialization to finish.
    • Avoids coordinate-based or visual clicking.
  3. Standard data mapper

    • Converts a user-owned standard order object from the business system/database into explicit ListForm field assignments.
    • Uses a versioned mapping table from standard fields to LTJT field names.
    • Does not ask an AI model what to fill at runtime.
  4. 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.
  5. 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.
  6. 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.json
  • mappings/orders_add.mapping.json
  • tools/dry_run_order_create.mjs
  • tools/browser_order_add_dry_run.mjs
  • tools/browser_order_add_preflight.mjs
  • samples/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-derived tuanxuhao1, 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.mjs records SelectBox bindings, endpoints, row/column counts, and linked fields without storing option values.
  • tools/validate_order_add_lookups.mjs checks a standard operation against existing LTJT options and blocks zero/multiple matches.
  • tools/resolve_order_add_lookups.mjs applies exact-match SelectBox rows to LTJT SetVal rules and can emit actual resolved field patches only when explicitly requested with --resolved-out.
  • tools/inspect_order_add_product_effect.mjs executes the product Find_product()/GetProduct(cpm) side effect in the browser without submitting and stores only redacted field-change metadata.
  • tools/browser_order_add_preflight.mjs is 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.mjs installs an AJAX intercept before calling the page's SubmitInfoForm(), so the page's own validation and submit branch can be tested while preventing DoInfoJH from reaching the network.
  • tools/browser_order_add_template_selftest.mjs uses a real existing LTJT product template in browser memory only, fills obvious AI-DRYRUN-NO-SUBMIT markers, and proves the end-to-end non-writing page path can pass with actual SelectBox values.
  • tools/browser_order_add_submit_approved.mjs is 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-submit and the exact approval token.
  • tools/verify_order_marker.mjs verifies the submitted test marker through JH_OrderList without 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:

  1. validate_order_add_lookups.mjs or resolve_order_add_lookups.mjs must pass for the real standard operation so zero/multiple matches are blocked early.
  2. browser_order_add_preflight.mjs --input <real-operation> --open-form must pass in the logged-in browser. This is the authoritative pre-submit payload path because it runs LTJT's own product-template script.
  3. Product-template output must be consistent with the standard operation for product, trip, route, route prefix, customer, and customer id. Mismatch blocks submit.
  4. 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.
  5. browser_order_add_submit_intercept.mjs --call-submit should capture exactly one intercepted DoInfoJH request with no validation alerts and DoInfoJH_network_prevented=true.
  6. browser_order_add_submit_approved.mjs may be used only when the real preflight approved payload hash equals the real submit-intercept hash, and only with the explicit approval token APPROVE-LTJT-DOINFOJH-SUBMIT.
  7. After submit, verify_order_marker.mjs or 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.