fix: use python3 for correctness checks and add CI (#50)

The benchmark harness hardcoded `python`, which is missing on macOS and
many Linux images. Probe python3 first, add npm test, and run checks in
GitHub Actions so regressions are caught on every PR.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Christopher Mayfield
2026-06-15 11:11:04 +02:00
committed by GitHub
co-authored by Cursor
parent 2302fbc843
commit f02f9424a5
4 changed files with 51 additions and 2 deletions
+29
View File
@@ -0,0 +1,29 @@
name: test
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Python deps for correctness checks
run: pip install pandas
- name: Check rule copies
run: node scripts/check-rule-copies.js
- name: Run tests
run: npm test
+3
View File
@@ -165,8 +165,11 @@ When changing the compact rule text, keep the agent copies aligned:
```bash
node scripts/check-rule-copies.js
npm test
```
The correctness benchmark spawns Python for email and CSV checks; `python3` is tried before `python`. CSV checks need `pandas` installed locally.
## FAQ
**Does it need a config file?**
+16 -2
View File
@@ -38,6 +38,20 @@ function exec(cmd, opts = {}) {
}
}
// ponytail: probe once at load; macOS and many Linux images ship python3 only.
let pythonCmd;
function python() {
if (pythonCmd) return pythonCmd;
for (const cmd of ['python3', 'python']) {
if (exec(`${cmd} -c "import sys"`).ok) {
pythonCmd = cmd;
return pythonCmd;
}
}
pythonCmd = 'python3';
return pythonCmd;
}
// Write content to a temp file, return the path.
function tmpFile(ext, content) {
const p = path.join(os.tmpdir(), `ponytail-bench-${Date.now()}-${Math.random().toString(36).slice(2)}${ext}`);
@@ -100,7 +114,7 @@ if failures:
print("PASS")
`;
const f = tmpFile('.py', harness);
const result = exec(`python "${f}"`);
const result = exec(`${python()} "${f}"`);
fs.unlinkSync(f);
if (result.ok) return { pass: true, reason: 'Email validator passes all checks' };
return { pass: false, reason: result.stderr || 'Email validator failed' };
@@ -194,7 +208,7 @@ else:
sys.exit(1)
`;
const f = tmpFile('.py', harness);
const result = exec(`python "${f}"`);
const result = exec(`${python()} "${f}"`);
try { fs.unlinkSync(f); } catch (e) {}
try { fs.unlinkSync(csvPath); } catch (e) {}
if (result.ok) return { pass: true, reason: 'CSV sum produces correct result (351)' };
+3
View File
@@ -4,6 +4,9 @@
"description": "Lazy senior dev mode for AI agents. The best code is the code you never wrote.",
"keywords": ["pi-package", "pi", "skills", "ponytail"],
"license": "MIT",
"scripts": {
"test": "node --test tests/*.test.js && npm test --prefix pi-extension"
},
"pi": {
"extensions": ["./pi-extension/index.js"],
"skills": ["./skills"]