gm-kilo 2.0.47 → 2.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish-npm.yml +28 -3
- package/.gitignore +3 -0
- package/agents/gm.md +5 -5
- package/hooks/pre-tool-use-hook.js +24 -1
- package/package.json +2 -2
- package/skills/dev/SKILL.md +35 -29
- package/skills/process-management/SKILL.md +21 -0
|
@@ -11,27 +11,52 @@ jobs:
|
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
steps:
|
|
13
13
|
- uses: actions/checkout@v4
|
|
14
|
+
with:
|
|
15
|
+
token: ${{ secrets.GH_PAT || github.token }}
|
|
14
16
|
|
|
15
17
|
- uses: actions/setup-node@v4
|
|
16
18
|
with:
|
|
17
19
|
node-version: '22'
|
|
18
20
|
registry-url: 'https://registry.npmjs.org'
|
|
19
21
|
|
|
22
|
+
- name: Configure git
|
|
23
|
+
run: |
|
|
24
|
+
git config user.name "github-actions[bot]"
|
|
25
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
26
|
+
|
|
27
|
+
- name: Bump patch version
|
|
28
|
+
run: |
|
|
29
|
+
PACKAGE=$(jq -r '.name' package.json)
|
|
30
|
+
OLD_VERSION=$(jq -r '.version' package.json)
|
|
31
|
+
|
|
32
|
+
# Skip bump if last commit was already a version bump
|
|
33
|
+
LAST_MSG=$(git log -1 --pretty=%s)
|
|
34
|
+
if echo "$LAST_MSG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
35
|
+
echo "Last commit was a version bump, skipping"
|
|
36
|
+
echo "SKIP_BUMP=true" >> $GITHUB_ENV
|
|
37
|
+
else
|
|
38
|
+
npm version patch --no-git-tag-version
|
|
39
|
+
NEW_VERSION=$(jq -r '.version' package.json)
|
|
40
|
+
git add package.json
|
|
41
|
+
git commit -m "v$NEW_VERSION"
|
|
42
|
+
git push
|
|
43
|
+
echo "Bumped $PACKAGE from $OLD_VERSION to $NEW_VERSION"
|
|
44
|
+
fi
|
|
45
|
+
|
|
20
46
|
- name: Publish to npm
|
|
21
47
|
run: |
|
|
22
48
|
PACKAGE=$(jq -r '.name' package.json)
|
|
23
49
|
VERSION=$(jq -r '.version' package.json)
|
|
24
50
|
echo "Package: $PACKAGE@$VERSION"
|
|
25
51
|
|
|
26
|
-
# Skip if this exact version is already on npm
|
|
27
52
|
PUBLISHED=$(npm view "$PACKAGE@$VERSION" version 2>/dev/null || echo "")
|
|
28
53
|
if [ "$PUBLISHED" = "$VERSION" ]; then
|
|
29
|
-
echo "
|
|
54
|
+
echo "$PACKAGE@$VERSION already published - skipping"
|
|
30
55
|
exit 0
|
|
31
56
|
fi
|
|
32
57
|
|
|
33
58
|
echo "Publishing $PACKAGE@$VERSION..."
|
|
34
59
|
npm publish --access public
|
|
35
|
-
echo "
|
|
60
|
+
echo "Published $PACKAGE@$VERSION"
|
|
36
61
|
env:
|
|
37
62
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/.gitignore
CHANGED
package/agents/gm.md
CHANGED
|
@@ -54,11 +54,11 @@ The .prd path must resolve to exactly ./.prd in current working directory. No va
|
|
|
54
54
|
|
|
55
55
|
Scope: Where and how code runs. Governs tool selection and execution context.
|
|
56
56
|
|
|
57
|
-
All execution via `
|
|
57
|
+
All execution via `code_execution` tool (Python) or `agent-browser` skill. Every hypothesis proven by execution before changing files. Know nothing until execution proves it.
|
|
58
58
|
|
|
59
|
-
**CODE YOUR HYPOTHESES**: Test every possible hypothesis using the `
|
|
59
|
+
**CODE YOUR HYPOTHESES**: Test every possible hypothesis using the `code_execution` tool with Python or `agent-browser` skill. Each run must be under 15 seconds and must densely pack every possible related hypothesis. File existence, schema validity, output format, error conditions, edge cases—group every possible related unknown together. The goal is every possible hypothesis per run. Use `agent-browser` skill for cross-client UI testing and browser-based hypothesis validation.
|
|
60
60
|
|
|
61
|
-
**DEFAULT IS
|
|
61
|
+
**DEFAULT IS code_execution WITH PYTHON**: Call the `code_execution` tool with Python code. The PreToolUse hook intercepts it, runs python3, and returns the output. Bash is blocked except for git, npm publish, and docker. If you find yourself writing a bash command, stop and ask: can this be done in Python? The answer is almost always yes. Use `subprocess.run()` for shell operations that truly can't be done otherwise.
|
|
62
62
|
|
|
63
63
|
**TOOL POLICY**: All code execution via `dev` skill. Use `code-search` skill for exploration. Reference TOOL_INVARIANTS for enforcement.
|
|
64
64
|
|
|
@@ -74,8 +74,8 @@ All execution via `dev` skill or `agent-browser` skill. Every hypothesis proven
|
|
|
74
74
|
|
|
75
75
|
**REQUIRED TOOL MAPPING**:
|
|
76
76
|
- Code exploration: `code-search` skill — THE ONLY exploration tool. Semantic search 102 file types. Natural language queries with line numbers. No glob, no grep, no find, no explore agent, no Read for discovery.
|
|
77
|
-
- Code execution: `
|
|
78
|
-
- File operations: `
|
|
77
|
+
- Code execution: call the `code_execution` tool directly with Python code — the PreToolUse hook intercepts it, runs python3, and returns `[CODE EXECUTION RESULT]\nstdout: ...\nstderr: ...\nexit_code: N` as the result. Use Python's `subprocess` module for shell operations, `pathlib`/`os` for files, `requests` for HTTP.
|
|
78
|
+
- File operations: `code_execution` tool with Python `pathlib`/`os`/`open()` — read, write, stat files
|
|
79
79
|
- Bash: ONLY git, npm publish/pack, docker, system daemons
|
|
80
80
|
- Browser: Use **`agent-browser` skill** instead of puppeteer/playwright - same power, cleaner syntax, built for AI agents
|
|
81
81
|
|
|
@@ -55,6 +55,29 @@ const run = () => {
|
|
|
55
55
|
return { block: true, reason: 'Plan mode is disabled. Use GM agent planning (PLAN→EXECUTE→EMIT→VERIFY→COMPLETE state machine) via gm:gm subagent instead.' };
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
if (tool_name === 'Bash') {
|
|
59
|
+
const command = (tool_input?.command || '').trim();
|
|
60
|
+
const allowed = /^(git |npm publish|npm pack|docker |sudo systemctl|systemctl )/.test(command);
|
|
61
|
+
if (!allowed) {
|
|
62
|
+
return { block: true, reason: 'Bash is blocked. Use the code_execution tool with Python instead. The hook intercepts code_execution, runs python3, and returns stdout/stderr/exit_code. Example: use code_execution with code "import subprocess; r=subprocess.run([\'node\',\'--version\'],capture_output=True,text=True); print(r.stdout)"' };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (tool_name === 'code_execution') {
|
|
67
|
+
const code = tool_input?.code || '';
|
|
68
|
+
const { spawnSync } = require('child_process');
|
|
69
|
+
const proc = spawnSync('python3', ['-'], {
|
|
70
|
+
input: code,
|
|
71
|
+
encoding: 'utf-8',
|
|
72
|
+
timeout: 30000
|
|
73
|
+
});
|
|
74
|
+
const stdout = proc.stdout || '';
|
|
75
|
+
const stderr = proc.stderr || '';
|
|
76
|
+
const exitCode = proc.status !== null ? proc.status : 1;
|
|
77
|
+
const result = `[CODE EXECUTION RESULT]\nstdout: ${stdout}\nstderr: ${stderr}\nexit_code: ${exitCode}`;
|
|
78
|
+
return { block: true, reason: result };
|
|
79
|
+
}
|
|
80
|
+
|
|
58
81
|
return { allow: true };
|
|
59
82
|
} catch (error) {
|
|
60
83
|
return { allow: true };
|
|
@@ -70,7 +93,7 @@ try {
|
|
|
70
93
|
} else {
|
|
71
94
|
console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: result.reason } }));
|
|
72
95
|
}
|
|
73
|
-
process.exit(
|
|
96
|
+
process.exit(0);
|
|
74
97
|
}
|
|
75
98
|
|
|
76
99
|
if (isGemini) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-kilo",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.49",
|
|
4
4
|
"description": "State machine agent with hooks, skills, and automated git enforcement",
|
|
5
5
|
"author": "AnEntrypoint",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,4 +54,4 @@
|
|
|
54
54
|
".gitignore",
|
|
55
55
|
".editorconfig"
|
|
56
56
|
]
|
|
57
|
-
}
|
|
57
|
+
}
|
package/skills/dev/SKILL.md
CHANGED
|
@@ -1,48 +1,54 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dev
|
|
3
|
-
description: Execute code
|
|
4
|
-
allowed-tools: Bash
|
|
3
|
+
description: Execute code by calling the code_execution tool with Python code. The PreToolUse hook intercepts code_execution calls, runs the Python via python3, and returns stdout/stderr/exit_code as the result. Use for all code execution, file operations, running scripts, and hypothesis testing.
|
|
4
|
+
allowed-tools: Bash,code_execution
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Code Execution with dev
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Use the `code_execution` tool with Python code. The hook intercepts the call, executes the Python locally, and returns the result as a deny reason formatted as:
|
|
10
10
|
|
|
11
|
-
## Run code inline
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
# JavaScript / TypeScript
|
|
15
|
-
bun -e "const fs = require('fs'); console.log(fs.readdirSync('.'))"
|
|
16
|
-
bun -e "import { readFileSync } from 'fs'; console.log(readFileSync('package.json', 'utf-8'))"
|
|
17
|
-
|
|
18
|
-
# Run a file
|
|
19
|
-
bun run script.ts
|
|
20
|
-
node script.js
|
|
21
|
-
|
|
22
|
-
# Python
|
|
23
|
-
python -c "import json; print(json.dumps({'ok': True}))"
|
|
24
|
-
|
|
25
|
-
# Shell
|
|
26
|
-
bash -c "ls -la && cat package.json"
|
|
27
11
|
```
|
|
12
|
+
[CODE EXECUTION RESULT]
|
|
13
|
+
stdout: <output>
|
|
14
|
+
stderr: <errors>
|
|
15
|
+
exit_code: <N>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Run code inline
|
|
28
19
|
|
|
29
|
-
|
|
20
|
+
```python
|
|
21
|
+
# File operations
|
|
22
|
+
import os, json
|
|
23
|
+
print(json.dumps(os.listdir('.')))
|
|
30
24
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
# Read a file
|
|
26
|
+
with open('package.json') as f:
|
|
27
|
+
print(f.read())
|
|
34
28
|
|
|
35
|
-
# Write
|
|
36
|
-
|
|
29
|
+
# Write a file
|
|
30
|
+
with open('out.json', 'w') as f:
|
|
31
|
+
import json
|
|
32
|
+
json.dump({'ok': True}, f, indent=2)
|
|
37
33
|
|
|
38
34
|
# Stat / exists
|
|
39
|
-
|
|
35
|
+
import os
|
|
36
|
+
print(os.path.exists('file.txt'), os.path.getsize('.'))
|
|
37
|
+
|
|
38
|
+
# HTTP requests
|
|
39
|
+
import urllib.request
|
|
40
|
+
resp = urllib.request.urlopen('https://example.com')
|
|
41
|
+
print(resp.read()[:200])
|
|
42
|
+
|
|
43
|
+
# Run subprocess
|
|
44
|
+
import subprocess
|
|
45
|
+
r = subprocess.run(['node', '--version'], capture_output=True, text=True)
|
|
46
|
+
print(r.stdout)
|
|
40
47
|
```
|
|
41
48
|
|
|
42
49
|
## Rules
|
|
43
50
|
|
|
44
51
|
- Each run under 15 seconds
|
|
45
52
|
- Pack every related hypothesis into one run — never one idea per run
|
|
46
|
-
- No persistent temp files; if a temp file is needed, delete it in the same
|
|
47
|
-
-
|
|
48
|
-
- Use `bun` over `node` when available
|
|
53
|
+
- No persistent temp files; if a temp file is needed, delete it in the same code
|
|
54
|
+
- Use `code_execution` tool for all execution; Bash only for git/npm publish/docker
|
|
@@ -12,6 +12,27 @@ description: >-
|
|
|
12
12
|
|
|
13
13
|
All applications MUST run through PM2. Direct invocations (node, bun, python) are forbidden for any process that produces output or has a lifecycle.
|
|
14
14
|
|
|
15
|
+
## Installation (First Time Only)
|
|
16
|
+
|
|
17
|
+
Check if PM2 is installed:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pm2 --version
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
If command not found, install globally:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g pm2
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Verify installation:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pm2 --version # should print version number
|
|
33
|
+
pm2 ping # should respond "pong"
|
|
34
|
+
```
|
|
35
|
+
|
|
15
36
|
## Pre-Start Check (MANDATORY)
|
|
16
37
|
|
|
17
38
|
Before starting any process, check what is already running:
|