diff --git a/rules/dist/ime-log-patterns.json b/rules/dist/ime-log-patterns.json index e1805c31..6a59e1b5 100644 --- a/rules/dist/ime-log-patterns.json +++ b/rules/dist/ime-log-patterns.json @@ -4,12 +4,23 @@ { "patternId": "HS-COMPLIANCE", "category": "always", - "pattern": "\\[HS\\] the (?pre|post)-remdiation detection script compliance result for (?[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}) is (?True|False)", + "pattern": "\\[HS\\] the (?pre|post)-rem(?:e)?diation detection script compliance result for (?[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}) is (?True|False)", "action": "healthScriptDetectionResult", "parameters": { "scriptType": "remediation" }, - "description": "Early-signal fallback for health-script detection / post-detection results. Microsoft IME emits this line immediately after each detection script runs, ~30-90 seconds before the consolidated [HS] new result = JSON line is logged (which only fires after IME's batch-send to the Microsoft service). Short Autopilot enrollments often end inside that gap, so this pattern guarantees at least the compliance verdict is captured. The full data version arrives later via HS-NEW-RESULT and replaces this sparse entry through the UI dedupe (dataCompleteness scoring).", + "description": "Early-signal fallback for health-script detection / post-detection results. Microsoft IME emits this line immediately after each detection script runs, ~30-90 seconds before the consolidated [HS] new result = JSON line is logged (which only fires after IME's batch-send to the Microsoft service). Short Autopilot enrollments often end inside that gap, so this pattern guarantees at least the compliance verdict is captured. The full data version arrives later via HS-NEW-RESULT and replaces this sparse entry through the UI dedupe (dataCompleteness scoring). Tolerates both Microsoft's historical typo 'remdiation' and a future corrected 'remediation'. NOTE: IME 1.97 (Dec 2025) no longer emits the post- variant of this line; the post case is covered by HS-COMPLIANCE-POST.", + "enabled": true + }, + { + "patternId": "HS-COMPLIANCE-POST", + "category": "always", + "pattern": "\\[HS\\] the (?post) detection script result for (?[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}) is (?True|False)", + "action": "healthScriptDetectionResult", + "parameters": { + "scriptType": "remediation" + }, + "description": "Post-remediation detection result, current wording. IME 1.97 (Dec 2025) replaced the old '[HS] the post-remdiation detection script compliance result for ...' line (still covered by HS-COMPLIANCE for older logs) with '[HS] the post detection script result for is ' (ScriptProcessorV2.cs:721). The literal word 'post' in the line is captured as the part group so the handler classifies it as the post-detection phase.", "enabled": true }, { @@ -139,6 +150,14 @@ "description": "Captures the install attempt number for the current app. IME logs 'Execute retry 0' for the first attempt and increments on each retry. Reported as attempt+1 so retry 0 becomes AttemptNumber=1 (human-friendly: first attempt).", "enabled": true }, + { + "patternId": "IME-CACHE-MISS", + "category": "always", + "pattern": "\\[Win32App\\] Content cache miss for app \\(id = {GUID}, name = (?.*?)\\), start downloading", + "action": "updateName", + "description": "Captures 'Content cache miss for app (id = , name = ), start downloading...' (ContentManager.cs) as a secondary app-name source. Fires right before a real download begins, so it resolves names for exactly the apps that will produce download/install activity — a redundancy for IME-POLICIES-based naming after IME retired the old name-bearing processing lines.", + "enabled": true + }, { "patternId": "IME-DECRYPT-FAILED", "category": "currentPhase", @@ -168,15 +187,15 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] Detected app {GUID} ", "action": "updateStateInstalled", - "description": "Detects when an app is detected as installed (old log format).", - "enabled": true + "description": "Detects when an app is detected as installed (old log format). DISABLED 2026-08-17: the standalone 'Detected app ' line no longer exists in IME 1.97.107; this regex instead matched the 'Detected app ... and intent is to install, skip applicability check' line, colliding with IME-SKIP-INSTALL-DETECTED and firing updateStateInstalled and updateStateSkipped on the same physical line (see tasks/ime-v1-code-audit-2026-08-17.md).", + "enabled": false }, { "patternId": "IME-DETECTION-RESULT", "category": "always", - "pattern": "\\[Win32App\\]\\[DetectionActionHandler\\] Detection for policy with id: (?{GUID}) resulted in action status: Success and detection state: (?Detected|NotDetected)", + "pattern": "\\[Win32App\\]\\[DetectionActionHandler\\] Detection for policy with id: (?{GUID}) resulted in action status: Success and detection state: (?DetectedDifferentVersion|NotDetected|Detected)", "action": "captureDetectionResult", - "description": "Captures the detection rule result after IME runs detection for an app. 'Detected' means the detection rule matched (app is installed), 'NotDetected' means it did not. Excludes [SimulatedDetectionActionHandler] which fires during applicability pre-checks.", + "description": "Captures the detection rule result after IME runs detection for an app. 'Detected' means the detection rule matched (app is installed), 'NotDetected' means it did not, 'DetectedDifferentVersion' means a different version was found (supersedence / WinGet version mismatch). DetectedDifferentVersion must come first in the alternation so the unanchored regex does not mis-capture its 'Detected' prefix. Excludes [SimulatedDetectionActionHandler] which fires during applicability pre-checks.", "enabled": true }, { @@ -217,9 +236,9 @@ { "patternId": "IME-ENFORCEMENT-SUCCESS", "category": "currentPhase", - "pattern": "\\[Win32App\\]\\[ReportingManager\\] Execution state for app with id: {GUID} has been updated\\. Report delta: \\{\"\"EnforcementState\"\":\\{\"\"OldValue\"\":\"\"InProgressDownloadCompleted\"\",\"\"NewValue\"\":\"\"Success\"\"", + "pattern": "\\[Win32App\\]\\[ReportingManager\\] Execution state for app with id: {GUID} has been updated\\. Report delta: \\{\"\"EnforcementState\"\":\\{\"\"OldValue\"\":(?:\"\"\\w+\"\"|null),\"\"NewValue\"\":\"\"Success\"\"", "action": "updateStateInstalled", - "description": "Detects when an app's enforcement state transitions from InProgressDownloadCompleted to Success.", + "description": "Detects when an app's enforcement state transitions to Success in an Execution state report delta. OldValue is deliberately unpinned: besides InProgressDownloadCompleted it can be Error (retry succeeding in a later check-in), InProgressPendingReboot (post-reboot completion) or null (first write) — the previously pinned InProgressDownloadCompleted missed those legitimate success paths (IME 1.97 audit 2026-08-17).", "enabled": true }, { @@ -266,12 +285,12 @@ { "patternId": "IME-ERROR-REPORT", "category": "currentPhase", - "pattern": "\\[Win32App\\]\\[ReportingManager\\] Execution state for app with id: {GUID} has been updated\\. Report delta: \\{\"\"EnforcementState\"\":\\{\"\"OldValue\"\":\"\"(?\\w+)\"\",\"\"NewValue\"\":\"\"(?\\w+)\"\"", + "pattern": "\\[Win32App\\]\\[ReportingManager\\] Execution state for app with id: {GUID} has been updated\\. Report delta: \\{\"\"EnforcementState\"\":\\{\"\"OldValue\"\":(?:\"\"(?\\w+)\"\"|null),\"\"NewValue\"\":\"\"(?\\w+)\"\"", "action": "updateStateError", "parameters": { "checkTo": "true" }, - "description": "Captures enforcement state transitions via ReportingManager. Only triggers error when 'to' value indicates an error state.", + "description": "Captures enforcement state transitions via ReportingManager. Only triggers error when 'to' value indicates an error state. OldValue may be the unquoted JSON literal null on the first-ever write of a reporting state — transitions straight from the initial state (e.g. first write directly to an error state) would otherwise be invisible (IME 1.97 audit 2026-08-17).", "enabled": true }, { @@ -293,6 +312,14 @@ "description": "Detects when an app installer returned an exit code that has no mapping configured in Intune.", "enabled": true }, + { + "patternId": "IME-ESP-APP-REGISTERED", + "category": "always", + "pattern": "\\[Win32App\\]\\[EspManager\\] In EspPhase: \\w+\\. App {GUID} has been registered.*?App name: (?.*?)$", + "action": "updateName", + "description": "Captures the ESP tracked-app registration line ('App has been registered[ for user ]. App name: ', EspManager.cs) as an app-name source. Primary replacement for the retired IME-UPDATE-NAME-1/2/3 whose emitters were removed with IME's old V1/V2 processing pipeline; also documents exactly which apps IME registered for ESP tracking. Category 'always' so names resolve even before the first ApplicationPoller EspPhase line is seen.", + "enabled": true + }, { "patternId": "IME-ESP-PHASE", "category": "always", @@ -304,9 +331,9 @@ { "patternId": "IME-ESP-TRACK-STATUS", "category": "currentPhase", - "pattern": "\\[Win32App\\]\\[EspManager\\] Updating ESP tracked install status from (?\\w+) to (?\\w+) for application {GUID}\\.", + "pattern": "\\[Win32App\\]\\[EspManager\\] Updating ESP tracked install status from (?\\w+) to (?\\w+) for application {GUID}", "action": "espTrackStatus", - "description": "Captures ESP tracked install status transitions (e.g., InProgress to Installed) for a specific app.", + "description": "Captures ESP tracked install status transitions (e.g., InProgress to Installed) for a specific app. No trailing anchor: IME 1.97 (Dec 2025) appends ' with name: .' after the GUID (EspManager.cs), which broke the previous '\\.' suffix. 'from' can be the literal string 'null' on first tracking.", "enabled": true }, { @@ -320,6 +347,17 @@ "description": "Captures the installer exit code (lpExitCode) for the current app.", "enabled": true }, + { + "patternId": "IME-EXITCODE-MAPPED-FAILED", + "category": "currentPhase", + "pattern": "\\[Win32App\\] lpExitCode is defined as Failed$", + "action": "updateStateError", + "parameters": { + "useCurrentApp": "true" + }, + "description": "Marks the current app as failed when its exit code maps to Failed via the admin-defined return-code table ('[Win32App] lpExitCode is defined as ', Win32AppInstaller.cs). This is the NORMAL mapped-exit-code outcome; the previously matched 'Setting enforcementState as ... Error' line only fires on the rare no-mapping fallback path. The numeric exit code is captured separately by IME-EXITCODE, which precedes this line.", + "enabled": true + }, { "patternId": "IME-HRESULT", "category": "currentPhase", @@ -422,6 +460,17 @@ "description": "Captures the JSON policies list discovered by IME, used to build the app inventory.", "enabled": true }, + { + "patternId": "IME-RESTART-STOP-PROCESSING", + "category": "currentPhase", + "pattern": "\\[Win32App\\]\\[V3Processor\\] A restart is required to continue processing apps\\. Stop processing\\.", + "action": "updateStatePostponed", + "parameters": { + "useCurrentApp": "true" + }, + "description": "Detects IME aborting app processing because an app requires a restart ('A restart is required to continue processing apps. Stop processing.', SideCarV3AppProcessor.cs). Postpones the current app: remaining apps do nothing until after the reboot, which previously looked like an unexplained stall mid-ESP.", + "enabled": true + }, { "patternId": "IME-SESSION-CHANGE", "category": "always", @@ -435,24 +484,24 @@ "category": "always", "pattern": "\\[Win32App\\] ProcessAppWithDependencies starts for {GUID} with name", "action": "setCurrentApp", - "description": "Detects when IME begins processing an app with its dependency chain, setting it as the current app.", - "enabled": true + "description": "Detects when IME begins processing an app with its dependency chain, setting it as the current app. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-SET-CURRENT-2", "category": "always", "pattern": "\\[Win32App\\] ExecManager: processing targeted app.*?\\bid\\W+{GUID}", "action": "setCurrentApp", - "description": "Detects when the IME ExecManager starts processing a targeted app, setting it as current.", - "enabled": true + "description": "Detects when the IME ExecManager starts processing a targeted app, setting it as current. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-SET-CURRENT-3", "category": "always", "pattern": "\\[Win32App\\] ===Step=== Start to Present app {GUID}", "action": "setCurrentApp", - "description": "Detects the start of app presentation step in IME, setting the app as current.", - "enabled": true + "description": "Detects the start of app presentation step in IME, setting the app as current. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-SET-CURRENT-4", @@ -478,24 +527,24 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] (?=.*?\\bapplicability\\b)(?=.*?NotMet\\b).*?\\bapp\\W+{GUID}\\b", "action": "updateStateSkipped", - "description": "Detects when an app's applicability check returns NotMet (old log format with lookaheads).", - "enabled": true + "description": "Detects when an app's applicability check returns NotMet (old log format with lookaheads). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-SKIP-DEPENDENCY-DETECT", "category": "currentPhase", "pattern": "\\[Win32App\\] app\\W+{GUID}\\b.*?\\bis a dependency\\b.*?\\bDetect Only mode\\b.*?\\bfinished processing", "action": "updateStateSkipped", - "description": "Detects when a dependency app in Detect Only mode finishes processing (no install needed).", - "enabled": true + "description": "Detects when a dependency app in Detect Only mode finishes processing (no install needed). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-SKIP-DETECTED", "category": "currentPhase", "pattern": "\\[Win32App\\] Detected app {GUID}.*?skip next step", "action": "updateStateSkipped", - "description": "Detects when an already-detected app is skipped for further processing steps (old log format).", - "enabled": true + "description": "Detects when an already-detected app is skipped for further processing steps (old log format). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-SKIP-FILTERS", @@ -529,8 +578,8 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] NOT detected app {GUID}.*?skip un-installation", "action": "updateStateSkipped", - "description": "Detects when an app is not detected and uninstall is skipped (alternate old log format).", - "enabled": true + "description": "Detects when an app is not detected and uninstall is skipped (alternate old log format). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-STARTED", @@ -540,6 +589,17 @@ "description": "Detects when the Intune Management Extension (IME) agent starts up.", "enabled": true }, + { + "patternId": "IME-STOP-SIGNAL", + "category": "currentPhase", + "pattern": "EMS Agent received stop signal", + "action": "updateStatePostponed", + "parameters": { + "useCurrentApp": "true" + }, + "description": "Detects an IME service stop ('EMS Agent received stop signal', EmsAgentService.OnStop) — fired on manual restarts and agent-updater restarts, unlike the OS-shutdown-only 'shutdown signal' line matched by IME-SHUTDOWN. Postpones the current app installation, mirroring IME-SHUTDOWN semantics.", + "enabled": true + }, { "patternId": "IME-SUBGRAPH", "category": "currentPhase", @@ -564,24 +624,24 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] ExecManager: processing targeted app.*?name\\W+(?.*?)\\W+id\\W+{GUID}", "action": "updateName", - "description": "Captures the app name from ExecManager processing log (old format: name before id).", - "enabled": true + "description": "Captures the app name from ExecManager processing log (old format: name before id). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-UPDATE-NAME-2", "category": "currentPhase", "pattern": "\\[Win32App\\] ProcessAppWithDependencies starts for {GUID} with name (?.*?)$", "action": "updateName", - "description": "Captures the app name from ProcessAppWithDependencies log entry.", - "enabled": true + "description": "Captures the app name from ProcessAppWithDependencies log entry. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-UPDATE-NAME-3", "category": "currentPhase", "pattern": "\\[Win32App\\] Processing app \\(id={GUID}, name = (?.*?)\\)", "action": "updateName", - "description": "Captures the app name from the Processing app log entry.", - "enabled": true + "description": "Captures the app name from the Processing app log entry. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false }, { "patternId": "IME-USER-SESSION-COMPLETED", @@ -607,6 +667,14 @@ "description": "Captures the Win32 app ESP state (e.g., Installed, InProgress) for a specific app.", "enabled": true }, + { + "patternId": "IME-WINGET-ERROR", + "category": "currentPhase", + "pattern": "\\[WinGetMessageProcessor\\] Processing Progress for app = {GUID}.*?- Operation Phase = Error", + "action": "updateStateError", + "description": "Marks a WinGet (new Store) app as failed when its operation progress reports phase Error (WinGetOperationInstallPhase: Downloading/Installing/Queued/Finished/Error). Before this pattern only the Installing phase was matched, so WinGet failures never surfaced as app errors (IME 1.97 audit 2026-08-17).", + "enabled": true + }, { "patternId": "IME-WINGET-INSTALLING-1", "category": "currentPhase", diff --git a/rules/ime-log-patterns/HS-COMPLIANCE-POST.json b/rules/ime-log-patterns/HS-COMPLIANCE-POST.json new file mode 100644 index 00000000..c7d182f6 --- /dev/null +++ b/rules/ime-log-patterns/HS-COMPLIANCE-POST.json @@ -0,0 +1,10 @@ +{ + "$schema": "../schema/ime-log-pattern.schema.json", + "patternId": "HS-COMPLIANCE-POST", + "category": "always", + "pattern": "\\[HS\\] the (?post) detection script result for (?[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}) is (?True|False)", + "action": "healthScriptDetectionResult", + "parameters": { "scriptType": "remediation" }, + "description": "Post-remediation detection result, current wording. IME 1.97 (Dec 2025) replaced the old '[HS] the post-remdiation detection script compliance result for ...' line (still covered by HS-COMPLIANCE for older logs) with '[HS] the post detection script result for is ' (ScriptProcessorV2.cs:721). The literal word 'post' in the line is captured as the part group so the handler classifies it as the post-detection phase.", + "enabled": true +} diff --git a/rules/ime-log-patterns/HS-COMPLIANCE.json b/rules/ime-log-patterns/HS-COMPLIANCE.json index 74a253e8..279683ee 100644 --- a/rules/ime-log-patterns/HS-COMPLIANCE.json +++ b/rules/ime-log-patterns/HS-COMPLIANCE.json @@ -2,9 +2,9 @@ "$schema": "../schema/ime-log-pattern.schema.json", "patternId": "HS-COMPLIANCE", "category": "always", - "pattern": "\\[HS\\] the (?pre|post)-remdiation detection script compliance result for (?[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}) is (?True|False)", + "pattern": "\\[HS\\] the (?pre|post)-rem(?:e)?diation detection script compliance result for (?[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}) is (?True|False)", "action": "healthScriptDetectionResult", "parameters": { "scriptType": "remediation" }, - "description": "Early-signal fallback for health-script detection / post-detection results. Microsoft IME emits this line immediately after each detection script runs, ~30-90 seconds before the consolidated [HS] new result = JSON line is logged (which only fires after IME's batch-send to the Microsoft service). Short Autopilot enrollments often end inside that gap, so this pattern guarantees at least the compliance verdict is captured. The full data version arrives later via HS-NEW-RESULT and replaces this sparse entry through the UI dedupe (dataCompleteness scoring).", + "description": "Early-signal fallback for health-script detection / post-detection results. Microsoft IME emits this line immediately after each detection script runs, ~30-90 seconds before the consolidated [HS] new result = JSON line is logged (which only fires after IME's batch-send to the Microsoft service). Short Autopilot enrollments often end inside that gap, so this pattern guarantees at least the compliance verdict is captured. The full data version arrives later via HS-NEW-RESULT and replaces this sparse entry through the UI dedupe (dataCompleteness scoring). Tolerates both Microsoft's historical typo 'remdiation' and a future corrected 'remediation'. NOTE: IME 1.97 (Dec 2025) no longer emits the post- variant of this line; the post case is covered by HS-COMPLIANCE-POST.", "enabled": true } diff --git a/rules/ime-log-patterns/IME-CACHE-MISS.json b/rules/ime-log-patterns/IME-CACHE-MISS.json new file mode 100644 index 00000000..8672fd63 --- /dev/null +++ b/rules/ime-log-patterns/IME-CACHE-MISS.json @@ -0,0 +1,9 @@ +{ + "$schema": "../schema/ime-log-pattern.schema.json", + "patternId": "IME-CACHE-MISS", + "category": "always", + "pattern": "\\[Win32App\\] Content cache miss for app \\(id = {GUID}, name = (?.*?)\\), start downloading", + "action": "updateName", + "description": "Captures 'Content cache miss for app (id = , name = ), start downloading...' (ContentManager.cs) as a secondary app-name source. Fires right before a real download begins, so it resolves names for exactly the apps that will produce download/install activity — a redundancy for IME-POLICIES-based naming after IME retired the old name-bearing processing lines.", + "enabled": true +} diff --git a/rules/ime-log-patterns/IME-DETECTED-OLD.json b/rules/ime-log-patterns/IME-DETECTED-OLD.json index ced89b62..43d2766e 100644 --- a/rules/ime-log-patterns/IME-DETECTED-OLD.json +++ b/rules/ime-log-patterns/IME-DETECTED-OLD.json @@ -4,6 +4,6 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] Detected app {GUID} ", "action": "updateStateInstalled", - "description": "Detects when an app is detected as installed (old log format).", - "enabled": true + "description": "Detects when an app is detected as installed (old log format). DISABLED 2026-08-17: the standalone 'Detected app ' line no longer exists in IME 1.97.107; this regex instead matched the 'Detected app ... and intent is to install, skip applicability check' line, colliding with IME-SKIP-INSTALL-DETECTED and firing updateStateInstalled and updateStateSkipped on the same physical line (see tasks/ime-v1-code-audit-2026-08-17.md).", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-DETECTION-RESULT.json b/rules/ime-log-patterns/IME-DETECTION-RESULT.json index 214c7e86..a12ad4fe 100644 --- a/rules/ime-log-patterns/IME-DETECTION-RESULT.json +++ b/rules/ime-log-patterns/IME-DETECTION-RESULT.json @@ -2,8 +2,8 @@ "$schema": "../schema/ime-log-pattern.schema.json", "patternId": "IME-DETECTION-RESULT", "category": "always", - "pattern": "\\[Win32App\\]\\[DetectionActionHandler\\] Detection for policy with id: (?{GUID}) resulted in action status: Success and detection state: (?Detected|NotDetected)", + "pattern": "\\[Win32App\\]\\[DetectionActionHandler\\] Detection for policy with id: (?{GUID}) resulted in action status: Success and detection state: (?DetectedDifferentVersion|NotDetected|Detected)", "action": "captureDetectionResult", - "description": "Captures the detection rule result after IME runs detection for an app. 'Detected' means the detection rule matched (app is installed), 'NotDetected' means it did not. Excludes [SimulatedDetectionActionHandler] which fires during applicability pre-checks.", + "description": "Captures the detection rule result after IME runs detection for an app. 'Detected' means the detection rule matched (app is installed), 'NotDetected' means it did not, 'DetectedDifferentVersion' means a different version was found (supersedence / WinGet version mismatch). DetectedDifferentVersion must come first in the alternation so the unanchored regex does not mis-capture its 'Detected' prefix. Excludes [SimulatedDetectionActionHandler] which fires during applicability pre-checks.", "enabled": true } diff --git a/rules/ime-log-patterns/IME-ENFORCEMENT-SUCCESS.json b/rules/ime-log-patterns/IME-ENFORCEMENT-SUCCESS.json index 3aea03d9..d49f4918 100644 --- a/rules/ime-log-patterns/IME-ENFORCEMENT-SUCCESS.json +++ b/rules/ime-log-patterns/IME-ENFORCEMENT-SUCCESS.json @@ -2,8 +2,8 @@ "$schema": "../schema/ime-log-pattern.schema.json", "patternId": "IME-ENFORCEMENT-SUCCESS", "category": "currentPhase", - "pattern": "\\[Win32App\\]\\[ReportingManager\\] Execution state for app with id: {GUID} has been updated\\. Report delta: \\{\"\"EnforcementState\"\":\\{\"\"OldValue\"\":\"\"InProgressDownloadCompleted\"\",\"\"NewValue\"\":\"\"Success\"\"", + "pattern": "\\[Win32App\\]\\[ReportingManager\\] Execution state for app with id: {GUID} has been updated\\. Report delta: \\{\"\"EnforcementState\"\":\\{\"\"OldValue\"\":(?:\"\"\\w+\"\"|null),\"\"NewValue\"\":\"\"Success\"\"", "action": "updateStateInstalled", - "description": "Detects when an app's enforcement state transitions from InProgressDownloadCompleted to Success.", + "description": "Detects when an app's enforcement state transitions to Success in an Execution state report delta. OldValue is deliberately unpinned: besides InProgressDownloadCompleted it can be Error (retry succeeding in a later check-in), InProgressPendingReboot (post-reboot completion) or null (first write) — the previously pinned InProgressDownloadCompleted missed those legitimate success paths (IME 1.97 audit 2026-08-17).", "enabled": true } diff --git a/rules/ime-log-patterns/IME-ERROR-REPORT.json b/rules/ime-log-patterns/IME-ERROR-REPORT.json index 8b1820e8..f09034e8 100644 --- a/rules/ime-log-patterns/IME-ERROR-REPORT.json +++ b/rules/ime-log-patterns/IME-ERROR-REPORT.json @@ -2,9 +2,9 @@ "$schema": "../schema/ime-log-pattern.schema.json", "patternId": "IME-ERROR-REPORT", "category": "currentPhase", - "pattern": "\\[Win32App\\]\\[ReportingManager\\] Execution state for app with id: {GUID} has been updated\\. Report delta: \\{\"\"EnforcementState\"\":\\{\"\"OldValue\"\":\"\"(?\\w+)\"\",\"\"NewValue\"\":\"\"(?\\w+)\"\"", + "pattern": "\\[Win32App\\]\\[ReportingManager\\] Execution state for app with id: {GUID} has been updated\\. Report delta: \\{\"\"EnforcementState\"\":\\{\"\"OldValue\"\":(?:\"\"(?\\w+)\"\"|null),\"\"NewValue\"\":\"\"(?\\w+)\"\"", "action": "updateStateError", "parameters": { "checkTo": "true" }, - "description": "Captures enforcement state transitions via ReportingManager. Only triggers error when 'to' value indicates an error state.", + "description": "Captures enforcement state transitions via ReportingManager. Only triggers error when 'to' value indicates an error state. OldValue may be the unquoted JSON literal null on the first-ever write of a reporting state — transitions straight from the initial state (e.g. first write directly to an error state) would otherwise be invisible (IME 1.97 audit 2026-08-17).", "enabled": true } diff --git a/rules/ime-log-patterns/IME-ESP-APP-REGISTERED.json b/rules/ime-log-patterns/IME-ESP-APP-REGISTERED.json new file mode 100644 index 00000000..1b745104 --- /dev/null +++ b/rules/ime-log-patterns/IME-ESP-APP-REGISTERED.json @@ -0,0 +1,9 @@ +{ + "$schema": "../schema/ime-log-pattern.schema.json", + "patternId": "IME-ESP-APP-REGISTERED", + "category": "always", + "pattern": "\\[Win32App\\]\\[EspManager\\] In EspPhase: \\w+\\. App {GUID} has been registered.*?App name: (?.*?)$", + "action": "updateName", + "description": "Captures the ESP tracked-app registration line ('App has been registered[ for user ]. App name: ', EspManager.cs) as an app-name source. Primary replacement for the retired IME-UPDATE-NAME-1/2/3 whose emitters were removed with IME's old V1/V2 processing pipeline; also documents exactly which apps IME registered for ESP tracking. Category 'always' so names resolve even before the first ApplicationPoller EspPhase line is seen.", + "enabled": true +} diff --git a/rules/ime-log-patterns/IME-ESP-TRACK-STATUS.json b/rules/ime-log-patterns/IME-ESP-TRACK-STATUS.json index 18985ad0..891570f6 100644 --- a/rules/ime-log-patterns/IME-ESP-TRACK-STATUS.json +++ b/rules/ime-log-patterns/IME-ESP-TRACK-STATUS.json @@ -2,8 +2,8 @@ "$schema": "../schema/ime-log-pattern.schema.json", "patternId": "IME-ESP-TRACK-STATUS", "category": "currentPhase", - "pattern": "\\[Win32App\\]\\[EspManager\\] Updating ESP tracked install status from (?\\w+) to (?\\w+) for application {GUID}\\.", + "pattern": "\\[Win32App\\]\\[EspManager\\] Updating ESP tracked install status from (?\\w+) to (?\\w+) for application {GUID}", "action": "espTrackStatus", - "description": "Captures ESP tracked install status transitions (e.g., InProgress to Installed) for a specific app.", + "description": "Captures ESP tracked install status transitions (e.g., InProgress to Installed) for a specific app. No trailing anchor: IME 1.97 (Dec 2025) appends ' with name: .' after the GUID (EspManager.cs), which broke the previous '\\.' suffix. 'from' can be the literal string 'null' on first tracking.", "enabled": true } diff --git a/rules/ime-log-patterns/IME-EXITCODE-MAPPED-FAILED.json b/rules/ime-log-patterns/IME-EXITCODE-MAPPED-FAILED.json new file mode 100644 index 00000000..ddc93637 --- /dev/null +++ b/rules/ime-log-patterns/IME-EXITCODE-MAPPED-FAILED.json @@ -0,0 +1,10 @@ +{ + "$schema": "../schema/ime-log-pattern.schema.json", + "patternId": "IME-EXITCODE-MAPPED-FAILED", + "category": "currentPhase", + "pattern": "\\[Win32App\\] lpExitCode is defined as Failed$", + "action": "updateStateError", + "parameters": { "useCurrentApp": "true" }, + "description": "Marks the current app as failed when its exit code maps to Failed via the admin-defined return-code table ('[Win32App] lpExitCode is defined as ', Win32AppInstaller.cs). This is the NORMAL mapped-exit-code outcome; the previously matched 'Setting enforcementState as ... Error' line only fires on the rare no-mapping fallback path. The numeric exit code is captured separately by IME-EXITCODE, which precedes this line.", + "enabled": true +} diff --git a/rules/ime-log-patterns/IME-RESTART-STOP-PROCESSING.json b/rules/ime-log-patterns/IME-RESTART-STOP-PROCESSING.json new file mode 100644 index 00000000..425802a9 --- /dev/null +++ b/rules/ime-log-patterns/IME-RESTART-STOP-PROCESSING.json @@ -0,0 +1,10 @@ +{ + "$schema": "../schema/ime-log-pattern.schema.json", + "patternId": "IME-RESTART-STOP-PROCESSING", + "category": "currentPhase", + "pattern": "\\[Win32App\\]\\[V3Processor\\] A restart is required to continue processing apps\\. Stop processing\\.", + "action": "updateStatePostponed", + "parameters": { "useCurrentApp": "true" }, + "description": "Detects IME aborting app processing because an app requires a restart ('A restart is required to continue processing apps. Stop processing.', SideCarV3AppProcessor.cs). Postpones the current app: remaining apps do nothing until after the reboot, which previously looked like an unexplained stall mid-ESP.", + "enabled": true +} diff --git a/rules/ime-log-patterns/IME-SET-CURRENT-1.json b/rules/ime-log-patterns/IME-SET-CURRENT-1.json index d2d80e90..e2434b7c 100644 --- a/rules/ime-log-patterns/IME-SET-CURRENT-1.json +++ b/rules/ime-log-patterns/IME-SET-CURRENT-1.json @@ -4,6 +4,6 @@ "category": "always", "pattern": "\\[Win32App\\] ProcessAppWithDependencies starts for {GUID} with name", "action": "setCurrentApp", - "description": "Detects when IME begins processing an app with its dependency chain, setting it as the current app.", - "enabled": true + "description": "Detects when IME begins processing an app with its dependency chain, setting it as the current app. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-SET-CURRENT-2.json b/rules/ime-log-patterns/IME-SET-CURRENT-2.json index cf71b0a4..87701f8e 100644 --- a/rules/ime-log-patterns/IME-SET-CURRENT-2.json +++ b/rules/ime-log-patterns/IME-SET-CURRENT-2.json @@ -4,6 +4,6 @@ "category": "always", "pattern": "\\[Win32App\\] ExecManager: processing targeted app.*?\\bid\\W+{GUID}", "action": "setCurrentApp", - "description": "Detects when the IME ExecManager starts processing a targeted app, setting it as current.", - "enabled": true + "description": "Detects when the IME ExecManager starts processing a targeted app, setting it as current. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-SET-CURRENT-3.json b/rules/ime-log-patterns/IME-SET-CURRENT-3.json index fcf6a731..2e66608c 100644 --- a/rules/ime-log-patterns/IME-SET-CURRENT-3.json +++ b/rules/ime-log-patterns/IME-SET-CURRENT-3.json @@ -4,6 +4,6 @@ "category": "always", "pattern": "\\[Win32App\\] ===Step=== Start to Present app {GUID}", "action": "setCurrentApp", - "description": "Detects the start of app presentation step in IME, setting the app as current.", - "enabled": true + "description": "Detects the start of app presentation step in IME, setting the app as current. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-SKIP-APPLICABILITY-NOTMET.json b/rules/ime-log-patterns/IME-SKIP-APPLICABILITY-NOTMET.json index 5e4bf197..990a10ec 100644 --- a/rules/ime-log-patterns/IME-SKIP-APPLICABILITY-NOTMET.json +++ b/rules/ime-log-patterns/IME-SKIP-APPLICABILITY-NOTMET.json @@ -4,6 +4,6 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] (?=.*?\\bapplicability\\b)(?=.*?NotMet\\b).*?\\bapp\\W+{GUID}\\b", "action": "updateStateSkipped", - "description": "Detects when an app's applicability check returns NotMet (old log format with lookaheads).", - "enabled": true + "description": "Detects when an app's applicability check returns NotMet (old log format with lookaheads). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-SKIP-DEPENDENCY-DETECT.json b/rules/ime-log-patterns/IME-SKIP-DEPENDENCY-DETECT.json index 8c574dec..180873ff 100644 --- a/rules/ime-log-patterns/IME-SKIP-DEPENDENCY-DETECT.json +++ b/rules/ime-log-patterns/IME-SKIP-DEPENDENCY-DETECT.json @@ -4,6 +4,6 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] app\\W+{GUID}\\b.*?\\bis a dependency\\b.*?\\bDetect Only mode\\b.*?\\bfinished processing", "action": "updateStateSkipped", - "description": "Detects when a dependency app in Detect Only mode finishes processing (no install needed).", - "enabled": true + "description": "Detects when a dependency app in Detect Only mode finishes processing (no install needed). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-SKIP-DETECTED.json b/rules/ime-log-patterns/IME-SKIP-DETECTED.json index c00462e7..eaced1b4 100644 --- a/rules/ime-log-patterns/IME-SKIP-DETECTED.json +++ b/rules/ime-log-patterns/IME-SKIP-DETECTED.json @@ -4,6 +4,6 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] Detected app {GUID}.*?skip next step", "action": "updateStateSkipped", - "description": "Detects when an already-detected app is skipped for further processing steps (old log format).", - "enabled": true + "description": "Detects when an already-detected app is skipped for further processing steps (old log format). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-SKIP-UNINSTALL-NOTDETECTED-2.json b/rules/ime-log-patterns/IME-SKIP-UNINSTALL-NOTDETECTED-2.json index e759ed10..8e46b71a 100644 --- a/rules/ime-log-patterns/IME-SKIP-UNINSTALL-NOTDETECTED-2.json +++ b/rules/ime-log-patterns/IME-SKIP-UNINSTALL-NOTDETECTED-2.json @@ -4,6 +4,6 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] NOT detected app {GUID}.*?skip un-installation", "action": "updateStateSkipped", - "description": "Detects when an app is not detected and uninstall is skipped (alternate old log format).", - "enabled": true + "description": "Detects when an app is not detected and uninstall is skipped (alternate old log format). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-STOP-SIGNAL.json b/rules/ime-log-patterns/IME-STOP-SIGNAL.json new file mode 100644 index 00000000..ccf86b6b --- /dev/null +++ b/rules/ime-log-patterns/IME-STOP-SIGNAL.json @@ -0,0 +1,10 @@ +{ + "$schema": "../schema/ime-log-pattern.schema.json", + "patternId": "IME-STOP-SIGNAL", + "category": "currentPhase", + "pattern": "EMS Agent received stop signal", + "action": "updateStatePostponed", + "parameters": { "useCurrentApp": "true" }, + "description": "Detects an IME service stop ('EMS Agent received stop signal', EmsAgentService.OnStop) — fired on manual restarts and agent-updater restarts, unlike the OS-shutdown-only 'shutdown signal' line matched by IME-SHUTDOWN. Postpones the current app installation, mirroring IME-SHUTDOWN semantics.", + "enabled": true +} diff --git a/rules/ime-log-patterns/IME-UPDATE-NAME-1.json b/rules/ime-log-patterns/IME-UPDATE-NAME-1.json index db12f5dc..64d5f60f 100644 --- a/rules/ime-log-patterns/IME-UPDATE-NAME-1.json +++ b/rules/ime-log-patterns/IME-UPDATE-NAME-1.json @@ -4,6 +4,6 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] ExecManager: processing targeted app.*?name\\W+(?.*?)\\W+id\\W+{GUID}", "action": "updateName", - "description": "Captures the app name from ExecManager processing log (old format: name before id).", - "enabled": true + "description": "Captures the app name from ExecManager processing log (old format: name before id). DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-UPDATE-NAME-2.json b/rules/ime-log-patterns/IME-UPDATE-NAME-2.json index de8ddd2d..b707cf98 100644 --- a/rules/ime-log-patterns/IME-UPDATE-NAME-2.json +++ b/rules/ime-log-patterns/IME-UPDATE-NAME-2.json @@ -4,6 +4,6 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] ProcessAppWithDependencies starts for {GUID} with name (?.*?)$", "action": "updateName", - "description": "Captures the app name from ProcessAppWithDependencies log entry.", - "enabled": true + "description": "Captures the app name from ProcessAppWithDependencies log entry. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-UPDATE-NAME-3.json b/rules/ime-log-patterns/IME-UPDATE-NAME-3.json index b2c2be9c..6dce2c1c 100644 --- a/rules/ime-log-patterns/IME-UPDATE-NAME-3.json +++ b/rules/ime-log-patterns/IME-UPDATE-NAME-3.json @@ -4,6 +4,6 @@ "category": "currentPhase", "pattern": "\\[Win32App\\] Processing app \\(id={GUID}, name = (?.*?)\\)", "action": "updateName", - "description": "Captures the app name from the Processing app log entry.", - "enabled": true + "description": "Captures the app name from the Processing app log entry. DISABLED 2026-08-17: emitter no longer exists in current IME (1.97.107, Dec 2025) - the old V1/V2 app processing pipeline was removed and this line is not logged anymore (verified against decompiled source, see tasks/ime-v1-code-audit-2026-08-17.md). Kept for history.", + "enabled": false } diff --git a/rules/ime-log-patterns/IME-WINGET-ERROR.json b/rules/ime-log-patterns/IME-WINGET-ERROR.json new file mode 100644 index 00000000..18c6f93e --- /dev/null +++ b/rules/ime-log-patterns/IME-WINGET-ERROR.json @@ -0,0 +1,9 @@ +{ + "$schema": "../schema/ime-log-pattern.schema.json", + "patternId": "IME-WINGET-ERROR", + "category": "currentPhase", + "pattern": "\\[WinGetMessageProcessor\\] Processing Progress for app = {GUID}.*?- Operation Phase = Error", + "action": "updateStateError", + "description": "Marks a WinGet (new Store) app as failed when its operation progress reports phase Error (WinGetOperationInstallPhase: Downloading/Installing/Queued/Finished/Error). Before this pattern only the Installing phase was matched, so WinGet failures never surfaced as app errors (IME 1.97 audit 2026-08-17).", + "enabled": true +} diff --git a/src/Backend/AutopilotMonitor.Functions/Services/ImeLogPatternService.cs b/src/Backend/AutopilotMonitor.Functions/Services/ImeLogPatternService.cs index 636710a5..d30e61cf 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/ImeLogPatternService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/ImeLogPatternService.cs @@ -199,7 +199,9 @@ namespace AutopilotMonitor.Functions.Services if (existingLookup.TryGetValue(pattern.PatternId, out var existing)) { if (existing.Pattern != pattern.Pattern || existing.Action != pattern.Action - || existing.Category != pattern.Category || existing.Description != pattern.Description) + || existing.Category != pattern.Category || existing.Description != pattern.Description + || existing.Enabled != pattern.Enabled + || !ParametersEqual(existing.Parameters, pattern.Parameters)) { await _ruleRepo.StoreImeLogPatternAsync(pattern, "global"); updated++; @@ -220,5 +222,18 @@ namespace AutopilotMonitor.Functions.Services _seeded = true; } + + private static bool ParametersEqual(Dictionary? a, Dictionary? b) + { + if ((a?.Count ?? 0) != (b?.Count ?? 0)) return false; + if (a == null || b == null) return true; + + foreach (var kv in a) + { + if (!b.TryGetValue(kv.Key, out var value) || value != kv.Value) return false; + } + + return true; + } } }