mirror of
https://github.com/EveryInc/compound-engineering-plugin.git
synced 2026-09-19 01:09:55 +08:00
126 lines
5.8 KiB
Markdown
126 lines
5.8 KiB
Markdown
---
|
|
title: "Resolve the Python interpreter by probing execution — never hardcode `python3` in agent-facing prose"
|
|
date: 2026-07-24
|
|
category: conventions
|
|
module: "skills (agent-facing reference prose and SKILL.md shell blocks across every skill with bundled scripts)"
|
|
problem_type: convention
|
|
component: tooling
|
|
severity: high
|
|
applies_when:
|
|
- "Writing a SKILL.md or reference doc that instructs an agent to run a bundled script"
|
|
- "A bundled Python script works when run by hand but the documented invocation fails"
|
|
- "Supporting native Windows contributors (not WSL, not Git Bash with a POSIX Python)"
|
|
- "A feature degrades to a fallback path on one platform and never reports why"
|
|
tags: [windows, python, interpreter-resolution, portability, skill-authoring, silent-failure, store-stub]
|
|
---
|
|
|
|
# Resolve the Python interpreter by probing execution — never hardcode `python3` in agent-facing prose
|
|
|
|
## Context
|
|
|
|
While adding native Windows support to `peer-job-runner.py` (issue #1243), the runner
|
|
itself was made to work — verified end to end on Windows 11. The feature still did not
|
|
work, because every skill that invokes it tells the agent to run:
|
|
|
|
```bash
|
|
python3 "$SKILL_DIR/scripts/peer-job-runner.py" start ...
|
|
```
|
|
|
|
On native Windows, `python3` resolves to the **Microsoft Store App Execution Alias stub**.
|
|
It prints an install advertisement and exits non-zero without running Python. The standard
|
|
python.org Windows installer creates `python.exe` and `py.exe` — it **never** creates
|
|
`python3.exe`. So this is the default state of an extremely common setup, not an edge case.
|
|
|
|
Observed on Windows 11 / Python 3.11:
|
|
|
|
```
|
|
$ python3 --version
|
|
Python was not found; run without arguments to install from the Microsoft Store, ...
|
|
$ echo $?
|
|
49
|
|
$ python --version
|
|
Python 3.11.0
|
|
```
|
|
|
|
The failure surfaced while attempting a sanctioned cross-model review pass: it died at the
|
|
interpreter, before the runner's own preflight ever ran.
|
|
|
|
## Guidance
|
|
|
|
**Do not hardcode an interpreter name in prose an agent will execute.** Resolve it, and
|
|
resolve it by *probing execution*, not presence.
|
|
|
|
```bash
|
|
PY="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"; [ -n "$PY" ] || { echo "no working Python 3 interpreter on PATH" >&2; exit 1; };
|
|
```
|
|
|
|
Then invoke `"$PY" "$SKILL_DIR/scripts/…"`.
|
|
|
|
Three rules make this work:
|
|
|
|
1. **Probe execution, not existence.** This is the whole trap. `command -v python3`
|
|
**succeeds** — the Store stub is a real file on `PATH`. Every existence check (`command
|
|
-v`, `which`, `test -x`) passes and the call still fails. Only actually running the
|
|
interpreter (`"$c" -c ''`) distinguishes them.
|
|
2. **Repeat the resolution in every self-contained shell block.** Agent harnesses run each
|
|
tool call in a **fresh shell**, so a `$PY` exported in one block does not exist in the
|
|
next. The repetition is deliberate, not redundancy to factor out — the same reason
|
|
`SKILL_DIR` is already set inline in every block in these docs.
|
|
3. **Make interpreter failure explicit before the operation crosses its boundary.** A
|
|
required Python operation exits non-zero with a message. An additive workflow may
|
|
instead log and skip cleanly, but it must do so before provider egress or partial work;
|
|
silent fallback to a broken interpreter is never acceptable.
|
|
|
|
Order matters: try `python3` first so POSIX hosts keep their canonical name, then `python`,
|
|
then `py` (the Windows launcher, the most reliable there). Note `python` can *also* be a
|
|
Store stub if python.org Python is not installed — which is why the probe, not the order,
|
|
is what guarantees correctness.
|
|
|
|
## Why This Matters
|
|
|
|
The historical failure was silent in the worst way: the calling workflow degraded
|
|
gracefully after dispatch failed, so a Windows user could receive a quietly weaker review.
|
|
The current code- and doc-review workers resolve one interpreter before provider egress,
|
|
reuse it for outcome classification and JSON recovery, and log a clean skip if none runs.
|
|
Their regression fixtures prove the provider is not invoked in that state.
|
|
|
|
It also invalidates smoke evidence. This project's own Phase C smoke commands invoke
|
|
`python $runner start ...`, so the runner passed its verification while the shipped
|
|
invocation path — the one an agent actually follows — stayed broken. **Verify the literal
|
|
documented invocation, not a hand-adjusted variant.**
|
|
|
|
## When to Apply
|
|
|
|
Any time agent-facing prose or a bundled script names an interpreter or external tool that
|
|
the host may resolve differently. Python is the instance encountered here; the class is
|
|
larger. The general form: *the name on PATH is not proof the thing runs.*
|
|
|
|
Related repo scope: cross-model review/elevation paths and the remaining
|
|
bundled-script invocation sites (`pr-snapshot`, `sweep-state.py`, `validate-*.py`,
|
|
session-history extractors, `ce-optimize` shell helpers) reuse this exact snippet
|
|
rather than inventing a variant. Issue #1247 closed after the execution-probe migration;
|
|
keep the convention because the Store-stub failure mode remains a platform property.
|
|
|
|
## Examples
|
|
|
|
Before — works on macOS/Linux, silently unreachable on native Windows:
|
|
|
|
```bash
|
|
SKILL_DIR="<absolute path…>";
|
|
python3 "$SKILL_DIR/scripts/peer-job-runner.py" status "<job-id>" --json
|
|
```
|
|
|
|
After — self-contained, correct on every host:
|
|
|
|
```bash
|
|
SKILL_DIR="<absolute path…>";
|
|
PY="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"; [ -n "$PY" ] || { echo "no working Python 3 interpreter on PATH" >&2; exit 1; };
|
|
"$PY" "$SKILL_DIR/scripts/peer-job-runner.py" status "<job-id>" --json
|
|
```
|
|
|
|
The wrong fix, for the record — this passes and still breaks, because the stub satisfies it:
|
|
|
|
```bash
|
|
PY=$(command -v python3 || command -v python) # WRONG: existence, not execution
|
|
```
|