gm-kilo 2.0.46 → 2.0.48

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.
@@ -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 "$PACKAGE@$VERSION already published - skipping"
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 "Published $PACKAGE@$VERSION"
60
+ echo "Published $PACKAGE@$VERSION"
36
61
  env:
37
62
  NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/.gitignore CHANGED
@@ -11,3 +11,6 @@ build/
11
11
  .vscode/
12
12
  .idea/
13
13
  *.iml
14
+ .gm-stop-verified
15
+
16
+ .code-search/
package/agents/gm.md CHANGED
@@ -225,6 +225,38 @@ Never report work complete while uncommitted changes exist. Never leave unpushed
225
225
 
226
226
  This policy applies to ALL platforms (Claude Code, Gemini CLI, OpenCode, Kilo CLI, Codex, and all IDE extensions). Platform-specific git enforcement hooks will verify compliance, but the responsibility lies with you to execute the commit and push before completion.
227
227
 
228
+ ## CHARTER 9: PROCESS MANAGEMENT
229
+
230
+ Scope: Runtime process execution. Governs how all applications are started, monitored, and cleaned up.
231
+
232
+ **ALL APPLICATIONS MUST RUN VIA PM2.** Direct invocations (node, bun, python, npx) are forbidden for any process that produces output or has a lifecycle. This applies to servers, workers, agents, and background services.
233
+
234
+ **PRE-START CHECK (MANDATORY)**: Before starting any process, execute `pm2 jlist`. If the process exists with `online` status: observe it with `pm2 logs <name>`. If `stopped`: restart it. Only start new if not found. Never create duplicate processes.
235
+
236
+ **Standard configuration** — all PM2 processes must use:
237
+ - `autorestart: false` — no crash recovery, explicit control only
238
+ - `watch: ["src", "config"]` — file-change restarts scoped to source directories
239
+ - `ignore_watch: ["node_modules", ".git", "logs", "*.log"]` — never watch these
240
+ - `watch_delay: 1000` — debounce rapid multi-file changes
241
+
242
+ **Cross-platform requirements**:
243
+ - Windows: cannot spawn `.cmd` shims — use `interpreter: "cmd", interpreter_args: "/c"` for npm scripts; resolve actual `.js` path for globally installed CLIs
244
+ - WSL watching `/mnt/c/...` paths: set `watch_options: { usePolling: true, interval: 1000 }`
245
+ - Windows 11+: `spawn wmic ENOENT` in daemon logs is cosmetic — app processes work; fix with `npm install -g pm2@latest`
246
+ - Linux watch exhaustion: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`
247
+
248
+ **Log monitoring**:
249
+ ```bash
250
+ pm2 logs <name> # stream live output
251
+ pm2 logs <name> --lines 100 # last N lines then stream
252
+ pm2 logs <name> --err # errors only
253
+ pm2 logs <name> --nostream --lines 200 # dump without follow
254
+ ```
255
+
256
+ **Lifecycle cleanup**: When work is complete, always run `pm2 delete <name>`. Never leave orphaned processes. `pm2 stop` on a watched process is not sufficient — use `pm2 delete`.
257
+
258
+ See `process-management` skill for full reference, ecosystem config templates, and Windows/Linux specifics.
259
+
228
260
  ## CONSTRAINTS
229
261
 
230
262
  Scope: Global prohibitions and mandates applying across all charters. Precedence cascade: CONSTRAINTS > charter-specific rules > prior habits or examples. When conflict arises, higher-precedence source wins and lower source must be revised.
@@ -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(2);
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.46",
3
+ "version": "2.0.48",
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
+ }
@@ -1,48 +1,54 @@
1
1
  ---
2
2
  name: dev
3
- description: Execute code and shell commands. Use for all code execution, file operations, running scripts, testing hypotheses, and any task that requires running code. Replaces plugin:gm:dev and mcp-glootie.
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
- Execute code directly using the Bash tool. No wrapper, no persistent files, no cleanup needed beyond what the code itself creates.
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
- ## File operations (inline, no temp files)
20
+ ```python
21
+ # File operations
22
+ import os, json
23
+ print(json.dumps(os.listdir('.')))
30
24
 
31
- ```bash
32
- # Read
33
- bun -e "console.log(require('fs').readFileSync('path/to/file', 'utf-8'))"
25
+ # Read a file
26
+ with open('package.json') as f:
27
+ print(f.read())
34
28
 
35
- # Write
36
- bun -e "require('fs').writeFileSync('out.json', JSON.stringify({x:1}, null, 2))"
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
- bun -e "const fs=require('fs'); console.log(fs.existsSync('file.txt'), fs.statSync?.('.')?.size)"
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 command
47
- - No spawn/exec/fork inside executed code
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
@@ -0,0 +1,187 @@
1
+ ---
2
+ name: process-management
3
+ description: >-
4
+ PM2 process management for all running applications. Enforces: pre-check for
5
+ running processes before start, watch enabled, autorestart disabled, lifecycle
6
+ cleanup when done. Use for all servers, workers, agents, background processes.
7
+ Triggers: start server, run application, background process, pm2, keep alive,
8
+ process manager, daemon, monitor logs.
9
+ ---
10
+
11
+ # Process Management — PM2
12
+
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
+
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
+
36
+ ## Pre-Start Check (MANDATORY)
37
+
38
+ Before starting any process, check what is already running:
39
+
40
+ ```bash
41
+ pm2 jlist
42
+ ```
43
+
44
+ - `online` → already running, use `pm2 logs <name>` to observe
45
+ - `stopped` → use `pm2 restart <name>`
46
+ - Not in list → proceed to start
47
+
48
+ Never start a duplicate process. Always check first.
49
+
50
+ ## Start a Process
51
+
52
+ ```bash
53
+ # CLI (quick)
54
+ pm2 start app.js --name myapp --watch --no-autorestart
55
+
56
+ # With interpreter
57
+ pm2 start script.py --interpreter python3 --name worker --watch --no-autorestart
58
+
59
+ # From ecosystem config (preferred for reproducibility)
60
+ pm2 start ecosystem.config.cjs
61
+ ```
62
+
63
+ ## Ecosystem Config (Standard Template)
64
+
65
+ `autorestart: false` — process stops on crash, no automatic recovery
66
+ `watch: true` — restarts on file changes in watched directories only
67
+
68
+ ```javascript
69
+ // ecosystem.config.cjs
70
+ module.exports = {
71
+ apps: [{
72
+ name: "myapp",
73
+ script: "src/index.js",
74
+ watch: ["src", "config"],
75
+ watch_delay: 1000,
76
+ autorestart: false,
77
+ ignore_watch: [
78
+ "node_modules",
79
+ ".git",
80
+ "logs",
81
+ "*.log",
82
+ ".pm2",
83
+ "public",
84
+ "uploads"
85
+ ],
86
+ watch_options: {
87
+ followSymlinks: false,
88
+ usePolling: false
89
+ },
90
+ log_date_format: "YYYY-MM-DD HH:mm:ss",
91
+ out_file: "./logs/out.log",
92
+ error_file: "./logs/error.log"
93
+ }]
94
+ };
95
+ ```
96
+
97
+ ## Log Viewing
98
+
99
+ ```bash
100
+ pm2 logs <name> # stream live (Ctrl+C to stop)
101
+ pm2 logs <name> --lines 100 # last 100 lines then stream
102
+ pm2 logs <name> --err # errors only
103
+ pm2 logs <name> --out # stdout only
104
+ pm2 logs <name> --nostream --lines 200 # dump without follow
105
+ pm2 logs --json # structured JSON output
106
+ pm2 flush # clear all log files
107
+ ```
108
+
109
+ Log files: `~/.pm2/logs/<name>-out.log` / `<name>-error.log`
110
+ Windows path: `C:\Users\<user>\.pm2\logs\`
111
+
112
+ ## Lifecycle Management
113
+
114
+ ```bash
115
+ pm2 list # view all processes and status
116
+ pm2 jlist # JSON output for scripting
117
+ pm2 info <name> # detailed process info
118
+ pm2 stop <name> # stop (keeps in list)
119
+ pm2 restart <name> # restart
120
+ pm2 delete <name> # stop + remove from list
121
+ pm2 delete all # remove all processes
122
+ pm2 ping # check if PM2 daemon is alive
123
+ ```
124
+
125
+ **When work is complete: always `pm2 delete <name>` to clean up orphaned processes.**
126
+
127
+ Stopping a watched process: `pm2 stop` while watch is active restarts on next file change.
128
+ To fully halt: `pm2 delete <name>` (removes it entirely).
129
+
130
+ ## Windows vs Linux
131
+
132
+ ### File Watching
133
+
134
+ | Environment | Config |
135
+ |---|---|
136
+ | Linux native | `usePolling: false` (inotify kernel events) |
137
+ | WSL watching `/mnt/c/...` | `usePolling: true, interval: 1000` |
138
+ | Windows native | `usePolling: false` (ReadDirectoryChangesW) |
139
+ | Network / NFS / Docker volumes | `usePolling: true, interval: 1000` |
140
+
141
+ Linux inotify exhaustion fix (symptom: watch silently stops working):
142
+ ```bash
143
+ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
144
+ ```
145
+
146
+ ### Windows: npm Scripts and .cmd Wrappers
147
+
148
+ PM2 cannot spawn `.cmd` shims (npm, npx, etc.) directly — they require `cmd.exe`.
149
+
150
+ ```javascript
151
+ // ecosystem.config.cjs — Windows npm script
152
+ {
153
+ name: "myapp",
154
+ script: "npm",
155
+ args: "start",
156
+ interpreter: "cmd",
157
+ interpreter_args: "/c"
158
+ }
159
+ ```
160
+
161
+ For globally installed CLIs, find the real `.js` entry point:
162
+ ```bash
163
+ # Linux/macOS
164
+ cat "$(which myapp)" | head -5
165
+
166
+ # Windows PowerShell
167
+ Get-Command myapp | Select-Object -ExpandProperty Source
168
+ ```
169
+ Point `script` at the resolved `.js` file — never at the `.cmd` wrapper.
170
+
171
+ ### Windows 11+ wmic Error
172
+
173
+ PM2 uses `wmic` for process stats — removed in Windows 11+.
174
+ Symptom: `Error: spawn wmic ENOENT` in `~/.pm2/pm2.log`.
175
+ Fix: `npm install -g pm2@latest`. App processes continue working despite the error.
176
+
177
+ ### Persistence on Reboot
178
+
179
+ | Platform | Method |
180
+ |---|---|
181
+ | Linux | `pm2 startup && pm2 save` (auto-detects systemd/upstart/openrc) |
182
+ | Windows | [pm2-installer](https://github.com/jessety/pm2-installer) (Windows Service) |
183
+
184
+ ```bash
185
+ pm2 save # snapshot current process list to ~/.pm2/dump.pm2
186
+ pm2 resurrect # restore saved list after manual daemon restart
187
+ ```