feat: ship deterministic parser and lifecycle release
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"contract_version": "ltjt-lifecycle-v2.8-updating-wide-parse-2026-08",
|
||||
"current_agent_parse_prompt_version": "ltjt-agent-prompt-v1.5-next-date-rollover",
|
||||
"current_extension_version": "0.5.140",
|
||||
"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.157",
|
||||
"historical_test_marker": "TEST-202609",
|
||||
"scope": "/System/Business/",
|
||||
"erp_session_keepalive": {
|
||||
@@ -31,6 +31,45 @@
|
||||
"failure_policy": "record structured recovery status and require manual login/inspection; never retry a business operation"
|
||||
}
|
||||
},
|
||||
"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": [
|
||||
@@ -89,7 +128,7 @@
|
||||
"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.leader pending fresh authorized ERP validation",
|
||||
"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",
|
||||
@@ -101,13 +140,13 @@
|
||||
"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.leader",
|
||||
"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-three-passenger-count/room types other than SGL/TWN/itinerary/OP/sales/flight/pickup ordinary updates",
|
||||
"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",
|
||||
@@ -150,28 +189,37 @@
|
||||
"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, never copied from user row_count",
|
||||
"every supplied sequence is unique and within the current ERP passenger-slot range",
|
||||
"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 authorizes only the supplied sequences",
|
||||
"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 source row has 证件类型 exactly 护照"
|
||||
"every source row has 证件类型 exactly 护照",
|
||||
"the workbook header is exactly row 2; row 1 is group metadata and never enters canonical TSV",
|
||||
"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 and stops at existing row count",
|
||||
"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",
|
||||
"证件类型 has no standalone native control and is not independently persisted"
|
||||
"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 slots",
|
||||
"restore every unspecified native row after DaoRuDones so partial input cannot clear or shift existing passengers",
|
||||
"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]",
|
||||
"preserve jj_dianhua and sj_dianhua",
|
||||
"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",
|
||||
"normalize every persisted source value by removing whitespace and report implicit_document_type=护照 plus non_persisted_source_fields=[证件类型]"
|
||||
"normalize every persisted source value by removing whitespace and report implicit_document_type=护照 plus non_persisted_source_fields=[证件类型]",
|
||||
"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": {
|
||||
@@ -185,7 +233,8 @@
|
||||
"form": "ListForm"
|
||||
}
|
||||
},
|
||||
"requery": ["fresh detail GET", "exact object/account identity", "row count", "full post-merge projection hash immediately after write", "supplied-row projection for later reconciliation", "marker row count", "explicit non-persisted document-type evidence"]
|
||||
"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": {
|
||||
@@ -201,8 +250,16 @@
|
||||
"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"],
|
||||
"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",
|
||||
"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"],
|
||||
@@ -306,11 +363,12 @@
|
||||
"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.leader 做字段映射和写后回查,其余目标在插件预检阶段转人工复核且 no_erp_write=true",
|
||||
"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"
|
||||
@@ -407,6 +465,14 @@
|
||||
"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",
|
||||
@@ -470,16 +536,20 @@
|
||||
}
|
||||
},
|
||||
"confirmation_export": {
|
||||
"allowed_kinds": ["independent_order", "shared_child_order"],
|
||||
"forbidden_kind": "shared_plan",
|
||||
"required_refs": ["concrete child_order_no or ddid", "parent_group_no or parent_plan_no or plan_no for shared child", "concrete tid or unique-row resolution"],
|
||||
"lookup_contract": "search shared parent list by parent ref, then lock one exact child leaf row by child_order_no or ddid and reconcile supplied ddid/tid",
|
||||
"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": "/System/Business/orders_Visitor.asp?did={ddid}&tid={tid}",
|
||||
"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}",
|
||||
|
||||
Reference in New Issue
Block a user