Skip to content

fix(windows): hold mode with RetroBat and relative config paths#674

Merged
wizzomafizzo merged 4 commits intomainfrom
fix/642-hold-mode-relative-paths
Apr 15, 2026
Merged

fix(windows): hold mode with RetroBat and relative config paths#674
wizzomafizzo merged 4 commits intomainfrom
fix/642-hold-mode-relative-paths

Conversation

@wizzomafizzo
Copy link
Copy Markdown
Member

@wizzomafizzo wizzomafizzo commented Apr 15, 2026

Summary

  • Fix hold mode not stopping RetroBat games on Windows by adding lastLauncher tracking to StopActiveLauncher, matching the MiSTer platform pattern
  • Resolve relative media_dir, index_root, and custom launcher media_dirs config paths relative to the executable directory instead of the unpredictable process CWD
  • Set cmd.Dir for custom launcher execute commands so relative paths resolve relative to the executable
  • Extract ExeDir and ResolveRelativePath into pkg/helpers/pathutil to avoid circular imports between config and helpers

Closes #642

Summary by CodeRabbit

  • Bug Fixes

    • Relative media and index paths are now resolved against the application's executable, preventing broken/misplaced launcher folders.
    • Launcher execution now runs with the correct working directory for more reliable launches.
  • New Features

    • Custom launchers can specify custom termination logic so stop/kill behavior follows the launcher's preference.

…d mode

RetroBat launchers use the EmulationStation HTTP API instead of direct
process tracking, returning nil for the process handle. When hold mode
triggered StopActiveLauncher, only the nil trackedProcess was checked
and the game kept running.

Add lastLauncher tracking to the Windows platform (matching the MiSTer
pattern) so StopActiveLauncher calls the launcher's custom Kill function
when one is defined.

Closes #642 (hold mode)
…rectory

Resolve relative paths in media_dir, index_root, and custom launcher
media_dirs relative to the executable directory instead of the process
CWD. Also set cmd.Dir for custom launcher execute commands so relative
paths in commands resolve predictably.

Extract path resolution into pkg/helpers/pathutil to avoid circular
imports between config and helpers.

Closes #642 (relative paths)
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 15, 2026

📝 Walkthrough

Walkthrough

Adds path resolution utilities and applies them to launcher-related configuration and helpers to resolve relative paths against the executable directory. Separately, Windows platform launcher shutdown now records the last-used launcher and invokes a custom Kill callback when present, falling back to terminating the tracked process.

Changes

Cohort / File(s) Summary
New Path Utilities
pkg/helpers/pathutil/pathutil.go, pkg/helpers/pathutil/pathutil_test.go
Adds ExeDir() and ResolveRelativePath() to compute executable directory and resolve relative paths against it.
Path helper wrappers & tests
pkg/helpers/paths.go, pkg/helpers/paths_test.go
Delegates ExeDir() to pathutil and exposes ResolveRelativePath(); adds tests validating resolution behavior.
Config: launcher path normalization
pkg/config/configlaunchers.go, pkg/config/configlaunchers_test.go
DefaultMediaDir() and IndexRoots() now return resolved paths (using ResolveRelativePath) for MediaDir and IndexRoot entries; tests added/updated to assert resolved ordering.
Custom launcher parsing & exec behavior
pkg/helpers/launchers.go, pkg/helpers/launchers_test.go
ParseCustomLaunchers() resolves each MediaDirs entry before assigning to platforms.Launcher.Folders and logging; launcher exec.Command now sets cmd.Dir = ExeDir(); tests updated accordingly.
Windows platform launcher shutdown
pkg/platforms/windows/platform.go, pkg/platforms/windows/platform_test.go
Adds lastLauncher and setLastLauncher(); StopActiveLauncher() invokes lastLauncher.Kill when present (clearing lastLauncher and unlocking before call), otherwise falls back to killing the tracked process; tests cover custom-kill and fallback scenarios.
CI task adjustments
scripts/tasks/cross-lint.yml
Removes linux cross-lint task; changes Windows and macOS lint tasks to run golangci-lint --fix --timeout=5m; updates all task description.

Sequence Diagram(s)

sequenceDiagram
  participant Platform
  participant LastLauncher
  participant CustomKill
  participant OSProcess

  Note over Platform,LastLauncher: StopActiveLauncher invoked
  Platform->>LastLauncher: check lastLauncher
  alt lastLauncher.Kill exists
    Platform->>LastLauncher: clear lastLauncher
    Platform->>CustomKill: invoke Kill(callback) (unlocked)
    CustomKill-->>Platform: return (may be error)
    Platform->>Platform: set trackedProcess = nil
  else no custom Kill
    Platform->>OSProcess: if trackedProcess != nil -> kill process
    OSProcess-->>Platform: process terminated
    Platform->>Platform: clear trackedProcess
  end
  Platform-->>Platform: return success
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰
Paths hop home beside the exe,
Relative roots find where to be,
Launchers set their working ground,
A last-launch note is safely found,
Kill callbacks whisper, "Stop," and free. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: Windows hold mode support with RetroBat and relative config path resolution are the primary objectives addressed in this PR.
Linked Issues check ✅ Passed The PR comprehensively addresses both requirements from issue #642: implements lastLauncher tracking for hold mode with RetroBat, and resolves relative config paths (media_dir, index_root, execute) relative to the executable directory.
Out of Scope Changes check ✅ Passed The PR includes changes to cross-lint tasks with --fix flag and Linux task removal, which are tangential tooling improvements but support the main objectives and don't represent scope creep.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/642-hold-mode-relative-paths

Comment @coderabbitai help to get the list of available commands and usage tips.

@sentry
Copy link
Copy Markdown

sentry bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 77.77778% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/helpers/pathutil/pathutil.go 66.66% 2 Missing and 2 partials ⚠️
pkg/config/configlaunchers.go 83.33% 1 Missing ⚠️
pkg/helpers/launchers.go 83.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
pkg/helpers/launchers_test.go (1)

249-275: Add a regression case for relative Execute paths too.

This update only checks that MediaDirs are resolved against ExeDir(). The PR also changes custom launcher execution to run with cmd.Dir = ExeDir(), and that behavior is still untested here. A case with non-empty Execute and a relative path would make the Windows path fix much safer.

As per coding guidelines, **/*.go: Write tests for all new code — see TESTING.md and pkg/testing/README.md.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/helpers/launchers_test.go` around lines 249 - 275, Add a new regression
test alongside TestParseCustomLaunchers_EmptyExecuteLeavesLaunchNil that
supplies a LaunchersCustom with a non-empty relative Execute (e.g.,
"tools/runner.exe") and relative MediaDirs, call ParseCustomLaunchers, then
assert that the resulting launcher has the Execute path resolved against
ExeDir() and that the created launch function will run with working directory
set to ExeDir() (i.e., exercise l.Launch to capture the command's Dir or
otherwise inspect the parsed command.Dir if ParseCustomLaunchers returns it);
use the same mocks (mocks.NewMockPlatform / mockPlatform.ID) and reference
ParseCustomLaunchers, LaunchersCustom, Execute and ExeDir() in the assertions to
ensure the relative Execute behavior is covered.
pkg/helpers/pathutil/pathutil.go (1)

32-50: Propagate executable path lookup failure instead of silently degrading to CWD behavior.

Line 35 and Line 48 silently fall back to "" / unchanged relative paths. Downstream, this can make command execution and config-path behavior CWD-dependent again (for example where cmd.Dir = ExeDir() is used). Consider returning an error (or a (string, bool) success flag) so callers can fail fast or log and explicitly choose fallback behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/helpers/pathutil/pathutil.go` around lines 32 - 50, Change ExeDir and
ResolveRelativePath to propagate executable lookup failures instead of returning
empty/unchanged values: modify ExeDir to return (string, error) and return the
os.Executable error when os.Executable() fails, and modify ResolveRelativePath
to return (string, error) and call the new ExeDir, returning an error if ExeDir
fails; keep the existing behavior of returning the input path unchanged only
when it is absolute or empty but return nil error in that case, and update all
callers to handle the new (string, error) signature (or convert the error to an
explicit fallback decision where appropriate).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/config/configlaunchers_test.go`:
- Around line 689-699: The test uses a hardcoded "/absolute/path" which is not
recognized as absolute on Windows, causing ResolveRelativePath()/IndexRoots()
assertions to fail; update the fixture to generate a real OS-appropriate
absolute path (e.g., use t.TempDir() or filepath.Abs on a created temp dir) and
replace the hardcoded string in the test so roots[1] compares against that
generated abs path (keep assertions referencing IndexRoots(),
ResolveRelativePath(), and ExeDir() behavior unchanged).

In `@pkg/helpers/paths_test.go`:
- Around line 878-881: The test case uses a Unix-only literal "/usr/share/games"
so filepath.IsAbs returns false on Windows; update the test to create a runtime
absolute path via t.TempDir() (or os.MkdirTemp) and use that value for both the
path and expected fields so ResolveRelativePath sees an absolute path
cross-platform; locate the test case for ResolveRelativePath and replace the
hardcoded path/expected with a call to t.TempDir() (or a temp directory
variable) to ensure the assertion is platform independent.

In `@pkg/helpers/pathutil/pathutil_test.go`:
- Around line 33-35: The tests currently skip when ExeDir() returns empty
instead of exercising the fallback logic; add a deterministic seam so you can
simulate os.Executable failing and assert the fallback behavior. Modify the test
for ExeDir (in pathutil_test.go) to inject or override the function ExeDir uses
to obtain the executable path (e.g., introduce a package-level variable or
constructor that points to os.Executable) so the test can replace it with a stub
that returns an error/empty string, then assert the fallback path is
returned/used instead of calling t.Skip; apply the same pattern to the other
skipped case to explicitly validate the fallback branch.
- Around line 48-50: Replace the hardcoded Unix absolute path in the table test
case named "absolute path unchanged" with a platform-native absolute directory
from t.TempDir(); i.e., in the test that asserts filepath.IsAbs behavior (look
for the table entry with name "absolute path unchanged" and code that relies on
filepath.IsAbs()), set path := t.TempDir() (or assign expected := t.TempDir()
and use that value for both path and expected) so the test uses an OS-native
absolute path on Windows and Unix.

In `@pkg/platforms/windows/platform.go`:
- Around line 193-209: The customKill branch currently unlocks processMu without
clearing launcher state, so stale lastLauncher/trackedProcess can be invoked
again; inside the StopActiveLauncher flow (the code using p.lastLauncher,
p.trackedProcess and p.processMu), set p.lastLauncher = nil and p.trackedProcess
= nil while still holding p.processMu (and any other stop-state like
setActiveMedia(nil) if relevant), then unlock and call
customKill(&config.Instance{}); this ensures the stop is idempotent and no stale
Kill callback is invoked on subsequent calls.

---

Nitpick comments:
In `@pkg/helpers/launchers_test.go`:
- Around line 249-275: Add a new regression test alongside
TestParseCustomLaunchers_EmptyExecuteLeavesLaunchNil that supplies a
LaunchersCustom with a non-empty relative Execute (e.g., "tools/runner.exe") and
relative MediaDirs, call ParseCustomLaunchers, then assert that the resulting
launcher has the Execute path resolved against ExeDir() and that the created
launch function will run with working directory set to ExeDir() (i.e., exercise
l.Launch to capture the command's Dir or otherwise inspect the parsed
command.Dir if ParseCustomLaunchers returns it); use the same mocks
(mocks.NewMockPlatform / mockPlatform.ID) and reference ParseCustomLaunchers,
LaunchersCustom, Execute and ExeDir() in the assertions to ensure the relative
Execute behavior is covered.

In `@pkg/helpers/pathutil/pathutil.go`:
- Around line 32-50: Change ExeDir and ResolveRelativePath to propagate
executable lookup failures instead of returning empty/unchanged values: modify
ExeDir to return (string, error) and return the os.Executable error when
os.Executable() fails, and modify ResolveRelativePath to return (string, error)
and call the new ExeDir, returning an error if ExeDir fails; keep the existing
behavior of returning the input path unchanged only when it is absolute or empty
but return nil error in that case, and update all callers to handle the new
(string, error) signature (or convert the error to an explicit fallback decision
where appropriate).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 254987de-2443-4500-90c2-c3031eba4a6f

📥 Commits

Reviewing files that changed from the base of the PR and between 42c1297 and dcefa56.

📒 Files selected for processing (10)
  • pkg/config/configlaunchers.go
  • pkg/config/configlaunchers_test.go
  • pkg/helpers/launchers.go
  • pkg/helpers/launchers_test.go
  • pkg/helpers/paths.go
  • pkg/helpers/paths_test.go
  • pkg/helpers/pathutil/pathutil.go
  • pkg/helpers/pathutil/pathutil_test.go
  • pkg/platforms/windows/platform.go
  • pkg/platforms/windows/platform_test.go

Comment thread pkg/config/configlaunchers_test.go
Comment thread pkg/helpers/paths_test.go
Comment on lines +878 to +881
name: "absolute path unchanged",
path: "/usr/share/games",
expected: "/usr/share/games",
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and examine the test file
fd -t f "paths_test.go" --exec head -n 910 {} \;

Repository: ZaparooProject/zaparoo-core

Length of output: 22206


🏁 Script executed:

# Get the test file content around lines 878-881
fd -t f "paths_test.go" -x cat -n {} | sed -n '850,910p'

Repository: ZaparooProject/zaparoo-core

Length of output: 1711


🏁 Script executed:

# Find the ResolveRelativePath implementation
fd -t f "paths.go" pkg/helpers/ -x cat -n {}

Repository: ZaparooProject/zaparoo-core

Length of output: 22071


🏁 Script executed:

# Quick verification of filepath.IsAbs behavior on Unix-like paths
python3 << 'EOF'
import os
import sys

# Simulate what filepath.IsAbs does in Go
# On Windows, only paths starting with drive letters or \\ are absolute
# On Unix, paths starting with / are absolute

test_path = "/usr/share/games"

# Simulate Unix behavior
unix_is_abs = test_path.startswith("/")
print(f"Unix filepath.IsAbs('{test_path}'): {unix_is_abs}")

# Simulate Windows behavior  
windows_is_abs = (len(test_path) > 1 and test_path[1] == ':') or test_path.startswith("\\\\")
print(f"Windows filepath.IsAbs('{test_path}'): {windows_is_abs}")

print(f"\nConclusion: Path '{test_path}' is portable-unsafe - different IsAbs() result on Windows vs Unix")
EOF

Repository: ZaparooProject/zaparoo-core

Length of output: 268


Use a runtime absolute path instead of a Unix-specific literal.

"/usr/share/games" is only guaranteed absolute on Unix. On Windows, filepath.IsAbs("/usr/share/games") returns false, so ResolveRelativePath treats it as relative and prepends ExeDir(), causing the test to fail. Use t.TempDir() to generate a platform-specific absolute path for consistent cross-platform test behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/helpers/paths_test.go` around lines 878 - 881, The test case uses a
Unix-only literal "/usr/share/games" so filepath.IsAbs returns false on Windows;
update the test to create a runtime absolute path via t.TempDir() (or
os.MkdirTemp) and use that value for both the path and expected fields so
ResolveRelativePath sees an absolute path cross-platform; locate the test case
for ResolveRelativePath and replace the hardcoded path/expected with a call to
t.TempDir() (or a temp directory variable) to ensure the assertion is platform
independent.

Comment on lines +33 to +35
if exeDir == "" {
t.Skip("ExeDir() returned empty, cannot test relative path resolution")
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fallback branches are skipped rather than validated.

Line 33 and Line 82 skip when ExeDir() is empty, but the new fallback behavior for that condition is part of the new production logic and remains unverified. Please add a deterministic test seam so os.Executable failure / empty ExeDir paths are explicitly asserted.

As per coding guidelines "Write tests for all new code — see TESTING.md and pkg/testing/README.md".

Also applies to: 82-84

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/helpers/pathutil/pathutil_test.go` around lines 33 - 35, The tests
currently skip when ExeDir() returns empty instead of exercising the fallback
logic; add a deterministic seam so you can simulate os.Executable failing and
assert the fallback behavior. Modify the test for ExeDir (in pathutil_test.go)
to inject or override the function ExeDir uses to obtain the executable path
(e.g., introduce a package-level variable or constructor that points to
os.Executable) so the test can replace it with a stub that returns an
error/empty string, then assert the fallback path is returned/used instead of
calling t.Skip; apply the same pattern to the other skipped case to explicitly
validate the fallback branch.

Comment thread pkg/helpers/pathutil/pathutil_test.go Outdated
Comment thread pkg/platforms/windows/platform.go
Fix fieldalignment in Windows Platform struct, use CommandContext in
test, and add --fix to all cross-lint task definitions so auto-fixable
issues are resolved in-place.
Use platform-native absolute paths in tests instead of hardcoded Unix
paths. Clear lastLauncher in StopActiveLauncher for idempotency. Remove
Linux target from cross-lint (native lint already covers it, zig cc
can't resolve system C deps like GTK/X11/pcsclite).
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/platforms/windows/platform.go`:
- Around line 193-200: The code calls the launcher Kill function with an empty
config instance (customKill(&config.Instance{})) which violates the interface;
update the Platform to store the active runtime config (e.g., add a field like
config *config.Instance on the Platform struct when created/initialized) and
pass that stored config into p.lastLauncher.Kill instead of a newly allocated
empty struct. Locate references to p.lastLauncher.Kill / customKill and replace
the empty-instance call with customKill(p.config) (ensuring p.config is set
where Platform is constructed and protected by p.processMu as needed), keeping
the existing trackedProcess niling and unlocking behavior intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8c9d5f3d-6161-4e62-b24e-e43c7b770e30

📥 Commits

Reviewing files that changed from the base of the PR and between dcefa56 and 20c7e77.

📒 Files selected for processing (6)
  • pkg/config/configlaunchers_test.go
  • pkg/helpers/paths_test.go
  • pkg/helpers/pathutil/pathutil_test.go
  • pkg/platforms/windows/platform.go
  • pkg/platforms/windows/platform_test.go
  • scripts/tasks/cross-lint.yml
✅ Files skipped from review due to trivial changes (2)
  • pkg/helpers/paths_test.go
  • pkg/helpers/pathutil/pathutil_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/config/configlaunchers_test.go
  • pkg/platforms/windows/platform_test.go

Comment on lines +193 to +200
customKill := p.lastLauncher.Kill
p.lastLauncher = platforms.Launcher{}

if customKill != nil {
p.trackedProcess = nil
log.Debug().Msg("killed tracked process")
p.processMu.Unlock()
log.Debug().Msg("using custom Kill function for launcher")
if err := customKill(&config.Instance{}); err != nil {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Current Windows call site:"
sed -n '190,205p' pkg/platforms/windows/platform.go

echo
echo "Kill implementations that accept *config.Instance:"
python <<'PY'
from pathlib import Path
import re

pattern = re.compile(r'Kill:\s*func\(\s*(\w+)\s+\*config\.Instance[^)]*\)\s*error\s*\{', re.M)
for path in Path(".").rglob("*.go"):
    text = path.read_text(encoding="utf-8")
    for match in pattern.finditer(text):
        var = match.group(1)
        brace = text.find("{", match.end() - 1)
        depth = 0
        end = brace
        while end < len(text):
            ch = text[end]
            if ch == "{":
                depth += 1
            elif ch == "}":
                depth -= 1
                if depth == 0:
                    end += 1
                    break
            end += 1
        body = text[brace:end]
        uses_cfg = bool(re.search(rf"\b{re.escape(var)}\.", body))
        line = text.count("\n", 0, match.start()) + 1
        print(f"{path}:{line}: uses_cfg={uses_cfg}")
PY

Repository: ZaparooProject/zaparoo-core

Length of output: 860


🏁 Script executed:

cat pkg/platforms/platforms.go | grep -A 20 "type Launcher struct"

Repository: ZaparooProject/zaparoo-core

Length of output: 1449


🏁 Script executed:

rg "Kill:\s*func" --type go -A 5 -B 2

Repository: ZaparooProject/zaparoo-core

Length of output: 2201


Pass the real runtime config into launcher.Kill.

The Launcher.Kill interface accepts a *config.Instance parameter, indicating implementations may need access to the active configuration. Line 200 calls customKill(&config.Instance{}) with an empty instance instead of the actual runtime config. While current implementations all ignore this parameter, passing an empty instance violates the interface contract and blocks future implementations from accessing launcher settings or resolving paths from config.

Store the config in the Platform struct and pass it here:

Suggested fix
 type Platform struct {
+	cfg                     *config.Instance
 	activeMedia             func() *models.ActiveMedia
 	setActiveMedia          func(*models.ActiveMedia)
 	customPlatformToSystem  map[string]string
 	systemToCustomPlatforms map[string][]string
 	trackedProcess          *os.Process
 	launchBoxPipe           *LaunchBoxPipeServer
 	steamTracker            *steamtracker.WindowsPlatformIntegration
 	lastLauncher            platforms.Launcher
 	processMu               syncutil.RWMutex
 	platformMappingsMu      syncutil.RWMutex
 	launchBoxPipeLock       syncutil.Mutex
 }

 func (p *Platform) StartPost(
 	cfg *config.Instance,
 	_ platforms.LauncherContextManager,
 	activeMedia func() *models.ActiveMedia,
 	setActiveMedia func(*models.ActiveMedia),
 	_ *database.Database,
 ) error {
+	p.cfg = cfg
 	p.activeMedia = activeMedia
 	p.setActiveMedia = setActiveMedia
 	...
 }

 ...
-		if err := customKill(&config.Instance{}); err != nil {
+		if err := customKill(p.cfg); err != nil {
 			log.Warn().Err(err).Msg("custom Kill function failed")
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/platforms/windows/platform.go` around lines 193 - 200, The code calls the
launcher Kill function with an empty config instance
(customKill(&config.Instance{})) which violates the interface; update the
Platform to store the active runtime config (e.g., add a field like config
*config.Instance on the Platform struct when created/initialized) and pass that
stored config into p.lastLauncher.Kill instead of a newly allocated empty
struct. Locate references to p.lastLauncher.Kill / customKill and replace the
empty-instance call with customKill(p.config) (ensuring p.config is set where
Platform is constructed and protected by p.processMu as needed), keeping the
existing trackedProcess niling and unlocking behavior intact.

@wizzomafizzo wizzomafizzo merged commit 8037d9e into main Apr 15, 2026
11 checks passed
@wizzomafizzo wizzomafizzo deleted the fix/642-hold-mode-relative-paths branch April 15, 2026 07:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scan mode hold not working with Retrobat and relative path issue in Zaparoo

1 participant