Objective: Do not fix anything. Do not edit code. Do not create a PR. Only detect cleanup opportunities and create 3 separate issues for the top 3 highest-value cleanup candidates: 1 issue per cleanup opportunity. Cleanup pattern search (must perform explicitly): - Excessive defensive checks inside trusted/internal code paths - Redundant error handling (`catch`/`except` that only rethrow, broad blanket handlers without clear need) - Duplicate code / duplicate conditional fragments - Deeply nested conditionals instead of guard clauses / early returns - Unnecessary `else` after an early return path - Dead, unreachable, obsolete, or otherwise unused code - Speculative abstractions, wrappers, helpers, or indirection with no demonstrated need - Overly long functions or long parameter lists that indicate avoidable complexity - Compatibility residue: deprecated paths, migration code, transitional aliases, backward-compat branches, or old data flows still kept after the new path is primary - Schema mirroring / data clumps: repeated request fields, validators, error strings, or payload reshaping across multiple components - Wrapper accretion / middle-men: helper layers that mostly forward, normalize, or repackage data without materially reducing complexity - Test clone farms: many near-identical tests covering permutations that could be table-driven or shared through fixtures/helpers - Comment-heavy scaffolding: comments/docstrings that mostly restate obvious code or preserve implementation narration rather than intent - Contract/integration drift: stale or duplicated contracts, partial migrations, or code that reshapes one contract into another only to preserve legacy structure - Complexity-heavy branching that can be removed or simplified Research requirements: - Research in the codebase first and gather concrete file-level evidence. - Search open and closed issues for possible duplicates before creating new issues. - Use current online research to sharpen pattern recognition when useful, especially for distinguishing classic cleanup from common AI-generated code patterns. - Prefer primary or authoritative sources when citing external guidance. Selection rule: - Rank candidates by estimated net LOC removal first, then safety/risk, then implementation feasibility. - Choose exactly 3 highest-impact candidates. - Do not merge unrelated cleanup opportunities into one issue. - Prefer bounded, actionable cleanup work over broad rewrites. Issue creation requirements: - Create 3 issues, one for each selected cleanup opportunity, unless a matching open issue already exists. - If a matching open issue already exists, add a comment with new evidence instead of creating a duplicate issue. - If only closed duplicates exist, do not create a new issue for that candidate; move to the next best candidate. - Use a file-backed markdown body for each new issue (not inline multiline text). - After creation, read back each created issue body and confirm formatting is correct (no literal `\n` escapes). Issue body template: - Context - Cleanup Pattern(s) Found - Evidence (files/paths, concise examples) - Proposed Cleanup - Estimated LOC Reduction - Why This Is In The Top 3 - Impact/Risk - Acceptance Criteria - Out of Scope Output to user: - For each of the 3 final issues: - Issue number and URL - Estimated LOC reduction - Provide the final ranking of the 3 selected opportunities from highest to lowest impact - Briefly mention the core pattern category for each selected issue - Do not list additional runner-up opportunities beyond these 3 Important constraints: - Do not implement fixes. - Do not modify repository files. - Do not open a PR. - Keep each issue narrowly scoped so it can be implemented safely in a follow-up cleanup change.
Start working on this gitea issue. Scrutinize the issue first. It might be a false alarm, outdated, missing important codebase context, or there may be a deeper underlying issue. Do the following phases using sub agents. - check whether the current open gitea issue has related issues using a sub agent - code exploration phase by a sub agent - internet research phase by a sub agent - planning phase by a sub agent Try to split out and delegate as much work as possible to sub agents. Make sure to update the issue with progress thus far. Keep updating the issue while working on it, not after, but during. Follow the branch, commit, push, PR, and verification rules from AGENTS.md. Before posting a PR, run an internal review using the `code-reviewer` agent against the branch diff and current changes. Treat that review as findings-first internal feedback. Fix all actionable review findings, re-verify the changes, and repeat the review if needed until the result is clean or only has clearly documented residual risks. Only open the PR after: - the implementation is complete - verification has passed - the `code-reviewer` review feedback has been addressed - the branch is ready for PR checks After opening the PR: - check PR checks - keep fixing and verifying until all PR checks are green If the issue is already solved, close the issue with comments. If related open gitea issues are found, comment on those, or close them if this work solves them as well. Start by reading the gitea issue and creating a new feature branch. You will focus on gitea issue ###
Tasks are tracked as markdown files in `docs/backlog/` with the naming convention `<index>_<task-slug>.md`: - `docs/backlog/open/` - Open tasks awaiting work - `docs/backlog/pending-review/` - Completed tasks awaiting review - `docs/backlog/done/` - Completed and reviewed tasks Move task files between directories as their status changes.
Use `docs/todo.md` to track work: `- [ ]` open, `- [~]` in progress, `- [x]` done.
ALWAYS keep track of troubleshooting progress in a troubleshooting case file in docs/troubleshooting/<DATE>_<SUBJECT>.md. While troubleshooting, append the steps taken to the troubleshooting case file. For example, `echo 'pinged 1.1.1.1, ping is ok' >> docs/troubleshooting/<DATE>_<SUBJECT>.md`
Logs always have to be written to logs/ in the project root
Commit in small increments, but no meaningless micro-commits. "WIP"/vague messages forbidden. Checkpoints must stay local or on scratch branch until green and reviewable. Before PR/merge: rebase/squash to atomic, green, conventional, documentation-grade commits.
Each commit must contain one logical change only. Do not mix unrelated changes, refactors with behavior changes, or formatting with functional changes. Each commit must be independently checkable and in working state.
Required Commit Body Sections for non-trivial commits: - Context: What problem/need triggered this - Change: High-level summary of what changed - Rationale: Why this approach, trade-offs, alternatives rejected - Impact/Risk: Behavior changes, migrations, compatibility, performance - Tests: Exact command(s) run (e.g., `Tests: cd src && uv run pytest tests/`)
Subject: imperative mood ("add", "fix"), ~50 chars, no period. Body: blank line after subject, explain what/why (not how), wrap ~72 chars. Body required for non-trivial changes.
Use Conventional Commits format: `type(scope?): subject` Allowed types: `feat, fix, docs, refactor, test, perf, build, ci, chore, style, revert` Breaking changes: use `type(scope)!: subject` OR `BREAKING CHANGE: ...` footer with migration steps.
Link issues via footer: `Fixes #123` or `Refs #123`. If no issue exists, body must clearly state the why.
MUST NOT add author/co-author attribution trailers for AI. Forbidden: `Co-authored-by:`, `Generated-by:`, `AI-Generated-by:`, `Assisted-by:`, `Model:`. Allowed trailers: `Fixes #...`, `Refs #...`, `BREAKING CHANGE:...`, `Signed-off-by:` (human only).
MUST run tests before every commit (minimum: fast suite or targeted tests for changed area). EACH COMMIT MUST KEEP REPO GREEN: build passes, tests pass. Failing commits are forbidden on shared branches. Intermediate failing steps must stay local and be squashed before PR/merge.
Intune applications must be packaged using the IntuneWinAppUtil executable to create `.intunewin` files for deployment. Create a `package.cmd` script to automate the packaging process: ```batch @echo off REM Check if IntuneWinAppUtil is available in PATH where IntuneWinAppUtil >nul 2>&1 if %ERRORLEVEL% NEQ 0 ( REM Install IntuneWinAppUtil using winget echo [INFO] Installing IntuneWinAppUtil via winget... winget install Microsoft.Win32ContentPrepTool --force REM PATH is modified by installer, requires terminal restart echo [WARNING] Restart your terminal and run this script again exit /b 0 ) REM Package the in/ folder into an .intunewin file in out/ folder IntuneWinAppUtil -c in -s install.ps1 -o out -q ``` This script: - Checks if IntuneWinAppUtil is available - Installs it via winget if missing - Packages the `in/` folder contents with `install.ps1` as the setup file - Outputs the `.intunewin` file to the `out/` folder
Use consistent Intune logging: write to the IME log path and to a custom Windows Event Log for the app. Create the log folder and event source before writing; build the log path from variables so installs and uninstalls stay separated. ```PowerShell $EventLogName = "$ORGANISATION" $EventSource = "$APPLICATION" $LogPath = "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\AppName_$currentDate.log" $LogDir = Split-Path -Path $LogPath -Parent # Create log directory if needed if (-not (Test-Path -Path $LogDir)) { New-Item -Path $LogDir -ItemType Directory -Force | Out-Null } # Create custom Windows Event Log if (-not [System.Diagnostics.EventLog]::SourceExists($EventSource)) { New-EventLog -LogName $EventLogName -Source $EventSource } function Write-Log { param( [string]$Message, [string]$Level = "Information" ) $LogMessage = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - $Message" Write-Output $LogMessage Add-Content -Path $LogPath -Value $LogMessage -Force Write-EventLog -LogName $EventLogName -Source $EventSource -EntryType $Level -EventId 1000 -Message $Message } ```
Standard PowerShell command format for Intune Win32 app install and uninstall commands. Use ExecutionPolicy Bypass and NoProfile for reliability. **Install command:** ``` PowerShell.exe -ExecutionPolicy Bypass -NoProfile -File "application-install.ps1" ``` **Uninstall command:** ``` PowerShell.exe -ExecutionPolicy Bypass -NoProfile -File "application-uninstall.ps1" ``` **With parameters (e.g., for Winget template):** ``` PowerShell.exe -ExecutionPolicy Bypass -NoProfile -File "winget-setup.ps1" -action install -wingetpkg "7zip.7zip" ```
Execute code in user context from system context. Uses scheduled task with Authenticated Users group to run script blocks as the currently logged-on user. Self-cleaning after execution. ```PowerShell function Invoke-AsCurrentLoggedOnUser { param ( [Parameter(Mandatory = $true)] [scriptblock]$ScriptBlock, [string]$taskName = "RunOnce_$(Get-Random)" ) try { # Create script content with self-cleanup $scriptContent = "$($ScriptBlock.ToString()); Unregister-ScheduledTask -TaskName '$taskName' -Confirm:`$false" # Create and register scheduled task $registerTaskParams = @{ TaskName = $taskName Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -WindowStyle Hidden -Command `"$scriptContent`"" Trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddSeconds(1) Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries ` -RunOnlyIfNetworkAvailable -StartWhenAvailable ` -ExecutionTimeLimit (New-TimeSpan -Minutes 5) ` -MultipleInstances IgnoreNew Principal = New-ScheduledTaskPrincipal -GroupId "Authenticated Users" -RunLevel Highest Force = $true } Register-ScheduledTask @registerTaskParams # Modify task permissions to allow Authenticated Users to run and delete it $Scheduler = New-Object -ComObject "Schedule.Service" $Scheduler.Connect() $Task = $Scheduler.GetFolder('\').GetTask($taskName) $SecurityDescriptor = $Task.GetSecurityDescriptor(0xF) + '(A;;FA;;;AU)' $Task.SetSecurityDescriptor($SecurityDescriptor, 0) Write-Output "Task created and permissions updated successfully" } catch { Write-Error "Failed to run as logged on user: $_" Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue } finally { if ($Scheduler) { [void][Runtime.InteropServices.Marshal]::ReleaseComObject($Scheduler) } } } # Usage example: Invoke-AsCurrentLoggedOnUser -ScriptBlock { Write-Output "Running as: $(whoami)" # Your user-context code here } ```
Recommended folder structure for Intune Win32 app packages. Separates input files, output packages, and documentation for easier maintenance and updates. ``` π Application-Name βββ π input β βββ π application-install.ps1 β βββ π application-uninstall.ps1 β βββ π application-detect.ps1 β βββ π application-setup.exe βββ π output β βββ π application-install.intunewin (generated) βββ π information β βββ π application-logo.png β βββ π application-documentation.pdf βββ π package.cmd ``` **Purpose:** - `input/` - All source files to be packaged (scripts, installers) - `output/` - Generated .intunewin files - `information/` - Logo, documentation, notes - `package.cmd` - Automation script to create .intunewin package
Test Intune scripts in system context using PSExec. Intune executes Win32 packages in system context and 32-bit mode, so testing as admin is not representative. **Launch 32-bit PowerShell in system context:** ```powershell psexec.exe -s -i "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe" ``` **Verify you're in system context:** ```powershell whoami # Should output: nt authority\system ``` **Test your script:** ```powershell cd "C:\path\to\your\scripts" .\application-install.ps1 ``` Logs will be written to `C:\ProgramData\Microsoft\IntuneManagementExtension\Logs` when using standard logging patterns.
The installation of an application has to be detectable by a key in the registry. Intune could detect the presence of an application by checking a registry key. If the installation of an application is succesful, this would be an example of setting a registry key: ```PowerShell # Define registry path for setting the registry detection key $regPath = "HKLM:\Software\$organisation\$applicationName" if ($($setup.ExitCode) -eq 0) { if (-not (Test-Path -Path $regPath)) { New-Item -Path $regPath -Force } Set-ItemProperty -Path $regPath -Name "InstallationDate" -Value $currentDateTime -Force } ```
Intune installations have to be done silently, and unattended. Users will not be able to see any popups if a setup is running in SYSTEM context. By default, setups are installed using SYSTEM context.
Detect Intuneβs 32-bit host on 64-bit Windows, then relaunch through Sysnative to avoid WOW64 redirection. Do this at the top of install/uninstall scripts so all file system and registry calls run in native 64-bit PowerShell. ```PowerShell # Only relaunch if we are a 32-bit process on a 64-bit OS (IME default) if ([Environment]::Is64BitOperatingSystem -and -not [Environment]::Is64BitProcess) { $nativePwsh = Join-Path $env:WINDIR 'Sysnative\WindowsPowerShell\v1.0\powershell.exe' if (-not (Test-Path $nativePwsh)) { Throw "Sysnative PowerShell not found at $nativePwsh" } # Re-run the current script with original args inside 64-bit PowerShell $argsList = @('-File', "`"$PSCommandPath`"") + $args $proc = Start-Process -FilePath $nativePwsh -ArgumentList $argsList -Wait -PassThru -NoNewWindow exit $proc.ExitCode } # Already running in 64-bit β continue script here ```
When relaunching from the 32-bit IME host, the parent process must wait for the 64-bit child to finish and pass the exit code back to Intune for accurate detection. ```PowerShell $proc = Start-Process -FilePath $nativePwsh -ArgumentList $argsList -Wait -PassThru exit $proc.ExitCode ```
Locate the latest winget.exe binary on the system. Required when running in system context where winget isn't in PATH. Sorts by LastWriteTime to get the newest version. ```PowerShell # Find latest winget.exe in WindowsApps (system context requires explicit path) $wingetPath = "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_8wekyb3d8bbwe" $winget = (Get-ChildItem -Path $wingetPath -Filter "winget.exe" -Recurse | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName Write-Output "Using winget at: $winget" ```
E2E test pattern for script testing: Create isolated temp directory with test data and override paths using environment variables. Example: ```python os.environ["PROJECT_ROOT"] = temp_dir # Override paths for isolation subprocess.run(["uv", "run", "python", script_path], env=env) ``` This allows testing scripts in isolation without affecting the main project.
Maximize information density, while making text effortless to read
Never use bold formatting in markdown text, unless the info is absolutely critical
NEVER use emojis anywhere, but rather use [ERROR], [WARNING], [INFO] or something else in brackets
Keep markdown and text headings unnumbered
Select snippets from the sidebar to build your context window.