652 lines
37 KiB
JSON
652 lines
37 KiB
JSON
{
|
||
"contract_version": "ltjt-lifecycle-v2.9-roster-leader-contact-2026-08",
|
||
"current_agent_parse_prompt_version": "ltjt-agent-prompt-v1.8-independent-headcount-categories",
|
||
"current_extension_version": "0.5.170",
|
||
"historical_test_marker": "TEST-202609",
|
||
"scope": "/System/Business/",
|
||
"erp_session_keepalive": {
|
||
"enabled_by_default": true,
|
||
"period_minutes": 5,
|
||
"initial_delay_minutes": 1,
|
||
"trigger": "chrome.alarms",
|
||
"request": "GET /System/Mainlt.asp in the existing allowlisted ERP tab with credentials=include and cache=no-store",
|
||
"only_when": [
|
||
"ERP automation and the keepalive setting are enabled",
|
||
"an existing allowlisted ERP tab is loaded",
|
||
"no ERP execution is running"
|
||
],
|
||
"tab_policy": "normal probe never opens or reloads a tab; exception recovery may bypass-cache reload the existing allowlisted ERP tab once per cooldown, never create a new tab",
|
||
"side_effect_policy": "read_only_session_refresh; no business operation or ERP write",
|
||
"sleep_boundary": "browser or operating-system sleep may delay alarms; the plugin does not claim continuous coverage during suspension",
|
||
"exception_recovery": {
|
||
"enabled_by_default": true,
|
||
"trigger": [
|
||
"session_expired",
|
||
"read-only keepalive failure",
|
||
"ERP page injection/session probe error"
|
||
],
|
||
"cooldown_minutes": 2,
|
||
"max_attempts_per_cooldown": 1,
|
||
"action": "reload the existing allowlisted ERP tab with bypassCache=true, wait for complete, then repeat the read-only GET probe",
|
||
"failure_policy": "record structured recovery status and require manual login/inspection; an interrupted MV3 service worker recovery is normalized out of running and the next successful read-only probe returns the recovery state to idle; never retry a business operation"
|
||
}
|
||
},
|
||
"erp_account_identity": {
|
||
"source": "the unique #Lable_UserName node in the existing ERP Mainlt.asp document",
|
||
"comparison": "NFKC-normalized, whitespace-normalized, case-insensitive exact equality with the platform account's configured ERP identity",
|
||
"forbidden_fallbacks": [
|
||
"whole-page substring matching",
|
||
"matching an expected account against unrelated ERP business text",
|
||
"accepting a missing or duplicate login identity node"
|
||
],
|
||
"privacy": "only matched/present/node-count booleans are returned to the platform; the observed ERP account text remains inside the extension session probe",
|
||
"failure_policy": "missing, duplicate, blank, or non-equal ERP identity is not execution-ready"
|
||
},
|
||
"operation_timing": {
|
||
"schema_version": "ltjt-operation-timing-v1",
|
||
"scope": "all plugin business executions through the shared result state machine",
|
||
"starts_at": "unique execution acceptance",
|
||
"ends_at": "first terminal plugin result; later human-triggered reconciliation does not include the idle gap",
|
||
"stage_boundary": "a new result stage closes the previous stage; terminal status closes the current stage",
|
||
"page_action_details": [
|
||
"script_injection",
|
||
"action_roundtrip.<allowlisted_action_code>",
|
||
"action_runtime.<allowlisted_action_code>",
|
||
"network_wait.<allowlisted_action_code>",
|
||
"frame_discovery.web_navigation",
|
||
"preflight_lookup.<lookup_code>",
|
||
"preflight_product_linkage",
|
||
"preflight_customer_restore",
|
||
"preflight_submit_intercept",
|
||
"storage_queue.<operation_code>",
|
||
"storage_read.<operation_code>",
|
||
"storage_write.<operation_code>",
|
||
"storage_prune.local_history",
|
||
"tab_lookup.<operation_code>"
|
||
],
|
||
"performance_policy": "read-only lookup endpoints may run concurrently; webNavigation narrows readiness probes to exact ERP frames; current-version action runtimes and the allowlisted ERP tab may be reused within a task; product linkage and DoInfoJH wait on native ajax completion callbacks, customer restoration uses immediate exact protected-field verification, and no write gate depends on background-throttled page polling; active or reconcilable local task roots are never pruned",
|
||
"result_delivery": "storage change push with per-task latest-result coalescing; 2.5-second polling remains a fallback",
|
||
"privacy_allowlist": [
|
||
"schema/version code",
|
||
"stage/step/status code",
|
||
"duration in milliseconds",
|
||
"bounded numeric counters"
|
||
],
|
||
"forbidden": [
|
||
"ERP URL or query string",
|
||
"form or operation field value",
|
||
"customer or passenger data",
|
||
"response body or alert text",
|
||
"cookie, token or session identifier"
|
||
],
|
||
"storage": "runtime state in extension local storage; sanitized public snapshot in the encrypted execution result plus a PII-free JSONB summary"
|
||
},
|
||
"execution_policy": {
|
||
"release_state": "guarded_narrow_candidate_pending_business_approval",
|
||
"platform_envelope_requires": [
|
||
"task_id",
|
||
"execution_id",
|
||
"confirmed task claim"
|
||
],
|
||
"dispatch_gate_requires": [
|
||
"supported action",
|
||
"minimal user-visible business fields",
|
||
"declared formats and narrow capability scope"
|
||
],
|
||
"erp_resolution_requires": [
|
||
"exactly one target object from a user-visible identifier, or one complete non-empty shared-plan target set for Program-only shared-child batch creation",
|
||
"ERP-derived kind/tid and applicable ddid",
|
||
"exactly one resource candidate when the operation uses a named ERP resource",
|
||
"fresh current status and current values when required"
|
||
],
|
||
"execution_gate_requires": [
|
||
"existing_refs.resolved=true",
|
||
"existing_refs.resolution_source=erp_unique_match",
|
||
"kind-specific exact group or child identifier and ddid",
|
||
"explicit_success_response",
|
||
"fresh_server_requery"
|
||
],
|
||
"historical_test_context_requires": [
|
||
"source.test_context with TEST-202609 marker",
|
||
"target dates inside 2026-09",
|
||
"exact test-account ownership and created_refs match",
|
||
"allowlist for order_delete"
|
||
],
|
||
"metadata_boundary": "session/task IDs, important summaries, confirmations and user communications stay in the platform envelope; they are not Agent operation data or ERP business fields",
|
||
"uncertain_write": "requery_first_no_auto_retry",
|
||
"reconciliation": "immutable-assignee-triggered read-only fresh requery on the same operation/execution; never resubmit the ERP save action",
|
||
"shared_child_identity": "prefer the stable hidden oldtdid parent reference; only fall back to regular tid controls or the URL when oldtdid is absent, and always pair it with the exact child ddid",
|
||
"completed_edit_dialog_cleanup": "after verified ERP evidence, run cleanup from the surviving top page (never from the frame that may navigate on save), require one exact route/reference candidate plus fresh identity proof; explicit test-context tasks additionally require TEST-202609/account/tid/ddid ownership, retry close at most three times, and verify exact iframe detachment",
|
||
"forbidden_side_effects": [
|
||
"procurement",
|
||
"payment",
|
||
"notification",
|
||
"external_send"
|
||
]
|
||
},
|
||
"object_kinds": {
|
||
"independent_order": "独立团订单",
|
||
"shared_plan": "散拼母团计划",
|
||
"shared_child_order": "散拼具体子单"
|
||
},
|
||
"capability_release_matrix": {
|
||
"validated_core": [
|
||
"team_order_create",
|
||
"team_order_batch_create",
|
||
"shared_plan_create without multi-date split_order facts",
|
||
"multi-date shared_plan_create with split_order customer/passenger facts: E2E3 and E2E4 each produced one concrete child per date with persisted customer and 15+1",
|
||
"shared_child_order_create for one exact parent",
|
||
"shared_child_order_batch_create resolves every product-matching parent in the inclusive date range before sequentially reusing the exact-parent child adapter",
|
||
"passenger_list_import full-list first_import or confirmed full_replace",
|
||
"five arrangement create/clear operations at status 未确认",
|
||
"arrangement_hotel update for one exact 未确认 row: end_date and room_count only",
|
||
"order_update_independent twin_room_count plus field-mapped rooms.SGL/rooms.TWN and pax.adult/pax.child_bed/pax.child_no_bed/pax.leader pending fresh authorized ERP validation",
|
||
"order_update_shared_plan planned_capacity only",
|
||
"order_update_shared_child lodging_note append with final length <= 50",
|
||
"exact synthetic receivable fixture add/clear and generated-zero cleanup",
|
||
"order_cancel and edit-only order_restore",
|
||
"confirmation_export with backend task attachments",
|
||
"allowlisted test-object order_delete"
|
||
],
|
||
"test_probe_only": [
|
||
"multi-date shared_plan_create split facts are no longer factually undetermined, but remain restricted to phase=shared_batch_split_order_probe until business release approval"
|
||
],
|
||
"blocked_erp": [
|
||
"order_update_independent fields other than twin_room_count/rooms.SGL/rooms.TWN/pax.adult/pax.child_bed/pax.child_no_bed/pax.leader",
|
||
"list order_restore through JH_set_quxiao(cz=0)",
|
||
"shared_child xiadanbeizhu",
|
||
"shared_child lodging_note final length > 50"
|
||
],
|
||
"not_live_validated": [
|
||
"independent order date/customer/group/product/non-four-passenger-count/room types other than SGL/TWN/itinerary/OP/sales/flight/pickup ordinary updates",
|
||
"arrangement update outside one exact unconfirmed hotel row, plus confirmed, ticketed, realized, self-loss or cancel states",
|
||
"hotel resource/room_type/start_date/remark update and every arrangement status update",
|
||
"vehicle end-date/change operations",
|
||
"sequence-based partial passenger import, identifier-only ownership date fallback, and nonblank post-save projection are engineering-validated in 0.5.91; the original two-row ERP write is awaiting read-only reconciliation under this build",
|
||
"per-date passenger/arrangement/export coverage for every batch-created object"
|
||
],
|
||
"deferred": [
|
||
"DOC to DOCX conversion",
|
||
"scheduled one-day/two-day triggering",
|
||
"external send",
|
||
"hotel/vehicle/transport message-template delivery",
|
||
"file upload"
|
||
],
|
||
"outside_authorized_scope": [
|
||
"customer/guide/hotel/supplier master-data maintenance",
|
||
"real procurement/payment/receipt/settlement/audit operations",
|
||
"notification or external communication"
|
||
],
|
||
"audit": "agent设计规范/test-fixtures/lwlt-lifecycle/operations-requirement-matrix.md"
|
||
},
|
||
"passenger_list_import": {
|
||
"page": "/System/Business/daoru.asp",
|
||
"dialog_field": "DaoruText",
|
||
"parser_callback": "DaoRuDones",
|
||
"canonical_headers": [
|
||
"序号",
|
||
"姓名",
|
||
"NAME",
|
||
"性别",
|
||
"出生日期",
|
||
"出生地",
|
||
"证件类型",
|
||
"证件号码",
|
||
"签发地",
|
||
"签发日",
|
||
"有效期",
|
||
"电话",
|
||
"备注"
|
||
],
|
||
"allowed_modes": ["first_import", "full_replace"],
|
||
"preconditions": [
|
||
"existing_refs.kind is independent_order or shared_child_order",
|
||
"expected_passenger_count is read from the exact ERP edit form as the initial merge baseline, never copied from user row_count and never treated as a business maximum",
|
||
"every supplied sequence is a unique positive integer within the 5000-row technical safety bound; the minimum target row count is max(initial ERP rows, highest supplied sequence)",
|
||
"first_import may fill blank rows or accept idempotent rows but cannot change occupied rows",
|
||
"full_replace requires confirmed=true and forces a native overwrite of every supplied sequence even when its current persisted projection is equal; the plugin must not downgrade confirmed user intent to no_changes",
|
||
"passenger_list.marker is exactly TEST-202609 only for an explicit historical test context",
|
||
"every canonical row has implicit 证件类型 exactly 护照; any source 证件类型 column is ignored",
|
||
"exactly one workbook row within the first 100 rows maps to the required ERP passenger fields; the header may be row 1 or follow metadata rows, source order is arbitrary, approved source/ERP aliases map to one semantic field each, and ordinary non-import columns are ignored and excluded from canonical output; contiguous roster data is read below the detected header",
|
||
"at most one row has trimmed 备注 exactly 领队; that row requires nonblank 姓名 and 电话 and must match passenger_list.leader_contact"
|
||
],
|
||
"native_defects": [
|
||
"parser overwrites from row 1; independent orders commonly begin with 16 rows and shared-child orders with 31, but these are initial editable slots rather than a post-save minimum and the parent form may compact trailing blank slots",
|
||
"generic dianhua selector can include jj_dianhua and sj_dianhua",
|
||
"parser removes all whitespace from the entire source row before splitting columns, affecting NAME, remark, and every persisted value",
|
||
"confirmed replacement of an occupied row can leave the existing pinyinxm value unchanged after native parsing",
|
||
"证件类型 has no standalone native control and is not independently persisted",
|
||
"post-save raw or hydrated passenger-row inspection can report false mismatches even after ERP has accepted and persisted the parent form"
|
||
],
|
||
"adapter_corrections": [
|
||
"use exact TSV headers 证件号码 and 签发日",
|
||
"merge supplied rows by explicit 序号 against the current ERP passenger rows and append canonical blank rows through the highest supplied sequence",
|
||
"restore every unspecified pre-existing native row after DaoRuDones so partial input cannot clear or shift existing passengers",
|
||
"fail closed before parent save when DaoRuDones does not materialize at least the calculated target row count",
|
||
"when the resolved native page materializes fewer passenger slots than the list requires, publish erp_passenger_count_limit_exceeded with the supplied count and actual ERP slot limit; retain passenger_native_* blockers only as technical evidence",
|
||
"block an occupied differing target row unless the user explicitly confirmed replacement",
|
||
"re-apply canonical whitespace-normalized NAME to pinyinxm only for merge-authorized changed sequences before strict projection validation",
|
||
"correct traveler phones within tr[id^=youke]",
|
||
"restore jj_lianxiren/jj_dianhua and sj_lianxiren/sj_dianhua after native parsing; when a validated leader_contact exists, intentionally overwrite only jj_lianxiren/jj_dianhua with the marked row name/phone",
|
||
"project document number through independent-order zjhaoma or shared-child haoma, with pinyinxm/fazhengri/youxiaori for the remaining native fields",
|
||
"select only required source fields before canonicalization, ignore non-import columns including 身份证号码/年龄/证件类型, normalize every persisted source value by removing whitespace, and report implicit_document_type=护照",
|
||
"treat the exact parent-form native success response as terminal success for passenger_list_import after every pre-save projection and native blocker has passed",
|
||
"do not perform a post-save row requery or automatic hydrated reconciliation for a newly submitted passenger list"
|
||
],
|
||
"final_save": {
|
||
"independent_order": {
|
||
"endpoint": "/System/DAT/orders.asp",
|
||
"action": "DoInfoJH",
|
||
"form": "ListForm"
|
||
},
|
||
"shared_child_order": {
|
||
"endpoint": "/System/DAT/plan.asp",
|
||
"action": "DoInfo_order",
|
||
"form": "ListForm"
|
||
}
|
||
},
|
||
"completion_evidence": ["all attachment, target identity, merge, overwrite-confirmation, passenger projection, and leader-contact projection checks pass before save", "the exact parent native save response is explicitly successful", "no post-save passenger-row requery is required", "no automatic reconciliation or second native save is started for a newly submitted passenger list"],
|
||
"completion_policy": "passenger_list_explicit_server_success"
|
||
},
|
||
"arrangements": {
|
||
"common": {
|
||
"endpoint": "/System/DAT/team.asp",
|
||
"form": "InfoForm1",
|
||
"status": "未确认",
|
||
"side_effect_policy": "no_external",
|
||
"allowed_modes_by_action": {
|
||
"arrangement_hotel": ["create", "update", "clear"],
|
||
"all_other_arrangement_actions": ["create", "clear"]
|
||
},
|
||
"create_mode": "create_in_empty_slot_0_only",
|
||
"clear_mode": "clear_exact_current_run_slot_0_only",
|
||
"slot_guard": ["resource row id is 0/empty", "resource hidden id is 0/empty", "payment reference yf0 is 0/empty", "audit fields are empty", "existing slot remark/item is empty"],
|
||
"clear_guard": ["same resolved resource id", "same persisted remark", "same date/item/quantity/status", "non-guide target.row_id from create requery", "payment reference is 0/empty", "audit and realized flags are empty"],
|
||
"business_preflight_rules": {
|
||
"arrangement_hotel_shared_plan_child_required": {
|
||
"evidence": ["resolved existing_refs.kind is shared_plan", "same-origin ERP page explicitly reports no child-group data", "SubmitButton is absent"],
|
||
"error_code": "erp_shared_plan_child_required_for_hotel",
|
||
"message": "散拼母团尚未创建子单,ERP 不允许安排酒店。请先新增散拼子单,再重新提交酒店安排。",
|
||
"policy": "block before ERP write; do not retry automatically"
|
||
}
|
||
},
|
||
"date_window": "operation target dates; explicit historical test context remains restricted to 2026-09",
|
||
"subpage_identity": "host/list ownership still requires the full created ref (including independent ddid), while native teams*.asp forms prove the target by tdID because they do not carry ddid",
|
||
"positive_quantity_required": true,
|
||
"linkage_sequence": "resolved reference/date/item -> wait stable -> quantity/status/remark",
|
||
"preflight": ["route-specific minimum serialized control count", "no visible loading indicator", "stable form for at least 1 second", "exact current-run ownership list proof"],
|
||
"requery": ["fresh arrangement subpage GET", "create returns row/resource target", "clear proves target row/resource/marker absent", "native PrintGridLists with Tpage/P_Size/riqi/departure-date/publication-unit/team-number"]
|
||
},
|
||
"arrangement_guide": {
|
||
"page": "/System/Business/teams_daoyou.asp",
|
||
"action": "DoInfo_daoyou",
|
||
"minimum_successful_controls": 13,
|
||
"fields": {
|
||
"resource.name": "daoyou0",
|
||
"resource.id": "daoyouid0",
|
||
"existing_refs.owner_account": "daoguan (ERP 原生必填;页面候选精确唯一)",
|
||
"remark": "beizhu0",
|
||
"confirmed_flag": "ap_dy=false"
|
||
},
|
||
"page_derived_only": ["dianhua0 (唯一导游候选联动值)", "dengji0 (唯一导游候选联动值)"]
|
||
},
|
||
"arrangement_vehicle": {
|
||
"page": "/System/Business/teams_cheliang.asp",
|
||
"action": "DoInfo_cheliang",
|
||
"fields": {
|
||
"supplier.name": "danwei0",
|
||
"supplier.id": "danweiid0",
|
||
"item": "chehao0",
|
||
"date": ["riqi0", "riqis0"],
|
||
"quantity": ["shuliang0", "tianshu0"],
|
||
"status": "zt0",
|
||
"remark": "beizhu0"
|
||
}
|
||
},
|
||
"arrangement_hotel": {
|
||
"page": "/System/Business/teams_jiudian.asp",
|
||
"action": "DoInfo_jiudian",
|
||
"live_validated_update": {
|
||
"mode": "update",
|
||
"target": "exact slot_index=0 plus native row_id",
|
||
"current_state": "status=未确认 and exact row identity/current snapshot matches; historical test-context rows additionally retain TEST-202609",
|
||
"allowed_changes": ["end_date", "room_count"],
|
||
"preserved_fields": ["resource", "resource.id", "row_id", "room_type", "start_date", "status", "remark", "payment and audit fields"],
|
||
"native_callback_guard": "after update_CZR(0), restore the frozen remark and recheck every preserved field before submit",
|
||
"requery": ["fresh teams_jiudian.asp", "fresh PrintGridLists team summary"]
|
||
},
|
||
"fields": {
|
||
"resource.name": "danwei0",
|
||
"resource.id": "danweiid0",
|
||
"room_type": "fangxing0",
|
||
"start_date": "riqi0",
|
||
"end_date": "riqis0",
|
||
"room_count": "jianshu0",
|
||
"status": "zt0",
|
||
"remark": "beizhu0"
|
||
}
|
||
},
|
||
"arrangement_transport": {
|
||
"page": "/System/Business/teams_piao.asp",
|
||
"action": "DoInfo_piao",
|
||
"fields": {
|
||
"supplier.name": "danwei0",
|
||
"supplier.id": "danweiid0",
|
||
"item": "shuoming0",
|
||
"date": "riqi0",
|
||
"quantity": "shuliang0",
|
||
"status": "zt0",
|
||
"remark": "beizhu0"
|
||
}
|
||
},
|
||
"arrangement_other": {
|
||
"page": "/System/Business/teams_qita.asp",
|
||
"action": "DoInfo_qita",
|
||
"fields": {
|
||
"supplier.name": "danwei0",
|
||
"supplier.id": "danweiid0",
|
||
"item": "shuoming0",
|
||
"date": "riqi0",
|
||
"quantity": "shuliang0",
|
||
"remark": "beizhu0",
|
||
"filing.number": "beianhao",
|
||
"filing.date": "beianri",
|
||
"filing.entry_port": "rujingkou",
|
||
"filing.exit_port": "chujingkou",
|
||
"confirmed_flag": "ap_qt=false"
|
||
},
|
||
"model_boundary": "other cost row and filing details share one payload but remain separate business objects",
|
||
"clear_boundary": "clear cost row only; preserve_filing=true and filing snapshot must requery unchanged"
|
||
}
|
||
},
|
||
"updates": {
|
||
"order_update_independent": {
|
||
"page": "/System/Business/orders_add.asp",
|
||
"endpoint": "/System/DAT/orders.asp",
|
||
"action": "DoInfoJH",
|
||
"blocked_fields": {
|
||
"booking_note": "xiadanbeizhu returns HTTP 200 with an empty body but does not persist in both plugin and native SubmitInfoForm baselines, including a fresh object with arrangement_history=false"
|
||
},
|
||
"live_validated_fields": {
|
||
"twin_room_count": "frenshu1"
|
||
},
|
||
"field_mapped_pending_live_validation": {
|
||
"rooms.SGL": "frenshu0",
|
||
"rooms.TWN": "frenshu1",
|
||
"pax.adult": "darenshu",
|
||
"pax.child_bed": "xiaorenshu",
|
||
"pax.child_no_bed": "ertrenshu",
|
||
"pax.leader": "quanrenshu"
|
||
},
|
||
"parsed_business_fields": "Skill 可解析人数、房型、日期、客户、产品、领队、行程、状态、备注和价格等用户明确目标;未逐字段实测的目标不得自动写入",
|
||
"executable_business_updates": ["set one or more non-negative integer rooms.SGL/rooms.TWN targets, one positive integer twin_room_count, or one or more non-negative passenger counts per request; passenger-count mappings are pending the next fresh authorized ERP validation"],
|
||
"manual_review_policy": "保留完整 updates.actions;当前插件对 twin_room_count、rooms.SGL、rooms.TWN、pax.adult、pax.child_bed、pax.child_no_bed、pax.leader 做字段映射和写后回查,其余目标在插件预检阶段转人工复核且 no_erp_write=true",
|
||
"allowed_non_business_operation": "receivable_fixture.clear_generated_zero only, using exact current-run row ids",
|
||
"known_result": "booking_note failed to persist both before and after arrangement history; HTTP 200 alone is never success",
|
||
"release_state": "wide_parse_field_mapped_room_and_passenger_counts_pending_live_validation_other_fields_manual_review"
|
||
},
|
||
"order_update_shared_plan": {
|
||
"page": "/System/Business/plan_update.asp",
|
||
"endpoint": "/System/DAT/plan.asp",
|
||
"action": "DoInfoSP",
|
||
"live_validated_fields": {
|
||
"planned_capacity": "jihuarenshu"
|
||
},
|
||
"parsed_business_fields": "Skill 可解析用户明确的计划人数及其他业务目标;仅 planned_capacity 已实测自动写入",
|
||
"manual_review_policy": "未验证目标保留在 updates.actions,插件预检时整体转人工复核且 no_erp_write=true",
|
||
"allowed_operation": "set one positive integer per request"
|
||
},
|
||
"order_update_shared_child": {
|
||
"page": "/System/Business/plan_order.asp",
|
||
"endpoint": "/System/DAT/plan.asp",
|
||
"action": "DoInfo_order",
|
||
"live_validated_fields": {
|
||
"lodging_note": "zhusushuoming"
|
||
},
|
||
"parsed_business_fields": "Skill 可解析用户明确的订房说明及其他业务目标;仅 lodging_note 已实测自动追加",
|
||
"manual_review_policy": "未验证目标保留在 updates.actions,插件预检时整体转人工复核且 no_erp_write=true",
|
||
"allowed_operation": "append one non-empty value per request; historical test-context values additionally retain TEST-202609",
|
||
"identity_reference": "oldtdid is authoritative for the parent tid when present; a regular tdid radio may represent an unrelated ERP option",
|
||
"maximum_persisted_length": 50,
|
||
"length_evidence": "fresh-session native DoInfo_order persisted 50 characters; a longer 68-character value returned HTTP 200 with an empty body and did not persist",
|
||
"blocked_fields": {
|
||
"xiadanbeizhu": "HTTP 200 but not persistent"
|
||
}
|
||
}
|
||
},
|
||
"receivable_fixture": {
|
||
"scope": "order_update_shared_child on /System/Business/plan_order.asp only",
|
||
"endpoint": "/System/DAT/plan.asp",
|
||
"action": "DoInfo_order",
|
||
"operation_shape": "standalone order_update_shared_child carrying existing_refs plus receivable_fixture; data.updates must be absent for add and clear",
|
||
"forbidden_companions": ["updates", "lodging_note mutation", "any other business-field mutation"],
|
||
"allowed_sequence": ["add", "fresh_requery_with_row_id", "clear_exact_row_id", "fresh_absence_requery"],
|
||
"fixed_business_values": {
|
||
"name": "其他费用",
|
||
"quantity": 1,
|
||
"unit_price": 0.01,
|
||
"currency": "CNY",
|
||
"paid": false,
|
||
"settled": false,
|
||
"marker": "TEST-202609"
|
||
},
|
||
"native_fields": {
|
||
"customer_name": "ys_danwei{slot}",
|
||
"customer_id": "ys_danweiid{slot}",
|
||
"name": "ys_xiangmu{slot}",
|
||
"currency": "ys_bizhong{slot}",
|
||
"quantity": "ys_shuliang{slot}",
|
||
"unit_price": "ys_danjia{slot}",
|
||
"amount": "ys_jine{slot}",
|
||
"paid": "ys_yishoufu{slot}",
|
||
"remark": "ys_beizhu{slot}",
|
||
"row_id": "ys_id{slot}",
|
||
"payment_type": "ys_shoufulei{slot}",
|
||
"operator": "ys_caozuoren{slot}",
|
||
"reviewer": "ys_shenheren{slot}"
|
||
},
|
||
"add_guard": ["no active receivable rows", "exactly one empty 其他费用 slot", "existing customer reference", "operator equals test account", "paid/reviewer clear", "payment type is 应收团款"],
|
||
"clear_guard": ["exact nonzero row_id from add requery", "single active row", "all business values unchanged", "paid/reviewer clear", "native GetYSHtml only"],
|
||
"requery": {
|
||
"add": "one exact active row and a fresh nonzero row_id",
|
||
"clear": "row_id absent, exact remark absent, active row count zero"
|
||
},
|
||
"native_baseline": {
|
||
"target": "C05 / D14457",
|
||
"add_row_id": "31558",
|
||
"add_payload_sha256": "59924707d0ba920f391c1537b43249535e3b4920ad20b539ea50fef3f6398a70",
|
||
"clear_payload_sha256": "cf33d20243caf8d88c03e9fe92e04e0cbcd3018e0735e9946bb836f0b0130c98"
|
||
},
|
||
"plugin_replay": {
|
||
"add_row_id": "31559",
|
||
"add_task_id": "TASK-20260811093811-PB0vccY",
|
||
"add_payload_sha256": "6773bba5346015dc0f20a960b672d637c59d7751d301358137d8e5622df2b9b3",
|
||
"clear_task_id": "TASK-20260811094452-MaE8sQc",
|
||
"clear_payload_sha256": "5f049062a687e8cc40895c56209ea76013f339187a3ca309d6d7497e344c1d8d",
|
||
"result": "explicit success plus fresh add/absence requery both matched"
|
||
},
|
||
"generated_zero_cleanup": {
|
||
"scope": "order_update_independent on /System/Business/orders_add.asp only",
|
||
"operation": "clear_generated_zero",
|
||
"allowed_rows": ["成人团费", "单人房差"],
|
||
"guard": ["exact native nonzero row ids", "CNY zero unit price and zero amount", "positive native quantity", "paid=false", "settled=false"],
|
||
"native_action": "GetYSHtml followed by DoInfoJH",
|
||
"verified_result": "both exact row ids absent and active receivable count zero; same-operation reconciliation performs no additional write"
|
||
}
|
||
},
|
||
"transitions": {
|
||
"order_cancel": {
|
||
"preconditions": ["receivables_cleared=true", "arrangements_cleared=true"],
|
||
"resolved_route_policy": {
|
||
"independent_order": "list",
|
||
"shared_plan": "list",
|
||
"shared_child_order": "edit",
|
||
"current_status_gate": "exact list row or exact edit form must expose exactly one allowed current status; missing, conflicting, or target-equals-current status blocks before write"
|
||
},
|
||
"edit_route_identity": "prefer exact form oldtdid/tdID/tid and ddid/dID/did values; fall back to case-insensitive query keys only when form refs are absent; conflicts fail closed",
|
||
"route_document_identity": "route preparation binds a fresh opaque 128-bit token only to the exact selected list/edit Document; frame discovery requires the token plus existing path/marker/reference checks, never logs the token, and still runs full business preflight before write",
|
||
"list": {
|
||
"supported_kinds": ["independent_order", "shared_plan"],
|
||
"action": "JH_set_quxiao",
|
||
"params": { "cz": 1, "tid": "resolved exact tid" }
|
||
},
|
||
"edit": {
|
||
"independent_order": { "action": "DoInfoJH", "field": "danzhuangtai", "value": "已取消" },
|
||
"shared_plan": { "action": "DoInfoSP", "field": "shoukezhuangtai", "value": "已取消", "side_effect": "propagates cancel to child orders" },
|
||
"shared_child_order": { "action": "DoInfo_order", "field": "danzhuangtai", "value": "已取消", "side_effect": "parent remains active but accepted passenger stats decrease" }
|
||
},
|
||
"shared_plan_success_gate": {
|
||
"parent_requery": "fresh native shared-plan list/detail status equals 已取消",
|
||
"child_discovery": "parse every concrete OPEN_update(parentTid, childDdid) returned by a fresh SP_OrderList response",
|
||
"child_requery": "fresh native child-detail GET for every discovered child",
|
||
"required_child_status": "已取消",
|
||
"failure": "any missing, ambiguous, unreadable, or non-canceled child keeps the operation incomplete and forbids automatic retry"
|
||
}
|
||
},
|
||
"order_restore": {
|
||
"list": { "supported": false, "reason": "cz=0 returns HTTP 200 but remains canceled across independent and shared plan" },
|
||
"edit": {
|
||
"independent_order": { "action": "DoInfoJH", "field": "danzhuangtai", "values": ["预订", "已确认"] },
|
||
"shared_plan": { "action": "DoInfoSP", "field": "shoukezhuangtai", "value": "收客中", "side_effect": "does not restore child orders" },
|
||
"shared_child_order": { "action": "DoInfo_order", "field": "danzhuangtai", "values": ["预订", "已确认"] }
|
||
}
|
||
}
|
||
},
|
||
"delete": {
|
||
"required_guard": [
|
||
"marker and account match",
|
||
"exact allowlist match on kind + tid + group/child identifier + ddid when applicable",
|
||
"export_evidence_frozen=true",
|
||
"delete_authorized=true",
|
||
"post_delete_requery=true"
|
||
],
|
||
"routes": {
|
||
"independent_order": {
|
||
"page": "/System/Business/orders.asp",
|
||
"endpoint": "/System/DAT/orders.asp",
|
||
"action": "DelRecord",
|
||
"params": ["dID=ddid", "tID=tid", "txh=group_no"]
|
||
},
|
||
"shared_child_order": {
|
||
"page": "/System/Business/plan_order.asp",
|
||
"endpoint": "/System/DAT/plan.asp",
|
||
"action": "Del_order",
|
||
"params": ["tID=parent tid", "did=child ddid"]
|
||
},
|
||
"shared_plan": {
|
||
"page": "/System/Business/plan.asp",
|
||
"endpoint": "/System/DAT/plan.asp",
|
||
"action": "DelRecord",
|
||
"params": ["tID=tid", "txh=parent group no"],
|
||
"extra_guard": [
|
||
"child_refs_deleted=true",
|
||
"delete_sequence=child_before_parent",
|
||
"fresh SP_OrderList child_count=0 during preflight",
|
||
"fresh SP_OrderList child_count=0 again immediately before DelRecord"
|
||
]
|
||
}
|
||
}
|
||
},
|
||
"confirmation_export": {
|
||
"allowed_kinds": ["independent_order", "shared_plan", "shared_child_order"],
|
||
"shared_plan_narrow_scope": "single visitor-list only; resolve one mother plan, require group/plan identifier plus tid, forbid child did/ddid, and request orders_Visitor.asp with tid only",
|
||
"required_refs": ["independent order or shared child: concrete ddid plus tid", "shared child: parent_group_no or parent_plan_no or plan_no", "shared plan whole-group visitor: concrete group/plan identifier plus tid and no child did/ddid"],
|
||
"lookup_contract": "independent order resolves one exact order row; shared child searches the parent list then locks one exact child leaf and reconciles ddid/tid; shared-plan whole-group visitor resolves one exact mother row and reconciles tid only",
|
||
"artifact_result": ["http_status", "content_type", "content_disposition", "bytes", "sha256", "downloaded=false", "backend_stored=true", "artifact_id", "file_name", "byte_size", "storage_backend", "download_url", "converted", "conversion_status (pdf|xlsx|converted_xlsx|already_xlsx|source_native|source_fallback|mixed)", "conversion_fallback", "native_source_count", "converted_count", "pdf_converted_count", "xlsx_count", "source_artifact_count", "derived_artifact_count", "delivered_artifact_count", "artifact_role", "agentbus_visible", "scheduled=false", "sent=false"],
|
||
"sources": {
|
||
"xingyou-confirm": "/System/Business/orders_confirm_news.asp?did={ddid}&tid={tid}",
|
||
"liantai-confirm": "/System/Business/orders_confirm_new.asp?did={ddid}&tid={tid}",
|
||
"job-order": "/System/Business/teams_beian1.asp?did={ddid}",
|
||
"visitor-list": {
|
||
"independent_order": "/System/Business/orders_Visitor.asp?did={ddid}&tid={tid}",
|
||
"shared_child_order": "/System/Business/orders_Visitor.asp?did={ddid}&tid={tid}",
|
||
"shared_plan": "/System/Business/orders_Visitor.asp?tid={tid}"
|
||
},
|
||
"guide-confirm": "/System/Business/teams_confirms_new.asp?tid={tid}",
|
||
"hotel-preorder": "/System/Business/teams_hotel_confirm.asp?tid={tid}",
|
||
"transport-preorder": "/System/Business/teams_piao_confirm.asp?tid={tid}",
|
||
"filing-current": "/System/Business/teams_beian.asp?did={ddid}",
|
||
"filing-history": "/System/Business/teams_beian1.asp?did={ddid}",
|
||
"pickup-sign": "/System/Business/teams_confirm_pai.asp?xingming={visitor_name}"
|
||
}
|
||
},
|
||
"unified_result": [
|
||
"resolved_refs",
|
||
"before_snapshot",
|
||
"preflight",
|
||
"native_request",
|
||
"server_response",
|
||
"requery",
|
||
"side_effects",
|
||
"manual_review_required"
|
||
],
|
||
"live_replay_20260812_e2e4": {
|
||
"validated_run_count": 4,
|
||
"previous_run_id": "sept-2026-lifecycle-plugin-e2e3-01",
|
||
"run_id": "sept-2026-lifecycle-plugin-e2e4-01",
|
||
"extension_version_span": ["0.5.79", "0.5.80", "0.5.81"],
|
||
"final_extension_version": "0.5.81",
|
||
"created_objects": 12,
|
||
"creation_routes": 4,
|
||
"passenger_imports": 2,
|
||
"arrangement_creates": 10,
|
||
"arrangement_clears": 10,
|
||
"persistent_business_updates": 2,
|
||
"receivable_write_operations": 3,
|
||
"safe_prewrite_blockers": 1,
|
||
"transition_checks": 7,
|
||
"source_only_exports": 4,
|
||
"source_artifacts": 40,
|
||
"deleted_objects": 12,
|
||
"aggregate_post_delete_present_count": 0,
|
||
"aggregate_post_delete_probe": "READONLY-REFS-sept-2026-lifecycle-plugin-e2e4-01-1786510672875",
|
||
"running_tasks_after_cleanup": 0,
|
||
"forbidden_side_effects_observed": 0,
|
||
"known_blocked_action": "order_update_independent booking_note",
|
||
"stabilization_fixes": [
|
||
"standalone receivable add/clear cannot mutate lodging_note",
|
||
"shared-child parent identity prefers oldtdid",
|
||
"completed edit dialogs close from the surviving top page after fresh ownership proof",
|
||
"auxiliary about:blank calendar/editor frames are ineligible lifecycle action frames"
|
||
],
|
||
"candidate_contract_version": "ltjt-lifecycle-v2.5-replay-stabilized-2026-09",
|
||
"candidate_extension_version": "0.5.81",
|
||
"release_state": "validated_core_candidate_ready_for_business_approval_broad_original_scope_blocked"
|
||
},
|
||
"live_validation_20260812_u1718": {
|
||
"run_id": "sept-2026-update-arrangement-live-03",
|
||
"runtime_extension": "0.5.83",
|
||
"final_candidate_extension": "0.5.84",
|
||
"post_validation_hardening_extension": "0.5.85",
|
||
"agent_prompt_version": "ltjt-agent-prompt-v1.0-u1718-live",
|
||
"created_refs": [
|
||
"LW-260905TEST-202609-U1718C-A/14420/14482",
|
||
"LW-260918TEST-202609-U1718C-A/14421/14483",
|
||
"LW-260927TEST-202609-U1718C-A/14422/14484"
|
||
],
|
||
"independent_update": {
|
||
"task": "TASK-20260812110459-zFj8aEk",
|
||
"execution": "95af0c74-4671-45ac-bdad-fb15ee83080a",
|
||
"field": "twin_room_count/frenshu1",
|
||
"before": 8,
|
||
"after": 9,
|
||
"restored_to": 8,
|
||
"server_response": "HTTP 200 explicit 修改成功",
|
||
"fresh_requery_matched": true
|
||
},
|
||
"hotel_arrangement_update": {
|
||
"task": "TASK-20260812111518-iWGEoT0",
|
||
"execution": "d04a4882-b219-4c2a-932f-419891916aac",
|
||
"row_id": "88528",
|
||
"before": { "end_date": "2026-09-12", "room_count": 8 },
|
||
"after": { "end_date": "2026-09-13", "room_count": 9 },
|
||
"server_response": "HTTP 200 explicit 操作成功",
|
||
"fresh_subpage_and_summary_requery_matched": true,
|
||
"test_row_cleared": true
|
||
},
|
||
"forbidden_side_effects_observed": 0,
|
||
"remaining_objects": 3,
|
||
"cleanup_state": "hotel row cleared; twin_room_count restored; three inert independent test orders retained on exact allowlist"
|
||
}
|
||
}
|