Panel/docs/decisions/COMPANION_PROGRAMS_DESIGN.md
2026-06-08 16:09:54 -05:00

28 KiB

Companion Programs Design Investigation

Workspace reference: GSP-WORKSPACE.md

This is an investigation-only design report for adding first-class companion/sidecar application support to GSP game servers. No implementation is included here.

Repository layout reviewed:

  • /Agent-Windows
  • /Agent_Linux
  • /Panel
  • /Website

Note: the repository currently uses Agent_Linux on disk, not Agent-Linux.

1. Current Flow Found

Main Agent Files

Relevant files:

  • Agent_Linux/ogp_agent.pl
  • Agent-Windows/ogp_agent.pl
  • Panel/includes/lib_remote.php
  • Panel/modules/gamemanager/mini_start.php
  • Panel/modules/gamemanager/home_handling_functions.php
  • Panel/modules/gamemanager/start_server.php
  • Panel/modules/gamemanager/stop_server.php
  • Panel/modules/gamemanager/restart_server.php
  • Panel/modules/config_games/schema_server_config.xml
  • Panel/modules/config_games/server_config_parser.php
  • Panel/modules/config_games/config_servers.php
  • Panel/modules/config_games/cli-params.php

Agent Startup Directory And Autostart

Both agents define an agent run directory and a startup flag directory:

  • Linux: AGENT_RUN_DIR, GAME_STARTUP_DIR, SCREEN_LOGS_DIR, SCREENRC_FILE
  • Windows/Cygwin: same general constants, with Windows-specific SteamCMD executable paths

Both agents create/read the startups directory on agent startup. If startup files exist and --no-startups is not set, the agent reads each startup file and calls universal_start_without_decrypt(...) with the saved startup arguments.

Startup files are CSV-like records containing:

home_id, home_path, server_exe, run_dir, startup_cmd, server_port, server_ip, cpu, nice, preStart, envVars, game_key, console_log

These files are useful for agent autostart but should not be treated as runtime status truth.

Screen Usage

Both agents use screen as the shared runtime backend.

Linux:

  • create_screen_id(SCREEN_TYPE_HOME, $home_id) creates names like OGP_HOME_000000123.
  • create_screen_cmd(...) returns a screen -d -m -t ... -S ... command.
  • create_screen_cmd_loop(...) creates a generated shell script named like OGP_HOME_000000123_startup_scr.sh, then runs that script inside screen.
  • The generated shell script loops/restarts the server when autorestart is enabled.
  • The script checks for SERVER_STOPPED before respawning.

Windows/Cygwin:

  • Uses the same create_screen_id(...) naming pattern.
  • create_screen_cmd(...) launches a command in screen.
  • create_screen_cmd_loop(...) writes _serverStart.bat, then runs it through cmd /Q /C inside screen.
  • The generated batch file loops/restarts the server when autorestart is enabled.
  • The batch file checks SERVER_STOPPED before respawning.

Start Flow

Panel start path:

  • Panel/modules/gamemanager/mini_start.php builds $start_cmd.
  • It collects XML pre_start, environment_variables, lock_files, executable name, executable location, port, IP, CPU affinity, nice value, game key, and console log.
  • It calls $remote->universal_start(...).

Linux agent start:

  • universal_start_without_decrypt(...) validates the home path and executable.
  • It may create a per-game Linux user when that preference is enabled.
  • It writes/updates the startup flag file in GAME_STARTUP_DIR.
  • It converts pre_start and environment variables between multiline and startup-safe formats.
  • It builds the command according to executable type:
    • .exe / .bat: Wine command
    • .jar: startup command
    • other: ./server_exe startup_cmd
  • It creates a generated shell startup script through create_screen_cmd_loop(...).
  • It backs up screenlogs/screenlog.<screen_id>.
  • It runs pre-start commands through run_before_start_commands(...).
  • It launches the generated command through sudo_exec_without_decrypt($cli_bin, $owner).
  • It renices server processes after launch.

Windows/Cygwin agent start:

  • universal_start_without_decrypt(...) validates the home path and executable.
  • It converts paths with cygpath -wa.
  • It converts pre_start and environment variables.
  • It builds Windows commands using cmd /Q /C start ... /WAIT.
  • With autorestart enabled, it uses create_screen_cmd_loop(...) and _serverStart.bat.
  • Without autorestart, it uses create_screen_cmd(...).
  • It backs up screenlogs/screenlog.<screen_id>.
  • It runs pre-start commands through run_before_start_commands(...).
  • It launches the screen command with system($cli_bin).
  • It writes a startup file named _serverStart.bat under GAME_STARTUP_DIR, though the name is generic rather than per IP/port in the current Windows path.

Stop Flow

Panel stop path:

  • Panel/modules/gamemanager/stop_server.php calls $remote->remote_stop_server(...).
  • Stop parameters include home ID, IP, port, control protocol, control password, control type, and home path.

Linux agent stop:

  • stop_server_without_decrypt(...) removes the startup flag for $server_ip-$server_port.
  • If autorestart is enabled, it creates SERVER_STOPPED in the game home.
  • It attempts a graceful stop when configured:
    • rcon
    • rcon2
    • armabe
    • minecraft
  • If graceful stop does not complete, it collects PIDs from the screen session using get_home_pids(...).
  • It sends kill 15, then kill 9 if needed.
  • It runs screen -wipe.

Windows/Cygwin agent stop:

  • stop_server_without_decrypt(...) removes the startup flag.
  • If autorestart is enabled, it creates SERVER_STOPPED in the game home.
  • It finds the screen PID from screen -list.
  • It maps that to a Windows PID using ps -W.
  • It calls cmd /C taskkill /f /fi 'PID eq ...' /T.
  • It runs screen -wipe.

Restart Flow

Both agents expose restart_server and restart_server_without_decrypt(...).

The current intended restart flow is:

  1. Stop server.
  2. Wait 60 seconds.
  3. Start server.

That flow is now present in the current agent files. Any companion system should hook into this sequence explicitly:

  1. Stop companions.
  2. Stop game server.
  3. Wait 60 seconds.
  4. Start game server.
  5. Start companions after their configured delays.

PID Tracking

Current PID tracking exists but is inconsistent:

  • The agents write their own ogp_agent.pid.
  • FastDownload has fd.pid.
  • Scheduler has scheduler.pid.
  • Linux game server child PIDs are discovered from the screen PID with pgrep -P.
  • Windows/Cygwin maps a screen PID to a Windows PID through ps -W.
  • Some game XML uses the PID_FILE CLI param, for example Source-engine servers.
  • Windows _alsoRun.bat behavior expects _alsoRun.pid to contain helper PIDs.

There is no general companion PID registry today.

Marker Files

Relevant marker files:

  • GAME_STARTUP_DIR/<ip>-<port> startup flag on Linux.
  • Windows writes a startup file under GAME_STARTUP_DIR, currently _serverStart.bat.
  • SERVER_STOPPED in the game home when autorestart is enabled.
  • _alsoRun.pid for the current Windows helper behavior.

SERVER_STOPPED is used by generated autorestart scripts to decide whether to respawn. It should not be used as the source of truth for current runtime status.

Logs

Game screen logs are written under:

screenlogs/screenlog.<screen_id>

The agents call backup_home_log(...) before starting a server. If XML defines console_log, Panel/agent log functions may read the game-specific console log instead.

There is no dedicated companion stdout/stderr log path today.

2. Current Helper Script Behavior

_alsoRun.bat

The clearest current companion behavior is Windows-only.

In Agent-Windows/ogp_agent.pl, create_screen_cmd_loop(...) generates _serverStart.bat. That generated batch file contains:

if exist "_alsoRun.bat" call "_alsoRun.bat"
start ... /wait <game command>
for /f %%p in (_alsoRun.pid) do taskkill /PID %%p /F

This means:

  • _alsoRun.bat is executed before the game server process.
  • _alsoRun.pid is read after the game server exits.
  • Each PID listed in _alsoRun.pid is force-killed.
  • This only exists in the Windows/Cygwin agent path.
  • It only works when the generated _serverStart.bat loop path is used.
  • It relies on files in or near the game server working directory.
  • It depends on the helper script correctly writing _alsoRun.pid.

Some DayZ/Arma XML files generate _alsoRun.bat in pre_start. Examples found include:

  • Panel/modules/config_games/server_configs/dayz_arma2co_win32.xml
  • Panel/modules/config_games/server_configs/dayz_epoch_mod_win32.xml

Those XML files build _alsoRun.bat to start BEC and use WMIC to find/write the BEC PID into _alsoRun.pid.

Problems:

  • The helper file lives in a customer-accessible game area.
  • The customer may be able to edit/delete _alsoRun.bat or _alsoRun.pid.
  • It is Windows-specific.
  • PID capture depends on executable path matching and WMIC.
  • Cleanup happens after the game process exits, not as a first-class stop action.
  • It is not centrally visible to the Panel as companion state.

pre_start

The XML schema supports pre_start.

Panel reads pre_start in:

  • Panel/modules/gamemanager/mini_start.php
  • Panel/modules/gamemanager/restart_server.php
  • Panel/modules/gamemanager/home_handling_functions.php

The value is passed to the agent as $preStart.

Linux behavior:

  • run_before_start_commands(...) writes ${home_path}/prestart_ogp.sh.
  • It writes each XML line into the shell file.
  • It runs bash prestart_ogp.sh as the game owner.
  • The script removes itself at the end.

Windows/Cygwin behavior:

  • run_before_start_commands(...) writes _prestart.bat in the Windows-converted home path.
  • It writes each XML line into the batch file.
  • It runs cmd /Q /C start /wait "<_prestart.bat>".
  • It deletes _prestart.bat.

Concerns:

  • pre_start is trusted XML/admin-defined script content, but it executes in/against the customer game home.
  • It is not structured.
  • It is not tracked.
  • It is only "before start"; it is not a companion lifecycle model.
  • It cannot reliably stop helper processes unless custom script authors implement that themselves.

post_start

The schema and config editor order include post_start.

Found references:

  • Panel/modules/config_games/schema_server_config.xml
  • Panel/modules/config_games/config_servers.php
  • Panel/modules/config_games/xml_tag_descriptions.php
  • One example XML: Panel/modules/config_games/server_configs/nexuiz_win.xml

I did not find a start path that reads server_xml->post_start or sends it to the agents. As currently written, post_start appears schema-visible but not operational.

post_install

Both agents include workshop/mod post-install script generation logic. This is install/update-related, not game-server runtime lifecycle management.

post_install should not be used for companion processes because it is not tied to server start/stop/restart.

Custom Fields And Custom Scripts

Custom fields are supported in XML and stored per server. They are used by config replacement logic:

  • Panel/modules/gamemanager/cfg_text_replace.php
  • Panel/modules/config_games/schema_server_config.xml

Custom fields can influence config file content. They are not currently a safe or structured way to define executable companion commands.

Customers can also use extra startup parameters where permissions allow. That should not become the companion command source because it would permit arbitrary command injection into managed helper launches.

First-Class Companion Programs System

The best design is a first-class, structured companion program system.

Game XML should define the allowed companion programs for that game. The Panel should store per-server choices such as enabled/disabled and optional safe settings. The agent should own runtime launch, PID tracking, log paths, stop, and restart cleanup.

Example XML shape:

<companion_programs>
  <program key="bec" name="BattlEye Extended Controls" os="windows">
    <enabled_default>0</enabled_default>
    <delay_seconds_default>30</delay_seconds_default>
    <working_dir>{GAME_PATH}\BEC</working_dir>
    <command>Bec.exe</command>
    <args>-f Config.cfg</args>
    <process_name>Bec.exe</process_name>
    <stop_on_server_stop>1</stop_on_server_stop>
    <restart_on_server_restart>1</restart_on_server_restart>
    <stdout_log>companions/bec.out.log</stdout_log>
    <stderr_log>companions/bec.err.log</stderr_log>
  </program>
</companion_programs>

Recommended XML fields:

  • key: stable internal ID.
  • name: display name.
  • os: linux, windows, or any.
  • enabled_default: default panel setting.
  • delay_seconds_default: default delay after game start.
  • working_dir: trusted template path.
  • command: trusted executable/script name or path template.
  • args: trusted default arguments.
  • process_name: optional verification aid only, not the kill target by itself.
  • stop_command: optional graceful stop command.
  • stop_timeout_seconds: default graceful wait.
  • kill_after_timeout: boolean.
  • stop_on_server_stop: boolean.
  • restart_on_server_restart: boolean.
  • stdout_log / stderr_log: relative managed log paths.
  • required_files: optional list for Panel validation.
  • requires_game_online: whether to delay until the game port is online.

Where XML Defines Allowed Companion Programs

Add companion_programs to Panel/modules/config_games/schema_server_config.xml as an optional top-level element.

Only admins/editors of game XML should be able to define:

  • executable path
  • arguments
  • working directory
  • stop command
  • process name
  • default delay
  • log paths

Customers should not be able to enter arbitrary commands.

Where Panel Stores Per-Server Settings

Panel should store per-home companion settings in the database, not in customer-editable files.

Possible table:

server_companion_settings (
  id INT AUTO_INCREMENT PRIMARY KEY,
  home_id INT NOT NULL,
  companion_key VARCHAR(64) NOT NULL,
  enabled TINYINT(1) NOT NULL DEFAULT 0,
  delay_seconds INT NULL,
  settings_json LONGTEXT NULL,
  UNIQUE KEY uniq_home_companion (home_id, companion_key)
)

settings_json should only contain safe, schema-defined options. Do not allow free-form command or shell text. For example:

  • config profile selection
  • config file name from an allowed list
  • delay override within min/max bounds
  • environment preset key

How The Agent Receives Settings

Extend the encrypted XML-RPC start/restart call to include a companion payload, or add a dedicated agent RPC after start:

Recommended:

  • universal_start(..., companion_payload) for direct lifecycle coupling.
  • server_companion_start(home_id, payload) for explicit start action.
  • server_companion_stop(home_id) for explicit stop action.
  • server_companion_status(home_id) for status display.

The payload should be generated by the Panel from trusted XML plus stored per-server enabled settings.

Payload should contain fully resolved, validated data:

{
  "home_id": 123,
  "server_ip": "1.2.3.4",
  "server_port": 2302,
  "companions": [
    {
      "key": "bec",
      "enabled": true,
      "delay_seconds": 30,
      "working_dir": "/home/ogp_agent/OGP_User_Files/123/BEC",
      "command": "Bec.exe",
      "args": ["-f", "Config.cfg"],
      "stdout_log": "bec.out.log",
      "stderr_log": "bec.err.log"
    }
  ]
}

For XML-RPC compatibility, this may be passed as JSON text.

How The Agent Starts Companions

The agent should start companions after the game screen/session has launched.

Recommended approach:

  • Use separate screen sessions per companion.
  • Session naming:
    • Game: OGP_HOME_000000123
    • Companion: OGP_COMPANION_000000123_bec
  • Write companion runtime state under an agent-controlled path outside the game FTP/file-manager root.
  • Start delayed companions through a small agent-owned delay wrapper:
    • Linux: screen -d -m -S OGP_COMPANION_... bash -lc 'sleep 30; cd ...; exec ...'
    • Windows/Cygwin: screen -d -m -S OGP_COMPANION_... cmd /Q /C "timeout /t 30 ... && cd /d ... && ..."

This avoids blocking game startup. The Panel can show the game as STARTING/ONLINE independently while companion statuses move through PENDING, STARTING, RUNNING, or FAILED.

How The Agent Records PIDs

Create an agent-owned runtime directory, for example:

<AGENT_RUN_DIR>/companions/<home_id>/

Files:

companions/<home_id>/state.json
companions/<home_id>/pids/<companion_key>.pid
companions/<home_id>/logs/<companion_key>.out.log
companions/<home_id>/logs/<companion_key>.err.log

State should include:

  • home ID
  • companion key
  • screen session name
  • agent PID/screen PID
  • child PID if known
  • command hash or executable path
  • start time
  • last status
  • last error

For Linux:

  • Prefer launching through screen.
  • Use the screen PID plus child process lookup.
  • If possible, make the wrapper write echo $$ and the exec child PID to a PID file.
  • Use process group/session cleanup where possible.

For Windows/Cygwin:

  • Keep screen for parity.
  • Prefer a wrapper that starts the companion and writes the Windows PID to a PID file.
  • Use Cygwin ps -W or PowerShell/WMIC alternatives where available.
  • Avoid killing by executable name alone.

How The Agent Stops Companions

Stop by the recorded handle, not by executable name.

Recommended stop order:

  1. Load companions/<home_id>/state.json.
  2. For each running companion:
    • If stop_command exists, run it in the configured working directory.
    • Wait up to stop_timeout_seconds.
    • If still alive and kill_after_timeout=1, kill only recorded PID/process tree/session.
    • Close the companion screen session.
    • Update state.
  3. Clean stale PID files only after verifying the process is gone.

Avoid:

  • pkill Bec.exe
  • taskkill /IM Bec.exe
  • broad executable-name matching

Those can kill unrelated customer processes.

Restart Behavior

Recommended restart sequence:

  1. Stop companions for the home.
  2. Stop game server.
  3. Wait 60 seconds.
  4. Start game server.
  5. Start enabled companions according to delay settings.

Do not let companions survive a restart unless explicitly marked as persistent and safe.

Companion Logging

Companion stdout/stderr should be logged separately from game screen logs.

Recommended default:

<AGENT_RUN_DIR>/companions/<home_id>/logs/<key>.out.log
<AGENT_RUN_DIR>/companions/<home_id>/logs/<key>.err.log

Panel can add a companion log viewer later, separate from the game server log viewer.

For customer visibility, expose logs through the agent RPC after permission checks rather than placing them inside the customer FTP root by default.

Security

This method is secure because:

  • Commands come from trusted game XML/admin configuration.
  • Customer UI stores only enable/disable and bounded safe settings.
  • Runtime files live outside the customer file manager/FTP root.
  • The agent launches only known companion keys for the current game config.
  • Stop/kill uses recorded PIDs/screen sessions, not executable names.
  • Logs are controlled by the agent.

Portability

This method is portable because:

  • XML can define Linux and Windows variants with the same logical companion key.
  • Agent receives normalized companion payload.
  • Both agents use screen sessions.
  • PID capture is platform-specific behind the same agent RPC model.

Agent-Managed Generated Startup/Cleanup Scripts

Alternate design: keep using scripts, but generate and store them in an agent-controlled directory outside customer-editable game files.

Example layout:

<AGENT_RUN_DIR>/companions/<home_id>/
  companions.json
  start_companions.sh
  stop_companions.sh
  start_companions.bat
  stop_companions.bat
  pids/
  logs/

The Panel still defines companions from trusted XML and stores per-server enabled settings. The agent generates scripts from those trusted definitions.

Start flow:

  1. Game server launches.
  2. Agent starts an agent-owned companion startup script in its own screen session.
  3. Script handles delays and PID capture.

Stop flow:

  1. Agent runs an agent-owned cleanup script.
  2. Script kills only PIDs listed in the agent-owned pids directory.
  3. Agent verifies cleanup.

Pros

  • Closer to the existing _serverStart.bat and generated shell script model.
  • Easier to debug for admins because generated scripts are readable.
  • Can work with the existing screen backend.
  • Avoids customer-editable _alsoRun.bat.
  • Can be implemented incrementally.

Cons

  • Still script-heavy.
  • Quoting rules remain difficult across Linux, Cygwin, and Windows.
  • Risk of script injection if generation is not strict.
  • PID capture still needs platform-specific care.
  • State management can drift if scripts are edited manually by admins.
  • Less clean than direct agent-managed process APIs.

Comparison To Method 1

Method 1 is better long term because the agent owns lifecycle state directly. Method 2 is a reasonable migration bridge if implementation speed matters, but it should still use trusted XML/admin definitions and agent-owned control paths.

5. Security Considerations

Do Not Trust Customer-Editable Startup Files

Avoid using customer-editable files such as:

  • _alsoRun.bat
  • _alsoRun.pid
  • arbitrary .bat or .sh helper files in the game home

Those files can be edited, deleted, replaced, or used to run unintended commands.

Managed Files Should Live Outside The FTP/File Manager Root

Recommended location:

<AGENT_RUN_DIR>/companions/<home_id>/

This directory should be owned by the agent or game server runner user and should not be directly writable by customers.

Commands Must Come From Trusted Configuration

Companion commands should come from:

  • shipped game XML
  • admin-managed XML
  • a future admin-only companion catalog

They should not come from:

  • customer text fields
  • startup extra parameters
  • uploaded files
  • customer-editable config files

Validate Commands

Validation should include:

  • companion key exists in the current game XML
  • OS matches the agent OS
  • command path resolves under an allowed directory unless explicitly admin-approved
  • working directory resolves under game home or an admin-approved path
  • no unexpanded {...} tokens remain
  • no shell metacharacters in fields that are supposed to be argv tokens
  • delay is numeric and capped
  • log paths are relative and cannot escape managed log directories

Avoid Arbitrary Command Execution

Use argv-style execution where possible.

When shell/batch is unavoidable:

  • generate commands from trusted fields only
  • quote every path/argument consistently
  • avoid concatenating customer-provided strings into shell code
  • keep generated files outside customer write paths

Avoid Killing Unrelated Processes

Do not kill by executable name alone.

Preferred kill targets:

  • recorded companion PID
  • recorded process group
  • recorded screen session
  • recorded Windows process tree for that PID

Process name should be used only as a verification hint, not as the primary kill selector.

6. Cross-platform Considerations

Linux Agent

Linux can use:

  • screen
  • bash
  • PID files
  • /proc
  • pgrep -P
  • kill 15, then kill 9

Recommended Linux companion launch:

screen -d -m -S OGP_COMPANION_<home_id>_<key> bash -lc '<agent-owned wrapper>'

Use an agent-owned wrapper or direct fork/exec to record PID and redirect logs.

Windows/Cygwin Agent

Windows/Cygwin can use:

  • screen
  • cmd /Q /C
  • start
  • taskkill /PID ... /T
  • ps -W
  • possibly WMIC or PowerShell depending on environment

Current _alsoRun.bat depends on WMIC in some XML. WMIC is not reliable on all modern Windows installations, so future code should not require it.

Recommended Windows companion launch:

screen -d -m -S OGP_COMPANION_<home_id>_<key> cmd /Q /C "<agent-owned wrapper.bat>"

The wrapper should record the Windows PID or enough process/session information for cleanup.

Batch vs Shell Differences

Risks:

  • quoting spaces in paths
  • escaping backslashes
  • environment variable syntax differences
  • start window title behavior on Windows
  • delayed expansion in batch files
  • Cygwin path vs Windows path conversion
  • signal semantics: Linux signals vs Windows taskkill

The Panel should not build platform command strings. It should send trusted structured definitions to the agent and let the agent perform OS-specific quoting/execution.

Screen Behavior

Screen remains the default shared backend for now.

Use separate screen sessions for companions rather than attaching them to the game server screen. This gives:

  • independent status
  • independent logs
  • safer cleanup
  • clearer restart behavior

Process Cleanup Risks

Companion processes may:

  • fork children
  • daemonize
  • spawn background processes
  • exit while leaving children
  • fail before writing PID
  • be started manually by the customer/admin

The agent should track process trees where possible and verify stop results.

7. Suggested Implementation Phases

Phase 1: Inventory Current Flow And Add Report Only

This report is Phase 1.

No source code changes should be made for companion behavior in this phase.

Phase 2: XML Schema Design

Add companion_programs to:

  • Panel/modules/config_games/schema_server_config.xml
  • Panel/modules/config_games/config_servers.php
  • Panel/modules/config_games/xml_tag_descriptions.php

Create example XML for BEC, B3, and a generic log watcher.

Phase 3: Panel Storage/UI Design

Add storage for per-server companion settings.

Initial UI:

  • show companion list from XML
  • enable/disable checkbox
  • delay override
  • safe predefined options only

Do not expose raw command editing to customers.

Phase 4: Agent Start/Stop Integration

Add encrypted RPCs:

  • server_companion_start
  • server_companion_stop
  • server_companion_status

Extend start/restart flow to call companion start/stop at the right time.

Phase 5: PID Tracking And Cleanup

Implement:

  • agent-owned state directory
  • PID files
  • screen session names
  • process tree cleanup
  • stale PID detection
  • companion status reporting

Phase 6: DayZ/BEC Test

Migrate one DayZ/Arma BEC case away from _alsoRun.bat.

Test:

  • start game
  • delayed BEC start
  • BEC status
  • stop game
  • BEC cleanup
  • restart flow
  • crash/recovery behavior
  • agent restart behavior

Phase 7: Generalized Docs

Document:

  • XML authoring
  • admin setup
  • supported placeholders
  • security rules
  • troubleshooting
  • log locations
  • migration path from _alsoRun.bat

8. Open Questions

  1. Should companions be started after the game process exists, after the game port is listening, or after query/RCON succeeds when available?
  2. Should companions be allowed to keep running if the game server crashes and autorestarts, or should they always restart with each game process cycle?
  3. Should some companions be marked "persistent" across game restarts?
  4. Which user should run companions on Linux when LINUX_USER_PER_GAME_SERVER is enabled?
  5. Should companion logs be visible to customers by default, or admin-only?
  6. Should companion config files be editable through the existing config file module?
  7. How should Windows PID capture work on systems without WMIC?
  8. Is PowerShell guaranteed available in the supported Windows/Cygwin agent environment?
  9. Should the Panel support companion install/update packages, or only runtime start/stop of already-installed files?
  10. Should companion definitions live only in game XML, or should there be a reusable global companion catalog?
  11. How should firewall rules handle companion ports if a companion needs one?
  12. What should happen if a companion fails but the game server is online?
  13. Should companion failure affect billing/status/customer-facing uptime?
  14. How should agent autostart restore companion state after power loss or agent restart?
  15. Should the agent stop companions before or after graceful game stop for tools that send shutdown messages to the game?
  16. Should companion environment variables be separate from game environment variables?
  17. How should command placeholders be standardized across Linux and Windows?
  18. What is the maximum acceptable startup delay for companion programs?
  19. Should admins be able to override companion commands per server, or only per game XML?
  20. How should existing _alsoRun.bat game configs be migrated without breaking current customers?

Summary Recommendation

Build Method 1: a first-class companion programs system driven by trusted XML/admin configuration, stored per server in the Panel, and executed/owned by the agent.

Do not continue expanding _alsoRun.bat. It is a useful proof of need, but it is Windows-specific, customer-editable, hard to audit, and unreliable for stop/restart cleanup.

Use screen as the shared backend for now, with one screen session per companion and agent-owned PID/log/state files outside the customer file root.