From 7718e2dd34819bdfa9e179ba6066027384917212 Mon Sep 17 00:00:00 2001 From: zhaoyilun Date: Sun, 12 Jul 2026 12:33:01 +0800 Subject: [PATCH] docs: add send upload deep dive validation items --- ...-12-login-reachability-validation-items.md | 75 +++ .../2026-07-12-send-upload-deep-dive.md | 435 ++++++++++++++++++ .../capability-source-matrix.md | 8 +- scripts/extract-send-upload-deep-dive.ps1 | 375 +++++++++++++++ 4 files changed, 890 insertions(+), 3 deletions(-) create mode 100644 docs/source-discovery/2026-07-12-login-reachability-validation-items.md create mode 100644 docs/source-discovery/2026-07-12-send-upload-deep-dive.md create mode 100644 scripts/extract-send-upload-deep-dive.ps1 diff --git a/docs/source-discovery/2026-07-12-login-reachability-validation-items.md b/docs/source-discovery/2026-07-12-login-reachability-validation-items.md new file mode 100644 index 0000000..aadca2d --- /dev/null +++ b/docs/source-discovery/2026-07-12-login-reachability-validation-items.md @@ -0,0 +1,75 @@ +# Login Reachability Validation Items + +Date: 2026-07-12 + +Purpose: this is the operator-facing checklist for the 2026-07-13 logged-in environment. It is generated from the offline send/upload deep dive and should be used to build the one-shot reachability probe package. + +## P0 items + +### Confirm logged-in IMPlatformClient.exe process and loaded assemblies + +- Category: runtime +- Evidence to capture: process id, module list, loaded managed assemblies +- Unlocks: all B-route adapter tests + +### Confirm AppContextManager/IAppContextManager reachability + +- Category: runtime +- Evidence to capture: type visible, instance path, SendTxtMessageByJid callable shape +- Unlocks: text send high-level path + +### Confirm Chat/XMPPConnection authenticated state + +- Category: runtime +- Evidence to capture: Chat instance, XMPPConnection state, target JID mapping +- Unlocks: text and file message finalization + +### Capture FileUploadPara required values without leaking token + +- Category: file_upload +- Evidence to capture: host, port, domain, local path presence, IsImg/IsPublic, token-present boolean/hash only +- Unlocks: upload_file probe + +### Confirm IFileTransfer/FileTransfer.FileUpload reachability + +- Category: file_upload +- Evidence to capture: service instance or constructor path, method signature, safe call readiness +- Unlocks: file upload + +### Confirm FileUploadResult.FileID after safe test upload + +- Category: file_upload_result +- Evidence to capture: FileID present, size/name or URL/remote folder metadata, failure code if upload fails +- Unlocks: send_file_message + +### Confirm trans_UploadCompleted/SendFileMessage consumes FileID + +- Category: send_file_message +- Evidence to capture: FileID enters payload, Chat.sendFileMessage invoked, sent file record/ack +- Unlocks: production file send + +### Correlate sent record/ack with content hash or file hash + +- Category: ack +- Evidence to capture: sent record timestamp, target ref, body/file metadata hash, ack/ref id +- Unlocks: production gate + +## P1 items + +### Confirm group ChatRoom branch and permissions + +- Category: group +- Evidence to capture: ChatRoom type, speech/upload permission state, group JID +- Unlocks: group send/file send + +### If B-route reachability fails, capture A-route UI evidence + +- Category: fallback +- Evidence to capture: window hwnd, rtbSendMessage, btnSend, screenshots, failure reason +- Unlocks: demo fallback only + +## Pass criteria + +- Text send can move forward when logged-in runtime exposes AppContextManager or MessageScheduling plus Chat/XMPPConnection and sent-record/ack correlation is possible. +- File send can move forward when logged-in runtime exposes IFileTransfer/FileUpload, FileUploadPara values, FileUploadResult.FileID, and Chat.sendFileMessage finalization evidence. +- Production remains blocked if any P0 item is missing or only static evidence is available. diff --git a/docs/source-discovery/2026-07-12-send-upload-deep-dive.md b/docs/source-discovery/2026-07-12-send-upload-deep-dive.md new file mode 100644 index 0000000..cf03cd1 --- /dev/null +++ b/docs/source-discovery/2026-07-12-send-upload-deep-dive.md @@ -0,0 +1,435 @@ +# Send / Upload Deep Dive + +Date: 2026-07-12 + +## Business summary + +Offline deep dive confirms the remaining work is not generic sending code. The business blocker is logged-in runtime reachability plus online proof. Text send needs reachable AppContextManager/MessageScheduling/Chat. File send needs upload parameters and server-issued FileUploadResult.FileID before Chat.sendFileMessage can be meaningful. + +## Decision + +| Question | Answer | +| --- | --- | +| Should work stop before login? | No | +| Highest-value offline work | Deepen send/upload decomposition and prepare login validation items | +| Can production send be enabled offline? | No | +| Next package | login reachability probe package | + +## Sources + +| Source | Role | Exists | Lines | Size bytes | +| --- | --- | --- | ---: | ---: | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il` | main client; high-level send, file-send orchestration, runtime auth/service state | True | 1360035 | 74148460 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il` | Chat/XMPP send implementation and file-message primitive | True | 87425 | 5019807 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il` | file upload HTTP/service implementation | True | 3351 | 207786 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il` | FileUploadPara/FileUploadResult/FileTransferParaBase DTO contracts | True | 1641 | 93585 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Interface.dll.il` | IAppContextManager/IFileTransfer interface contracts | True | 4429 | 227335 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il` | ServiceManager/Auth DTOs and common runtime state | True | 118343 | 5703293 | + +## Deep-dive findings + +| Item | Stage | Status | Evidence | Business meaning | +| --- | --- | --- | ---: | --- | +| `Text send high-level entry: AppContextManager.SendTxtMessageByJid` | `text_send` | `static_evidence_found` | 6 | Best business-level text-send candidate if reachable in logged-in runtime. | +| `Text send scheduling fallback: MessageScheduling.SendChatMessage` | `text_send` | `static_evidence_found` | 16 | Fallback text-send path if AppContextManager is hard to reach but Chat/Roster args exist. | +| `Low-level text primitive: Chat.SendMessage -> XMPPConnection.send` | `text_send` | `static_evidence_found` | 20 | Confirms final XMPP send primitive; not enough alone without authenticated Chat/XMPP state. | +| `Upload parameter base: FileTransferParaBase` | `file_upload` | `static_evidence_found` | 20 | Defines host, port, domain, local path, timeout/cache and token fields required by upload/download DTOs. | +| `Upload DTO: FileUploadPara` | `file_upload` | `static_evidence_found` | 20 | Concrete upload request DTO; adds IsImg/IsPublic and invokes FileTransferParaBase constructor. | +| `Upload service: IFileTransfer/FileTransfer.FileUpload` | `file_upload` | `static_evidence_found` | 20 | Managed upload entry; returns FileUploadResult and internally writes multipart token/form data. | +| `Upload auth/server state: HTTPFileServer + Auth token` | `file_upload` | `static_evidence_found` | 20 | File upload depends on runtime server/auth state, not only a local file path. | +| `Upload result: FileUploadResult.FileID and remote metadata` | `file_upload_result` | `static_evidence_found` | 20 | Server-issued FileID is required before a chat file message is meaningful. | +| `File-message finalization: trans_UploadCompleted / SendFileMessage / Chat.sendFileMessage` | `send_file_message` | `static_evidence_found` | 20 | After upload succeeds, the client constructs offline file-transfer content and sends chat file message. | +| `Target resolution: JID -> Chat / ChatRoom` | `runtime_context` | `static_evidence_found` | 20 | Both text and file send need a target JID mapped to Chat or ChatRoom; group handling may differ. | +| `Runtime owner: frmMain / IMPPManager / MessageCenter` | `runtime_context` | `static_evidence_found` | 20 | Likely owners of initialized logged-in state and message center callbacks. | + +## What this adds to tomorrow's login validation + +| Priority | Category | Validation item | Evidence to capture | Unlocks | +| --- | --- | --- | --- | --- | +| P0 | runtime | Confirm logged-in IMPlatformClient.exe process and loaded assemblies | process id, module list, loaded managed assemblies | all B-route adapter tests | +| P0 | runtime | Confirm AppContextManager/IAppContextManager reachability | type visible, instance path, SendTxtMessageByJid callable shape | text send high-level path | +| P0 | runtime | Confirm Chat/XMPPConnection authenticated state | Chat instance, XMPPConnection state, target JID mapping | text and file message finalization | +| P0 | file_upload | Capture FileUploadPara required values without leaking token | host, port, domain, local path presence, IsImg/IsPublic, token-present boolean/hash only | upload_file probe | +| P0 | file_upload | Confirm IFileTransfer/FileTransfer.FileUpload reachability | service instance or constructor path, method signature, safe call readiness | file upload | +| P0 | file_upload_result | Confirm FileUploadResult.FileID after safe test upload | FileID present, size/name or URL/remote folder metadata, failure code if upload fails | send_file_message | +| P0 | send_file_message | Confirm trans_UploadCompleted/SendFileMessage consumes FileID | FileID enters payload, Chat.sendFileMessage invoked, sent file record/ack | production file send | +| P0 | ack | Correlate sent record/ack with content hash or file hash | sent record timestamp, target ref, body/file metadata hash, ack/ref id | production gate | +| P1 | group | Confirm group ChatRoom branch and permissions | ChatRoom type, speech/upload permission state, group JID | group send/file send | +| P1 | fallback | If B-route reachability fails, capture A-route UI evidence | window hwnd, rtbSendMessage, btnSend, screenshots, failure reason | demo fallback only | + +## Evidence by item + +### Text send high-level entry: AppContextManager.SendTxtMessageByJid + +Stage: `text_send`. Status: `static_evidence_found`. Evidence count: 6. + +Business meaning: Best business-level text-send candidate if reachable in logged-in runtime. + +Must verify tomorrow: +- Reach AppContextManager instance +- Confirm target JID/chat type mapping +- Invoke dry/probe path without send first +- Correlate sent record/ack after real send test + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:542112` | `string_literal` | `IL_09bf: ldstr "SendTxtMessageByJid"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:585987` | `signature_continuation` | `instance void SendTxtMessageByJid(string jid,` | `L585986: .method public hidebysig newslot virtual final instance void SendTxtMessageByJid(string jid,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:586197` | `method_end` | `} // end of method AppContextManager::SendTxtMessageByJid` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1358068` | `string_literal` | `IL_0c3f: ldstr "SendTxtMessageByJid"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Interface.dll.il:1920` | `signature_continuation` | `instance void SendTxtMessageByJid(string jid,` | `L1919: .method public hidebysig newslot abstract virtual instance void SendTxtMessageByJid(string jid,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Interface.dll.il:1924` | `method_end` | `} // end of method IAppContextManager::SendTxtMessageByJid` | `L1919: .method public hidebysig newslot abstract virtual instance void SendTxtMessageByJid(string jid,` | + +### Text send scheduling fallback: MessageScheduling.SendChatMessage + +Stage: `text_send`. Status: `static_evidence_found`. Evidence count: 16. + +Business meaning: Fallback text-send path if AppContextManager is hard to reach but Chat/Roster args exist. + +Must verify tomorrow: +- Locate or construct RosterContactsArgs +- Locate Chat instance +- Confirm direct/group branch +- Correlate sent record/ack + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:728720` | `callsite` | `IL_0213: call class [smack]com.vision.smack.packet.XmppMessage IMPP.Client.Core.MessageEngine.MessageScheduling::SendChatMessage(class IMPP.Client.Business.RosterContacts.RosterContactsArgs,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1153541` | `reference` | `SendChatMessage(class [smack]com.vision.smack.Chat chat,` | `L1153540: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1153800` | `method_end` | `} // end of method MessageScheduling::SendChatMessage` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1154128` | `reference` | `SendChatMessage(class IMPP.Client.Business.RosterContacts.RosterContactsArgs rosterArgs,` | `L1154127: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1154187` | `callsite` | `IL_006e: call class [smack]com.vision.smack.packet.XmppMessage IMPP.Client.Core.MessageEngine.MessageScheduling::SendChatMessage(class [smack]com.vision.smack.Chat,` | `L1154127: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1154225` | `method_end` | `} // end of method MessageScheduling::SendChatMessage` | `L1154127: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99274` | `reference` | `get_issendchatmessage() cil managed` | `L99273: .method public hidebysig specialname instance string` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99284` | `reference` | `set_issendchatmessage(string 'value') cil managed` | `L99283: .method public hidebysig specialname instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99582` | `property` | `.property instance string issendchatmessage()` | `L99546: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99586` | `reference` | `.set instance void Schedule::set_issendchatmessage(string)` | `L99546: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99587` | `reference` | `.get instance string Schedule::get_issendchatmessage()` | `L99546: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:100662` | `reference` | `get_issendchatmessage() cil managed` | `L100661: .method public hidebysig specialname instance string` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:100672` | `reference` | `set_issendchatmessage(string 'value') cil managed` | `L100671: .method public hidebysig specialname instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:101019` | `property` | `.property instance string issendchatmessage()` | `L100976: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:101023` | `reference` | `.get instance string ScheduleTaskDetailsDTO::get_issendchatmessage()` | `L100976: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:101024` | `reference` | `.set instance void ScheduleTaskDetailsDTO::set_issendchatmessage(string)` | `L100976: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | + +### Low-level text primitive: Chat.SendMessage -> XMPPConnection.send + +Stage: `text_send`. Status: `static_evidence_found`. Evidence count: 20. + +Business meaning: Confirms final XMPP send primitive; not enough alone without authenticated Chat/XMPP state. + +Must verify tomorrow: +- Locate Chat instance +- Locate authenticated XMPPConnection +- Confirm direct/group message payload +- Capture ack/sent-record + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:80284` | `callsite` | `IL_34d2: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:206378` | `callsite` | `IL_0010: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L206369: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:249554` | `callsite` | `IL_0c1e: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:249857` | `callsite` | `IL_0f27: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:299997` | `callsite` | `IL_0096: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::SendMessage(class [smack]com.vision.smack.packet.XmppMessage)` | `L299937: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:410318` | `callsite` | `IL_2257: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:412929` | `callsite` | `IL_00d2: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::SendMessage(class [smack]com.vision.smack.packet.XmppMessage)` | `L412858: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:430535` | `callsite` | `IL_0357: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::SendMessage(class [smack]com.vision.smack.packet.XmppMessage)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:451786` | `callsite` | `IL_00b1: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L451702: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:451858` | `callsite` | `IL_018f: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:454073` | `callsite` | `IL_0179: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:454206` | `callsite` | `IL_00b9: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L454118: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:454298` | `callsite` | `IL_00b9: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L454210: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:520831` | `callsite` | `IL_017a: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:521914` | `callsite` | `IL_007a: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L521860: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:521970` | `callsite` | `IL_0075: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L521918: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:522012` | `callsite` | `IL_004c: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L521974: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:540102` | `callsite` | `IL_0109: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L539996: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:651133` | `callsite` | `IL_0136: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:651239` | `callsite` | `IL_0068: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L651184: .method public hidebysig instance void` | + +### Upload parameter base: FileTransferParaBase + +Stage: `file_upload`. Status: `static_evidence_found`. Evidence count: 20. + +Business meaning: Defines host, port, domain, local path, timeout/cache and token fields required by upload/download DTOs. + +Must verify tomorrow: +- Host +- Port +- Domain +- LocalFilePath +- Token +- Cache/timeout flags if present + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:12927` | `signature_continuation` | `instance int32 get_Port() cil managed` | `L12926: .method public hidebysig newslot specialname abstract virtual instance int32 get_Port() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:12981` | `reference` | `.get instance int32 NetFwTypeLib.INetFwOpenPort::get_Port()` | `L12962: .method public hidebysig newslot specialname abstract virtual instance void set_Enabled([in] bool Enabled) cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:13737` | `callsite` | `IL_01e1: callvirt instance void [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileTransferParaBase::add_FileTransferNodity(class [mscorlib]System.EventHandler`1` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:586220` | `callsite` | `IL_0023: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L586199: .method public hidebysig newslot virtual final instance class [mscorlib]System.Collections.Generic.List`1` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:586225` | `callsite` | `IL_0038: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L586199: .method public hidebysig newslot virtual final instance class [mscorlib]System.Collections.Generic.List`1` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:604500` | `callsite` | `IL_0129: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608772` | `callsite` | `IL_0063: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L608722: .method private hidebysig instance void` | + +### Upload result: FileUploadResult.FileID and remote metadata + +Stage: `file_upload_result`. Status: `static_evidence_found`. Evidence count: 20. + +Business meaning: Server-issued FileID is required before a chat file message is meaningful. + +Must verify tomorrow: +- FileID +- URL or remote folder if present +- size/name metadata +- failure code/message + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:365887` | `callsite` | `IL_028d: callvirt instance string [IMPP.Common]AppInfoDTO::get_url()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:388652` | `callsite` | `IL_002e: callvirt instance string IMPP.Client.Business.ISphereAssistant.ISphereTabCtrlInfo::get_url()` | `L388624: .method public hidebysig instance bool` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:413084` | `callsite` | `IL_00ff: callvirt instance string IMPP.Client.Business.ISphereAssistant.ISphereTabCtrlInfo::get_url()` | `L412984: .method public hidebysig instance bool` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:413214` | `callsite` | `IL_0272: callvirt instance string IMPP.Client.Business.ISphereAssistant.ISphereTabCtrlInfo::get_url()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:413504` | `callsite` | `IL_058d: callvirt instance string IMPP.Client.Business.ISphereAssistant.ISphereTabCtrlInfo::get_url()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:427078` | `callsite` | `IL_0a5e: callvirt instance string [IMPP.Common]IMPP.Common.HttpItem::get_URL()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:427127` | `callsite` | `IL_0ace: callvirt instance string [IMPP.Common]IMPP.Common.HttpItem::get_URL()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:427502` | `callsite` | `IL_0e6d: callvirt instance string [IMPP.Common]IMPP.Common.HttpItem::get_URL()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:427551` | `callsite` | `IL_0edb: callvirt instance string [IMPP.Common]IMPP.Common.HttpItem::get_URL()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:461320` | `reference` | `get_Url() cil managed` | `L461319: .method public hidebysig specialname instance string` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:461328` | `method_end` | `} // end of method AdvertiseImageInfo::get_Url` | `L461319: .method public hidebysig specialname instance string` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:461360` | `reference` | `.get instance string IMPP.Client.Business.AdvertisementManage.AdvertiseImageInfo::get_Url()` | `L461342: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:512002` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_14,` | `L511981: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:512182` | `callsite` | `IL_01d9: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.F...` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:512315` | `callsite` | `IL_0322: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:564370` | `callsite` | `IL_064c: callvirt instance string [IMPP.Common]AppInfoDTO::get_url()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608733` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_5,` | `L608722: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608800` | `callsite` | `IL_00b2: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.F...` | `L608722: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608819` | `callsite` | `IL_00e0: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `L608722: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608848` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_6,` | `L608836: .method private hidebysig instance void` | + +### File-message finalization: trans_UploadCompleted / SendFileMessage / Chat.sendFileMessage + +Stage: `send_file_message`. Status: `static_evidence_found`. Evidence count: 20. + +Business meaning: After upload succeeds, the client constructs offline file-transfer content and sends chat file message. + +Must verify tomorrow: +- trans_UploadCompleted receives FileID +- OFFLINE_FILE_TRANSFER payload fields +- Target Chat/JID +- Sent file record/ack + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:13650` | `string_literal` | `IL_010a: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:14612` | `string_literal` | `IL_00e6: ldstr "OFFLINE_FILE_TRANSFER"` | `L14529: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblPersonMsg` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:15245` | `string_literal` | `IL_010f: ldstr "OFFLINE_FILE_TRANSFER"` | `L15134: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblMsgGroupPersonMsg` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:76219` | `string_literal` | `IL_05ec: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:76335` | `string_literal` | `IL_0751: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:76471` | `string_literal` | `IL_08ef: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:76792` | `string_literal` | `IL_0cae: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:78639` | `string_literal` | `IL_2267: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:83138` | `string_literal` | `IL_030d: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:86296` | `string_literal` | `IL_01a9: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:121988` | `string_literal` | `IL_09b1: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:122534` | `string_literal` | `IL_0fbe: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:122836` | `string_literal` | `IL_12de: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:123116` | `string_literal` | `IL_15f3: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:123656` | `string_literal` | `IL_1c15: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:123706` | `string_literal` | `IL_1caa: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:123873` | `string_literal` | `IL_1e82: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:124349` | `string_literal` | `IL_23b0: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:125361` | `string_literal` | `IL_2e70: ldstr "OFFLINE_FILE_TRANSFER"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:130922` | `string_literal` | `IL_01cf: ldstr "OFFLINE_FILE_TRANSFER"` | `` | + +### Target resolution: JID -> Chat / ChatRoom + +Stage: `runtime_context`. Status: `static_evidence_found`. Evidence count: 20. + +Business meaning: Both text and file send need a target JID mapped to Chat or ChatRoom; group handling may differ. + +Must verify tomorrow: +- Contact JID +- Group/conference JID +- ChatManager.GetChat +- ChatRoom branch and permissions + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:958` | `reference` | `.mresource public IMPP.Client.control.UCChatRoomMember.resources` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:961` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.control.UCChatRoomMember.resources` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1138` | `reference` | `.mresource public IMPP.Client.Business.ChatManager.BaseControl.frmChatRoom.resources` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1141` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.Business.ChatManager.BaseControl.frmChatRoom.resources` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1173` | `reference` | `.mresource public IMPP.Client.Business.ChatManager.WorkGroup.frmReserveChatRoom.resources` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1176` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.Business.ChatManager.WorkGroup.frmReserveChatRoom.resources` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1193` | `reference` | `.mresource public IMPP.Client.Forms.frmTempChatRoom.resources` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1196` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.Forms.frmTempChatRoom.resources` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1529` | `field` | `.field public string chatRoomJID` | `L1486: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1574` | `reference` | `IL_0044: ldfld string IMPP.Client.VideoChat.SingleAVDispatcher/'<>c__DisplayClass7'::chatRoomJID` | `L1540: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:2973` | `reference` | `string chatRoomJID,` | `L2970: .method family hidebysig newslot abstract virtual instance void Instance_OnAVRoomStateChange(valuetype IMPP.Client.MultiplayerAV.AVRoom.EventTypeEnum eventType,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:2983` | `reference` | `string chatRoomJID) cil managed` | `L2981: .method family hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:3000` | `reference` | `IL_0010: stfld string IMPP.Client.VideoChat.SingleAVDispatcher/'<>c__DisplayClass7'::chatRoomJID` | `L2981: .method family hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:13688` | `callsite` | `IL_0179: callvirt instance class [smack]com.vision.smack.Chat [smack]com.vision.smack.ChatManager::GetChat(class [smack]com.vision.smack.XMPPConnection,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:14269` | `callsite` | `IL_00be: callvirt instance class [smack]com.vision.smack.Chat [smack]com.vision.smack.ChatManager::GetChat(class [smack]com.vision.smack.XMPPConnection,` | `L14190: .method public hidebysig static void OpenSetRoamMessageForm(valuetype [IMPP.Model]IMPP.Model.ChatRecord.MsgType msgSource,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:14273` | `reference` | `IL_00c3: castclass [smack]com.vision.smack.muc.ChatRoom` | `L14190: .method public hidebysig static void OpenSetRoamMessageForm(valuetype [IMPP.Model]IMPP.Model.ChatRecord.MsgType msgSource,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:15141` | `reference` | `class [smack]com.vision.smack.muc.ChatRoom V_1,` | `L15134: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblMsgGroupPersonMsg` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:15179` | `callsite` | `IL_0074: callvirt instance class [smack]com.vision.smack.Chat [smack]com.vision.smack.ChatManager::GetChat(class [smack]com.vision.smack.XMPPConnection,` | `L15134: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblMsgGroupPersonMsg` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:15183` | `reference` | `IL_0079: castclass [smack]com.vision.smack.muc.ChatRoom` | `L15134: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblMsgGroupPersonMsg` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:15369` | `callsite` | `IL_026e: callvirt instance string [smack]com.vision.smack.muc.ChatRoom::get_Name()` | `` | + +### Runtime owner: frmMain / IMPPManager / MessageCenter + +Stage: `runtime_context`. Status: `static_evidence_found`. Evidence count: 20. + +Business meaning: Likely owners of initialized logged-in state and message center callbacks. + +Must verify tomorrow: +- Running frmMain +- IMPPManager.UserInfo +- MessageCenter +- Reconnect success state +- loaded assemblies + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1714` | `field` | `.field family class IMPP.Client.frmMain mainWin` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1744` | `reference` | `IL_001d: ldfld class IMPP.Client.frmMain IMPP.Client.VideoChat.SingleAVDispatcher::mainWin` | `L1721: .method family hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1789` | `reference` | `IL_002a: ldfld class IMPP.Client.frmMain IMPP.Client.VideoChat.SingleAVDispatcher::mainWin` | `L1761: .method family hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:2777` | `reference` | `Init(class IMPP.Client.frmMain frmMain) cil managed` | `L2776: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:2791` | `reference` | `IL_000a: stfld class IMPP.Client.frmMain IMPP.Client.VideoChat.SingleAVDispatcher::mainWin` | `L2776: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:3005` | `reference` | `IL_001d: ldfld class IMPP.Client.frmMain IMPP.Client.VideoChat.SingleAVDispatcher::mainWin` | `L2981: .method family hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:3533` | `callsite` | `IL_004c: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `L3492: .method public hidebysig static void FillDataToDataGridView(class [IMPP.UI]IMPP.UI.SkinControl.SkinDataGridView dgv,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:4359` | `callsite` | `IL_01ba: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:4393` | `callsite` | `IL_021a: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:4403` | `callsite` | `IL_0236: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:5267` | `callsite` | `IL_02ea: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:5752` | `callsite` | `IL_08ac: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:5772` | `callsite` | `IL_08ee: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:6283` | `callsite` | `IL_0ea6: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:6329` | `callsite` | `IL_0f2f: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:6399` | `callsite` | `IL_1006: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:7402` | `callsite` | `IL_0141: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `L7286: .method public hidebysig static void AddUserTitle(class CSharpWin.ChatRichTextBox textBox,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:7504` | `callsite` | `IL_024f: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:7855` | `callsite` | `IL_00bf: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `L7780: .method public hidebysig static void AddLinkID(class CSharpWin.ChatRichTextBox textBox,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:7997` | `callsite` | `IL_023a: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | + +## Updated stop / continue rules + +Continue B-route tomorrow if P0 runtime, text-send, upload, FileID, and ack probes produce positive or actionable evidence. Stop B-route and escalate if logged-in runtime cannot expose AppContextManager/MessageScheduling/Chat/IFileTransfer, or if upload cannot produce FileUploadResult.FileID. Keep A-route/RPA backup-only for demo continuity. diff --git a/docs/source-discovery/capability-source-matrix.md b/docs/source-discovery/capability-source-matrix.md index 19c96b0..e8d26ef 100644 --- a/docs/source-discovery/capability-source-matrix.md +++ b/docs/source-discovery/capability-source-matrix.md @@ -23,6 +23,8 @@ Offline B-route file-send map: `docs/source-discovery/2026-07-12-broute-file-sen Offline B-route bridge map: `docs/source-discovery/2026-07-12-broute-bridge-static-map.md` Offline B-route decision: `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md` In-process adapter static map: `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md` +Send/upload deep dive: `docs/source-discovery/2026-07-12-send-upload-deep-dive.md` +Login reachability validation items: `docs/source-discovery/2026-07-12-login-reachability-validation-items.md` ## Source priority @@ -43,8 +45,8 @@ Route rule: UIA helper / A-route / RPA is a backup route only. It can preserve d | `isphere_search_contacts` | bare sender/receiver JIDs extracted from normalized log-backed messages loaded from configured PacketReader file or directory source | validated copied `MsgLib.db` tables: `TD_Roster`, `TD_CustomEffigy`, `tblRecent`, `tblChatLevel`, `tblPersonMsg`; decrypted roster/contact stanzas from `Smark.SendReceive`; UIA helper source if display names are still missing | `docs/source-discovery/2026-07-10-msglib-readonly-schema-extraction.md`; `internal/isphere/contacts_test.go`; `internal/tools/isphere_contacts_test.go` | C34 documents optional MsgLib contact display enrichment; R2 adds deterministic exact-match-first ranking, case-insensitive de-duplication across log/MsgLib candidates, and preserves `source`/`raw_ref` | core contact search complete; optional richer fields later | | `isphere_search_groups` | decrypted `PacketReader.ProcessPacket` `type="groupchat"` stanzas and conference/MUC JIDs loaded from configured PacketReader file or directory source | validated copied `MsgLib.db` tables: `tblMsgGroupPersonMsg`, `TD_WorkGroupAuth`, `tblRecent`; UIA helper source if group display names are still missing | `docs/source-discovery/2026-07-10-msglib-readonly-schema-extraction.md`; `internal/isphere/groups_test.go`; `internal/tools/isphere_groups_test.go`; C9 ignored-log scan: PacketReader 86 groupchat/86 conference hits; Smark 24 groupchat/658 conference/631 muc hits | C34 documents optional MsgLib group display enrichment; R2 adds deterministic exact-match-first ranking, case-insensitive de-duplication across log/MsgLib candidates, and preserves `source`/`raw_ref` | core group search complete; optional member/owner hierarchy later | | `isphere_receive_files` | decrypted `PacketReader.ProcessPacket` file-transfer message stanzas via `internal/isphere.ListFilesFromMessages` and `isphere_receive_files` list mode; configured PacketReader file or directory source; `zyl\importal\` cache entries remain unlinked | MsgLib `TD_ReceiveFileRecord` safe metadata through explicit copied-DB path; decrypted `Smark.SendReceive` and `SaveToDB` traces for file-reference reconciliation; future UIA/client connector for download | `docs/source-discovery/2026-07-09-n12-pre-zyl-schema-notes.md#c12-file-transfer-evidence-precheck`; `docs/source-discovery/2026-07-10-file-download-mapping-precheck.md`; `docs/source-discovery/2026-07-10-file-cache-mapping-diagnostic.md`; `docs/source-discovery/2026-07-10-file-download-mapping-v2.md`; `docs/reports/2026-07-10-business-goals-smoke.md` | C22 verifies safe file-list contract args; R10 proves resolver scoring with fixture accepted matches; R11 adds structured download preview with `blocked`/`planned` status and side-effect flags false; R13/R14 confirms list is ready but real download is still blocked. | blocked for real download pending accepted real cache mapping and copy gate; list mode is complete | -| `isphere_send_message` | B-route selected: `in_process_adapter_research` after offline reverse. Static call path is confirmed through `AppContextManager.SendTxtMessageByJid(...)`, `MessageScheduling.SendChatMessage(...)`, `Chat.SendMessage`, and `XMPPConnection.send`, but no existing IPC/plugin/local HTTP send bridge is confirmed; default MCP tool still exposes preview/dry-run unless an explicit connector mode is configured | A-route fallback is now implemented for UI action: `ISPHERE_SEND_CONNECTOR_MODE=uia_rpa` calls WinHelper `uia_send_message` against a configured HWND, writes `rtbSendMessage`, and clicks `btnSend`; this stays backup-only and network/protocol replay remains deferred | `docs/source-discovery/2026-07-10-send-message-source-precheck.md`; `docs/source-discovery/2026-07-10-send-message-connector-selection.md`; `docs/source-discovery/2026-07-10-send-sidecar-b-first-plan.md`; `docs/source-discovery/2026-07-10-returned-live-probe-analysis.md`; `docs/source-discovery/2026-07-10-send-connector-preflight.md`; `docs/source-discovery/2026-07-10-send-sandbox-gate.md`; `docs/source-discovery/2026-07-10-returned-send-sandbox-analysis.md`; `docs/source-discovery/2026-07-10-returned-send-sandbox-analysis-v2.md`; `docs/source-discovery/2026-07-10-returned-send-sent-record-diagnostic.md`; `docs/source-discovery/2026-07-11-a-route-uia-send.md`; `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`; `docs/source-discovery/2026-07-12-broute-text-send-static-map.md`; `docs/source-discovery/2026-07-12-broute-bridge-static-map.md`; `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`; `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`; `internal/tools/isphere_send_message_test.go`; `cmd/isphere-capability-smoke/main.go`; `docs/reports/2026-07-10-business-goals-smoke.md` | R6f-R6l define connector contract, audit/idempotency replay, production gate, B-route shell, strict-v2 package, and explicit production closure. R10a validates two returned sent-record packages as manual-only evidence. A-route adds local UI action readiness: synthetic window proof plus real offline `frmP2PChat` open/write/click target proof. Offline B-route reverse confirms the send call path but rejects existing IPC/plugin-first for this evidence set; business delivery is still not verified because local runtime is offline and no success/ack or sent-record hash evidence has passed. | B-route now exposes only the `in_process_contract` connector mode for request-shape/audit validation; keep external sidecar preview/probe-only and A-route UI action backup-only; production remains blocked until logged-in adapter reachability plus online sent-record/content-hash/ack evidence passes | -| `isphere_send_file` | B-route selected after offline reverse: managed file send is upload-first through `OffLineFileSend.sendFile()`, `FileUploadPara`, `IMPP.Service*.dll` `IFileTransfer.FileUpload(...)`, then chat file-message finalization through `trans_UploadCompleted(fileId)`, `MessageScheduling.SendFileMessage`, and `Chat.sendFileMessage(...)`; current MCP tool exposes preview/dry-run only | A-route file fallback is not implemented yet; real offline UIA dump did not expose stable `btnSendFile`, so the fallback slice remains toolbar/menu locator discovery; native `TcpFileTransfer.dll` is not the first B-route bridge because managed upload/message flow is now mapped | `docs/source-discovery/2026-07-10-send-message-source-precheck.md`; `docs/source-discovery/2026-07-10-send-message-connector-selection.md`; `docs/source-discovery/2026-07-10-send-sidecar-b-first-plan.md`; `docs/source-discovery/2026-07-10-returned-live-probe-analysis.md`; `docs/source-discovery/2026-07-10-send-connector-preflight.md`; `docs/source-discovery/2026-07-10-send-file-sandbox-gate.md`; `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`; `docs/source-discovery/2026-07-12-broute-file-send-static-map.md`; `docs/source-discovery/2026-07-12-broute-bridge-static-map.md`; `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`; `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`; `internal/tools/isphere_files_test.go`; `docs/reports/2026-07-10-business-goals-smoke.md` | R7 registers send-file preview as the tenth MCP tool; R8 adds audit/idempotency duplicate/conflict hardening without raw file paths/content; R9 builds and verifies the online send-file evidence package; R13/R14 confirms preview is ready and production upload remains blocked. Offline B-route reverse confirms upload-first/file-message-second and shows file id/auth/runtime reachability are the blockers. A-route real-window work confirms file-button automation still needs a separate locator node. | blocked until B-route in-process adapter research proves logged-in access to `IFileTransfer.FileUpload`, returned `FileUploadResult.FileID`, and `Chat.sendFileMessage` finalization; production file upload/send remains blocked until online evidence exists; A-route locator remains backup-only | +| `isphere_send_message` | B-route selected: `in_process_adapter_research` after offline reverse. Static call path is confirmed through `AppContextManager.SendTxtMessageByJid(...)`, `MessageScheduling.SendChatMessage(...)`, `Chat.SendMessage`, and `XMPPConnection.send`, but no existing IPC/plugin/local HTTP send bridge is confirmed; default MCP tool still exposes preview/dry-run unless an explicit connector mode is configured | A-route fallback is now implemented for UI action: `ISPHERE_SEND_CONNECTOR_MODE=uia_rpa` calls WinHelper `uia_send_message` against a configured HWND, writes `rtbSendMessage`, and clicks `btnSend`; this stays backup-only and network/protocol replay remains deferred | `docs/source-discovery/2026-07-10-send-message-source-precheck.md`; `docs/source-discovery/2026-07-10-send-message-connector-selection.md`; `docs/source-discovery/2026-07-10-send-sidecar-b-first-plan.md`; `docs/source-discovery/2026-07-10-returned-live-probe-analysis.md`; `docs/source-discovery/2026-07-10-send-connector-preflight.md`; `docs/source-discovery/2026-07-10-send-sandbox-gate.md`; `docs/source-discovery/2026-07-10-returned-send-sandbox-analysis.md`; `docs/source-discovery/2026-07-10-returned-send-sandbox-analysis-v2.md`; `docs/source-discovery/2026-07-10-returned-send-sent-record-diagnostic.md`; `docs/source-discovery/2026-07-11-a-route-uia-send.md`; `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`; `docs/source-discovery/2026-07-12-broute-text-send-static-map.md`; `docs/source-discovery/2026-07-12-broute-bridge-static-map.md`; `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`; `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`; `docs/source-discovery/2026-07-12-send-upload-deep-dive.md`; `docs/source-discovery/2026-07-12-login-reachability-validation-items.md`; `internal/tools/isphere_send_message_test.go`; `cmd/isphere-capability-smoke/main.go`; `docs/reports/2026-07-10-business-goals-smoke.md` | R6f-R6l define connector contract, audit/idempotency replay, production gate, B-route shell, strict-v2 package, and explicit production closure. R10a validates two returned sent-record packages as manual-only evidence. A-route adds local UI action readiness: synthetic window proof plus real offline `frmP2PChat` open/write/click target proof. Offline B-route reverse confirms the send call path but rejects existing IPC/plugin-first for this evidence set; business delivery is still not verified because local runtime is offline and no success/ack or sent-record hash evidence has passed. | B-route now exposes only the `in_process_contract` connector mode for request-shape/audit validation; next work is the 2026-07-13 login reachability probe covering AppContextManager/IAppContextManager, Chat/XMPPConnection, target JID mapping, and sent-record/content-hash/ack correlation; keep external sidecar preview/probe-only and A-route UI action backup-only; production remains blocked until those P0 items pass | +| `isphere_send_file` | B-route selected after offline reverse: managed file send is upload-first through `OffLineFileSend.sendFile()`, `FileUploadPara`, `IMPP.Service*.dll` `IFileTransfer.FileUpload(...)`, then chat file-message finalization through `trans_UploadCompleted(fileId)`, `MessageScheduling.SendFileMessage`, and `Chat.sendFileMessage(...)`; current MCP tool exposes preview/dry-run only | A-route file fallback is not implemented yet; real offline UIA dump did not expose stable `btnSendFile`, so the fallback slice remains toolbar/menu locator discovery; native `TcpFileTransfer.dll` is not the first B-route bridge because managed upload/message flow is now mapped | `docs/source-discovery/2026-07-10-send-message-source-precheck.md`; `docs/source-discovery/2026-07-10-send-message-connector-selection.md`; `docs/source-discovery/2026-07-10-send-sidecar-b-first-plan.md`; `docs/source-discovery/2026-07-10-returned-live-probe-analysis.md`; `docs/source-discovery/2026-07-10-send-connector-preflight.md`; `docs/source-discovery/2026-07-10-send-file-sandbox-gate.md`; `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`; `docs/source-discovery/2026-07-12-broute-file-send-static-map.md`; `docs/source-discovery/2026-07-12-broute-bridge-static-map.md`; `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`; `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`; `docs/source-discovery/2026-07-12-send-upload-deep-dive.md`; `docs/source-discovery/2026-07-12-login-reachability-validation-items.md`; `internal/tools/isphere_files_test.go`; `docs/reports/2026-07-10-business-goals-smoke.md` | R7 registers send-file preview as the tenth MCP tool; R8 adds audit/idempotency duplicate/conflict hardening without raw file paths/content; R9 builds and verifies the online send-file evidence package; R13/R14 confirms preview is ready and production upload remains blocked. Offline B-route reverse confirms upload-first/file-message-second and shows file id/auth/runtime reachability are the blockers. A-route real-window work confirms file-button automation still needs a separate locator node. | blocked until the login reachability probe proves `FileUploadPara` host/port/domain/local path/token presence, logged-in access to `IFileTransfer.FileUpload`, returned `FileUploadResult.FileID`, and `Chat.sendFileMessage` finalization; production file upload/send remains blocked until online upload plus sent-record/ack evidence exists; A-route locator remains backup-only | ## Stage C entry rule @@ -61,4 +63,4 @@ Start Stage C with a narrow log-backed `isphere_receive_messages` source abstrac ## Deferred source work -`MsgLib.db` has a validated copied read-only open path through the bundled 32-bit `System.Data.SQLite.dll` and password `123`. C27 adds `MsgLibReadSidecar` as the bounded x86 .NET reader boundary, C28 adds the Go `internal/msglib` process client, C29 adds bounded `display_entities` extraction, C30 wires it as optional contact/group MCP enrichment, C31 proves real copied-DB MCP enrichment with sanitized output, C32 reuses it for receive-message display fields, C33 proves that receive display path through a real copied-DB MCP smoke without printing entity values, C34 documents the operator setup/verification path, C35 maps MsgLib message tables to receive-message contract fields without reading row values, C36 adds metadata-only `message_sources` readiness, C37 defines the bounded DB-backed receive-source design, C38 implements sidecar/Go-wrapper `list_messages` with sanitized verification, C39 adds a Go adapter from MsgLib list results to the receive-message domain model, C40 adds explicit tool-level `msglib_readonly` source selection, C41 wires env-configured explicit MsgLib receive with optional sanitized smoke, R1 documents source reconciliation keys, and R2 hardens contact/group search ranking and de-duplication. R6j/R6k confirm the send-message strict-v2 production gate is still not passed; R10a confirms the returned sent-record packages are manual-only evidence and do not unlock production send; R10/R11 define file-download resolver/preview behavior while keeping real copy blocked; R12 adds receive-source reconciliation without changing default routing; R13/R14 publish business-goals smoke and the release-candidate status. A-route now proves UI write/click readiness against synthetic and real offline chat windows, but not online delivery. The active B-route follow-up is now the in-process contract path in `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`: validate logged-in adapter reachability before production send/file work. A-route RPA remains backup-only under `docs/superpowers/plans/2026-07-11-a-route-rpa-send.md`. +`MsgLib.db` has a validated copied read-only open path through the bundled 32-bit `System.Data.SQLite.dll` and password `123`. C27 adds `MsgLibReadSidecar` as the bounded x86 .NET reader boundary, C28 adds the Go `internal/msglib` process client, C29 adds bounded `display_entities` extraction, C30 wires it as optional contact/group MCP enrichment, C31 proves real copied-DB MCP enrichment with sanitized output, C32 reuses it for receive-message display fields, C33 proves that receive display path through a real copied-DB MCP smoke without printing entity values, C34 documents the operator setup/verification path, C35 maps MsgLib message tables to receive-message contract fields without reading row values, C36 adds metadata-only `message_sources` readiness, C37 defines the bounded DB-backed receive-source design, C38 implements sidecar/Go-wrapper `list_messages` with sanitized verification, C39 adds a Go adapter from MsgLib list results to the receive-message domain model, C40 adds explicit tool-level `msglib_readonly` source selection, C41 wires env-configured explicit MsgLib receive with optional sanitized smoke, R1 documents source reconciliation keys, and R2 hardens contact/group search ranking and de-duplication. R6j/R6k confirm the send-message strict-v2 production gate is still not passed; R10a confirms the returned sent-record packages are manual-only evidence and do not unlock production send; R10/R11 define file-download resolver/preview behavior while keeping real copy blocked; R12 adds receive-source reconciliation without changing default routing; R13/R14 publish business-goals smoke and the release-candidate status. A-route now proves UI write/click readiness against synthetic and real offline chat windows, but not online delivery. The active B-route follow-up is now the login reachability probe path in `docs/source-discovery/2026-07-12-login-reachability-validation-items.md`, generated from `docs/source-discovery/2026-07-12-send-upload-deep-dive.md`: validate logged-in adapter reachability before production send/file work. A-route RPA remains backup-only under `docs/superpowers/plans/2026-07-11-a-route-rpa-send.md`. diff --git a/scripts/extract-send-upload-deep-dive.ps1 b/scripts/extract-send-upload-deep-dive.ps1 new file mode 100644 index 0000000..0f1eedc --- /dev/null +++ b/scripts/extract-send-upload-deep-dive.ps1 @@ -0,0 +1,375 @@ +param( + [string]$IlDir = "runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il", + [string]$OutputDir = "runs/send-upload-deep-dive", + [string]$ReportPath = "docs/source-discovery/2026-07-12-send-upload-deep-dive.md", + [string]$ValidationPath = "docs/source-discovery/2026-07-12-login-reachability-validation-items.md", + [int]$WindowRadius = 5, + [int]$MaxEvidencePerItem = 20 +) + +$ErrorActionPreference = "Stop" + +$repo = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path +$ilDirFull = Join-Path $repo $IlDir +$outDir = Join-Path $repo $OutputDir +$reportFullPath = Join-Path $repo $ReportPath +$validationFullPath = Join-Path $repo $ValidationPath +New-Item -ItemType Directory -Force -Path $outDir | Out-Null +New-Item -ItemType Directory -Force -Path (Split-Path -Parent $reportFullPath) | Out-Null +New-Item -ItemType Directory -Force -Path (Split-Path -Parent $validationFullPath) | Out-Null + +$sources = @( + @{ path = "IMPlatformClient.exe.il"; role = "main client; high-level send, file-send orchestration, runtime auth/service state" }, + @{ path = "smack.dll.il"; role = "Chat/XMPP send implementation and file-message primitive" }, + @{ path = "IMPP.Service.dll.il"; role = "file upload HTTP/service implementation" }, + @{ path = "IMPP.ServiceBase.dll.il"; role = "FileUploadPara/FileUploadResult/FileTransferParaBase DTO contracts" }, + @{ path = "IMPP.Interface.dll.il"; role = "IAppContextManager/IFileTransfer interface contracts" }, + @{ path = "IMPP.Common.dll.il"; role = "ServiceManager/Auth DTOs and common runtime state" } +) + +$items = @( + @{ + key = "text_entry_app_context" + title = "Text send high-level entry: AppContextManager.SendTxtMessageByJid" + stage = "text_send" + meaning = "Best business-level text-send candidate if reachable in logged-in runtime." + must_verify = @("Reach AppContextManager instance", "Confirm target JID/chat type mapping", "Invoke dry/probe path without send first", "Correlate sent record/ack after real send test") + patterns = @("AppContextManager::SendTxtMessageByJid", "\bSendTxtMessageByJid\b", "IAppContextManager::SendTxtMessageByJid") + }, + @{ + key = "text_entry_scheduling" + title = "Text send scheduling fallback: MessageScheduling.SendChatMessage" + stage = "text_send" + meaning = "Fallback text-send path if AppContextManager is hard to reach but Chat/Roster args exist." + must_verify = @("Locate or construct RosterContactsArgs", "Locate Chat instance", "Confirm direct/group branch", "Correlate sent record/ack") + patterns = @("MessageScheduling::SendChatMessage", "SendChatMessage\(") + }, + @{ + key = "chat_low_level_send" + title = "Low-level text primitive: Chat.SendMessage -> XMPPConnection.send" + stage = "text_send" + meaning = "Confirms final XMPP send primitive; not enough alone without authenticated Chat/XMPP state." + must_verify = @("Locate Chat instance", "Locate authenticated XMPPConnection", "Confirm direct/group message payload", "Capture ack/sent-record") + patterns = @("com\.vision\.smack\.Chat::SendMessage", "com\.vision\.smack\.XMPPConnection::send", "callvirt instance void com\.vision\.smack\.XMPPConnection::send") + }, + @{ + key = "file_upload_para_base" + title = "Upload parameter base: FileTransferParaBase" + stage = "file_upload" + meaning = "Defines host, port, domain, local path, timeout/cache and token fields required by upload/download DTOs." + must_verify = @("Host", "Port", "Domain", "LocalFilePath", "Token", "Cache/timeout flags if present") + patterns = @("FileTransferParaBase", "get_Host\(\)", "get_Port\(\)", "get_Domain\(\)", "get_LocalFilePath\(\)", "get_Token\(\)") + }, + @{ + key = "file_upload_para" + title = "Upload DTO: FileUploadPara" + stage = "file_upload" + meaning = "Concrete upload request DTO; adds IsImg/IsPublic and invokes FileTransferParaBase constructor." + must_verify = @("Constructor arguments", "IsImg", "IsPublic", "Token value", "Local file path normalization") + patterns = @("FileUploadPara", "FileUploadPara::\.ctor", "get_IsImg\(\)", "get_IsPublic\(\)", "set_IsImg", "set_IsPublic") + }, + @{ + key = "file_upload_service" + title = "Upload service: IFileTransfer/FileTransfer.FileUpload" + stage = "file_upload" + meaning = "Managed upload entry; returns FileUploadResult and internally writes multipart token/form data." + must_verify = @("Reach IFileTransfer instance", "Call FileUpload with safe test file", "Capture FileUploadResult", "Capture HTTP server/token fields without leaking token") + patterns = @("FileTransfer::FileUpload", "IFileTransfer::FileUpload", 'Content-Disposition: form-data; name="token"', "FileUploadResult") + }, + @{ + key = "file_upload_auth" + title = "Upload auth/server state: HTTPFileServer + Auth token" + stage = "file_upload" + meaning = "File upload depends on runtime server/auth state, not only a local file path." + must_verify = @("HTTPFileServer host/port", "UnifiedAuthentication/Auth token", "Domain/resource", "Access token/client id if present") + patterns = @("get_HTTPFileServer\(\)", "UnifiedAuthentication", "Auth::get_token", "accessToken", "clientId", "HTTPFileServer") + }, + @{ + key = "file_upload_result" + title = "Upload result: FileUploadResult.FileID and remote metadata" + stage = "file_upload_result" + meaning = "Server-issued FileID is required before a chat file message is meaningful." + must_verify = @("FileID", "URL or remote folder if present", "size/name metadata", "failure code/message") + patterns = @("FileUploadResult::get_FileID", "FileUploadResult::set_FileID", "FileUploadResult", "RemoteFolder", "get_Url", "get_URL") + }, + @{ + key = "file_message_finalizer" + title = "File-message finalization: trans_UploadCompleted / SendFileMessage / Chat.sendFileMessage" + stage = "send_file_message" + meaning = "After upload succeeds, the client constructs offline file-transfer content and sends chat file message." + must_verify = @("trans_UploadCompleted receives FileID", "OFFLINE_FILE_TRANSFER payload fields", "Target Chat/JID", "Sent file record/ack") + patterns = @("OffLineFileSend::trans_UploadCompleted", "MessageScheduling::SendFileMessage", "Chat::sendFileMessage", "OFFLINE_FILE_TRANSFER") + }, + @{ + key = "target_chat_resolution" + title = "Target resolution: JID -> Chat / ChatRoom" + stage = "runtime_context" + meaning = "Both text and file send need a target JID mapped to Chat or ChatRoom; group handling may differ." + must_verify = @("Contact JID", "Group/conference JID", "ChatManager.GetChat", "ChatRoom branch and permissions") + patterns = @("ChatManager::GetChat", "GetChat\(", "ChatRoom", "get_RosterJid", "get_ChatRoomJid", "get_HasSpeechAuthJid") + }, + @{ + key = "runtime_owner" + title = "Runtime owner: frmMain / IMPPManager / MessageCenter" + stage = "runtime_context" + meaning = "Likely owners of initialized logged-in state and message center callbacks." + must_verify = @("Running frmMain", "IMPPManager.UserInfo", "MessageCenter", "Reconnect success state", "loaded assemblies") + patterns = @("class IMPP\.Client\.frmMain", "IMPPManager::get_UserInfo", "GetMessageCenter\(\)", "MessageCenter", "OnReConnectionSucceed") + } +) + +function Get-RelativePath([string]$Path) { + if ($Path.StartsWith($repo, [System.StringComparison]::OrdinalIgnoreCase)) { + return $Path.Substring($repo.Length).TrimStart([char[]]@('\', '/')) + } + return $Path +} + +function Write-Utf8NoBomLf([string]$Path, [string]$Text) { + $utf8NoBom = [System.Text.UTF8Encoding]::new($false) + $normalized = $Text -replace "`r`n", "`n" + $normalized = $normalized -replace "`r", "`n" + $normalized = $normalized.TrimEnd() + "`n" + [System.IO.File]::WriteAllText($Path, $normalized, $utf8NoBom) +} + +function Get-EvidenceKind([string]$Line) { + if ($Line -match "^\s*\.class\b") { return "type_definition" } + if ($Line -match "^\s*\.method\b") { return "method_header" } + if ($Line -match "^\s*\.field\b") { return "field" } + if ($Line -match "^\s*\.property\b") { return "property" } + if ($Line -match "\bend of method\b") { return "method_end" } + if ($Line -match "\bnewobj\b") { return "constructor_call" } + if ($Line -match "\bcall(?:virt)?\b") { return "callsite" } + if ($Line -match "\bldstr\b") { return "string_literal" } + if ($Line -match "^\s*(instance|static)\b.*\(") { return "signature_continuation" } + return "reference" +} + +function Get-MethodContext($Lines, [int]$Index) { + $start = [Math]::Max(0, $Index - 120) + for ($i = $Index; $i -ge $start; $i--) { + if ($Lines[$i] -match "^\s*\.method\b") { + $header = $Lines[$i].Trim() + if (($i + 1) -lt $Lines.Count -and $Lines[$i + 1] -match "^\s+(instance|static|default)\b") { + $header = ($header + " " + $Lines[$i + 1].Trim()) + } + return "L$($i + 1): $header" + } + } + return "" +} + +function Find-Evidence($Item) { + $evidence = New-Object System.Collections.Generic.List[object] + foreach ($source in $sources) { + $path = Join-Path $ilDirFull $source.path + if (-not (Test-Path -LiteralPath $path)) { continue } + $lines = [System.IO.File]::ReadAllLines($path) + for ($i = 0; $i -lt $lines.Count; $i++) { + $line = $lines[$i] + foreach ($pattern in $Item.patterns) { + if ($line -match $pattern) { + $evidence.Add([pscustomobject]@{ + source = Get-RelativePath $path + source_role = $source.role + line = $i + 1 + kind = Get-EvidenceKind $line + pattern = $pattern + snippet = $line.Trim() + context = Get-MethodContext $lines $i + }) + break + } + } + if ($evidence.Count -ge $MaxEvidencePerItem) { break } + } + if ($evidence.Count -ge $MaxEvidencePerItem) { break } + } + return $evidence.ToArray() +} + +$sourceSummary = foreach ($source in $sources) { + $path = Join-Path $ilDirFull $source.path + $exists = Test-Path -LiteralPath $path + $lineCount = 0 + $size = 0 + if ($exists) { + $file = Get-Item -LiteralPath $path + $size = $file.Length + $lineCount = ([System.IO.File]::ReadLines($path) | Measure-Object).Count + } + [pscustomobject]@{ + path = Get-RelativePath $path + role = $source.role + exists = $exists + lines = $lineCount + size_bytes = $size + } +} + +$itemResults = foreach ($item in $items) { + $evidence = Find-Evidence $item + $status = if ($evidence.Count -gt 0) { "static_evidence_found" } else { "missing_static_evidence" } + [pscustomobject]@{ + key = $item.key + title = $item.title + stage = $item.stage + meaning = $item.meaning + status = $status + evidence_count = $evidence.Count + must_verify = $item.must_verify + evidence = $evidence + } +} + +$newValidationItems = @( + [pscustomobject]@{ priority = "P0"; category = "runtime"; item = "Confirm logged-in IMPlatformClient.exe process and loaded assemblies"; evidence = "process id, module list, loaded managed assemblies"; unlocks = "all B-route adapter tests" }, + [pscustomobject]@{ priority = "P0"; category = "runtime"; item = "Confirm AppContextManager/IAppContextManager reachability"; evidence = "type visible, instance path, SendTxtMessageByJid callable shape"; unlocks = "text send high-level path" }, + [pscustomobject]@{ priority = "P0"; category = "runtime"; item = "Confirm Chat/XMPPConnection authenticated state"; evidence = "Chat instance, XMPPConnection state, target JID mapping"; unlocks = "text and file message finalization" }, + [pscustomobject]@{ priority = "P0"; category = "file_upload"; item = "Capture FileUploadPara required values without leaking token"; evidence = "host, port, domain, local path presence, IsImg/IsPublic, token-present boolean/hash only"; unlocks = "upload_file probe" }, + [pscustomobject]@{ priority = "P0"; category = "file_upload"; item = "Confirm IFileTransfer/FileTransfer.FileUpload reachability"; evidence = "service instance or constructor path, method signature, safe call readiness"; unlocks = "file upload" }, + [pscustomobject]@{ priority = "P0"; category = "file_upload_result"; item = "Confirm FileUploadResult.FileID after safe test upload"; evidence = "FileID present, size/name or URL/remote folder metadata, failure code if upload fails"; unlocks = "send_file_message" }, + [pscustomobject]@{ priority = "P0"; category = "send_file_message"; item = "Confirm trans_UploadCompleted/SendFileMessage consumes FileID"; evidence = "FileID enters payload, Chat.sendFileMessage invoked, sent file record/ack"; unlocks = "production file send" }, + [pscustomobject]@{ priority = "P0"; category = "ack"; item = "Correlate sent record/ack with content hash or file hash"; evidence = "sent record timestamp, target ref, body/file metadata hash, ack/ref id"; unlocks = "production gate" }, + [pscustomobject]@{ priority = "P1"; category = "group"; item = "Confirm group ChatRoom branch and permissions"; evidence = "ChatRoom type, speech/upload permission state, group JID"; unlocks = "group send/file send" }, + [pscustomobject]@{ priority = "P1"; category = "fallback"; item = "If B-route reachability fails, capture A-route UI evidence"; evidence = "window hwnd, rtbSendMessage, btnSend, screenshots, failure reason"; unlocks = "demo fallback only" } +) + +$result = [pscustomobject]@{ + ok = $true + generated_at = (Get-Date).ToUniversalTime().ToString("o") + decision = "continue_offline_deep_dive_then_login_reachability_probe" + sources = $sourceSummary + items = $itemResults + new_validation_items = $newValidationItems + originals_copied = $false + originals_modified = $false +} + +$jsonPath = Join-Path $outDir "send-upload-deep-dive.json" +Write-Utf8NoBomLf $jsonPath ($result | ConvertTo-Json -Depth 8) + +$md = New-Object System.Collections.Generic.List[string] +$md.Add("# Send / Upload Deep Dive") +$md.Add("") +$md.Add("Date: 2026-07-12") +$md.Add("") +$md.Add("## Business summary") +$md.Add("") +$md.Add("Offline deep dive confirms the remaining work is not generic sending code. The business blocker is logged-in runtime reachability plus online proof. Text send needs reachable AppContextManager/MessageScheduling/Chat. File send needs upload parameters and server-issued FileUploadResult.FileID before Chat.sendFileMessage can be meaningful.") +$md.Add("") +$md.Add("## Decision") +$md.Add("") +$md.Add("| Question | Answer |") +$md.Add("| --- | --- |") +$md.Add("| Should work stop before login? | No |") +$md.Add("| Highest-value offline work | Deepen send/upload decomposition and prepare login validation items |") +$md.Add("| Can production send be enabled offline? | No |") +$md.Add("| Next package | login reachability probe package |") +$md.Add("") +$md.Add("## Sources") +$md.Add("") +$md.Add("| Source | Role | Exists | Lines | Size bytes |") +$md.Add("| --- | --- | --- | ---: | ---: |") +foreach ($source in $sourceSummary) { + $md.Add("| ``$($source.path)`` | $($source.role) | $($source.exists) | $($source.lines) | $($source.size_bytes) |") +} +$md.Add("") +$md.Add("## Deep-dive findings") +$md.Add("") +$md.Add("| Item | Stage | Status | Evidence | Business meaning |") +$md.Add("| --- | --- | --- | ---: | --- |") +foreach ($item in $itemResults) { + $md.Add("| ``$($item.title)`` | ``$($item.stage)`` | ``$($item.status)`` | $($item.evidence_count) | $($item.meaning) |") +} +$md.Add("") +$md.Add("## What this adds to tomorrow's login validation") +$md.Add("") +$md.Add("| Priority | Category | Validation item | Evidence to capture | Unlocks |") +$md.Add("| --- | --- | --- | --- | --- |") +foreach ($v in $newValidationItems) { + $md.Add("| $($v.priority) | $($v.category) | $($v.item) | $($v.evidence) | $($v.unlocks) |") +} +$md.Add("") +$md.Add("## Evidence by item") +foreach ($item in $itemResults) { + $md.Add("") + $md.Add("### $($item.title)") + $md.Add("") + $md.Add("Stage: ``$($item.stage)``. Status: ``$($item.status)``. Evidence count: $($item.evidence_count).") + $md.Add("") + $md.Add("Business meaning: $($item.meaning)") + $md.Add("") + $md.Add("Must verify tomorrow:") + foreach ($verify in $item.must_verify) { + $md.Add("- $verify") + } + $md.Add("") + if ($item.evidence_count -eq 0) { + $md.Add("No static evidence found in configured IL sources.") + continue + } + $md.Add("| Source | Kind | Snippet | Context |") + $md.Add("| --- | --- | --- | --- |") + foreach ($e in $item.evidence) { + $snippet = ($e.snippet -replace "\|", "\\|") + if ($snippet.Length -gt 240) { $snippet = $snippet.Substring(0, 237) + "..." } + $context = ($e.context -replace "\|", "\\|") + if ($context.Length -gt 180) { $context = $context.Substring(0, 177) + "..." } + $md.Add("| ``$($e.source):$($e.line)`` | ``$($e.kind)`` | ``$snippet`` | ``$context`` |") + } +} +$md.Add("") +$md.Add("## Updated stop / continue rules") +$md.Add("") +$md.Add("Continue B-route tomorrow if P0 runtime, text-send, upload, FileID, and ack probes produce positive or actionable evidence. Stop B-route and escalate if logged-in runtime cannot expose AppContextManager/MessageScheduling/Chat/IFileTransfer, or if upload cannot produce FileUploadResult.FileID. Keep A-route/RPA backup-only for demo continuity.") + +Write-Utf8NoBomLf $reportFullPath ($md -join "`n") + +$validation = New-Object System.Collections.Generic.List[string] +$validation.Add("# Login Reachability Validation Items") +$validation.Add("") +$validation.Add("Date: 2026-07-12") +$validation.Add("") +$validation.Add("Purpose: this is the operator-facing checklist for the 2026-07-13 logged-in environment. It is generated from the offline send/upload deep dive and should be used to build the one-shot reachability probe package.") +$validation.Add("") +$validation.Add("## P0 items") +$validation.Add("") +foreach ($v in $newValidationItems | Where-Object { $_.priority -eq "P0" }) { + $validation.Add("### $($v.item)") + $validation.Add("") + $validation.Add("- Category: $($v.category)") + $validation.Add("- Evidence to capture: $($v.evidence)") + $validation.Add("- Unlocks: $($v.unlocks)") + $validation.Add("") +} +$validation.Add("## P1 items") +$validation.Add("") +foreach ($v in $newValidationItems | Where-Object { $_.priority -eq "P1" }) { + $validation.Add("### $($v.item)") + $validation.Add("") + $validation.Add("- Category: $($v.category)") + $validation.Add("- Evidence to capture: $($v.evidence)") + $validation.Add("- Unlocks: $($v.unlocks)") + $validation.Add("") +} +$validation.Add("## Pass criteria") +$validation.Add("") +$validation.Add("- Text send can move forward when logged-in runtime exposes AppContextManager or MessageScheduling plus Chat/XMPPConnection and sent-record/ack correlation is possible.") +$validation.Add("- File send can move forward when logged-in runtime exposes IFileTransfer/FileUpload, FileUploadPara values, FileUploadResult.FileID, and Chat.sendFileMessage finalization evidence.") +$validation.Add("- Production remains blocked if any P0 item is missing or only static evidence is available.") + +Write-Utf8NoBomLf $validationFullPath ($validation -join "`n") + +[pscustomobject]@{ + ok = $true + json_path = $jsonPath + report_path = $reportFullPath + validation_path = $validationFullPath + items = $itemResults.Count + validation_items = $newValidationItems.Count + decision = $result.decision + originals_copied = $false + originals_modified = $false +} | ConvertTo-Json -Depth 5