gm-hermes 2.0.515
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/AGENTS.md +11 -0
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/cli.js +37 -0
- package/hermes-skill.json +9 -0
- package/index.html +54 -0
- package/package.json +33 -0
- package/skills/software-development/browser/SKILL.md +202 -0
- package/skills/software-development/code-search/SKILL.md +69 -0
- package/skills/software-development/create-lang-plugin/SKILL.md +183 -0
- package/skills/software-development/gm/SKILL.md +28 -0
- package/skills/software-development/gm-complete/SKILL.md +185 -0
- package/skills/software-development/gm-emit/SKILL.md +126 -0
- package/skills/software-development/gm-execute/SKILL.md +159 -0
- package/skills/software-development/pages/SKILL.md +258 -0
- package/skills/software-development/planning/SKILL.md +177 -0
- package/skills/software-development/ssh/SKILL.md +89 -0
- package/skills/software-development/update-docs/SKILL.md +113 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pages
|
|
3
|
+
description: Scaffold and maintain a GitHub Pages site. Buildless in browser (webjsx + rippleui via CDN), flatspace for content aggregation built during GH Actions. Use when user wants to create or update a GH Pages site.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pages — GitHub Pages Site Scaffolder
|
|
7
|
+
|
|
8
|
+
Scaffold a complete GH Pages site: **no local build step**, content managed via flatspace flat-file CMS, UI via webjsx + rippleui CDN, GH Actions builds and deploys.
|
|
9
|
+
|
|
10
|
+
**Follow full gm skill chain: planning → gm-execute → gm-emit → gm-complete → update-docs.**
|
|
11
|
+
|
|
12
|
+
## Stack
|
|
13
|
+
|
|
14
|
+
| Layer | Tool | How |
|
|
15
|
+
|-------|------|-----|
|
|
16
|
+
| UI rendering | [webjsx](https://webjsx.org) | ES module via importmap, `applyDiff` for DOM updates |
|
|
17
|
+
| Styling | [rippleui](https://ripple-ui.com) | CDN `<link>` — Tailwind-based component classes |
|
|
18
|
+
| Content CMS | [flatspace](https://npmjs.com/package/flatspace) | Aggregates `content/` → `docs/data/*.json` at build time |
|
|
19
|
+
| Build | GH Actions | `npx flatspace` runs in CI, commits output to `docs/` |
|
|
20
|
+
| Hosting | GitHub Pages | Source: `docs/` branch, or GH Actions deploy |
|
|
21
|
+
|
|
22
|
+
## Directory Layout
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
<project>/
|
|
26
|
+
content/ # Source content (markdown, json, yaml)
|
|
27
|
+
pages/ # Static pages (index.md, about.md, ...)
|
|
28
|
+
posts/ # Blog posts or articles
|
|
29
|
+
data/ # Structured data files
|
|
30
|
+
docs/ # GH Pages root (gitignored build output except index.html)
|
|
31
|
+
index.html # Entry point — committed, never regenerated
|
|
32
|
+
app.js # Main webjsx app — committed
|
|
33
|
+
data/ # flatspace output — gitignored, built by CI
|
|
34
|
+
.github/
|
|
35
|
+
workflows/
|
|
36
|
+
pages.yml # Build + deploy workflow
|
|
37
|
+
flatspace.config.js # flatspace aggregation config
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## index.html — Buildless Entry
|
|
41
|
+
|
|
42
|
+
```html
|
|
43
|
+
<!DOCTYPE html>
|
|
44
|
+
<html lang="en">
|
|
45
|
+
<head>
|
|
46
|
+
<meta charset="UTF-8">
|
|
47
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
48
|
+
<title>{{SITE_TITLE}}</title>
|
|
49
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rippleui@1.12.1/dist/css/styles.css">
|
|
50
|
+
<script type="importmap">
|
|
51
|
+
{
|
|
52
|
+
"imports": {
|
|
53
|
+
"webjsx": "https://cdn.jsdelivr.net/npm/webjsx@0.0.42/dist/index.js",
|
|
54
|
+
"webjsx/jsx-runtime": "https://cdn.jsdelivr.net/npm/webjsx@0.0.42/dist/jsx-runtime.js"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
</script>
|
|
58
|
+
<script type="module" src="./app.js"></script>
|
|
59
|
+
</head>
|
|
60
|
+
<body class="bg-backgroundPrimary text-content1 min-h-screen">
|
|
61
|
+
<div id="root"></div>
|
|
62
|
+
</body>
|
|
63
|
+
</html>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## app.js — webjsx App Pattern
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
import { applyDiff } from 'webjsx';
|
|
70
|
+
|
|
71
|
+
const h = (tag, props, ...children) => ({ tag, props: props || {}, children });
|
|
72
|
+
|
|
73
|
+
const state = { page: null, data: {} };
|
|
74
|
+
|
|
75
|
+
async function loadData(path) {
|
|
76
|
+
const res = await fetch(path);
|
|
77
|
+
return res.json();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function render() {
|
|
81
|
+
applyDiff(document.getElementById('root'), App(state));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function App(s) {
|
|
85
|
+
if (!s.page) return h('div', { class: 'flex justify-center p-8' },
|
|
86
|
+
h('span', { class: 'spinner' })
|
|
87
|
+
);
|
|
88
|
+
return h('div', { class: 'max-w-4xl mx-auto p-4' },
|
|
89
|
+
h('nav', { class: 'navbar bg-backgroundSecondary mb-6' },
|
|
90
|
+
h('span', { class: 'navbar-brand text-xl font-bold' }, s.page.title)
|
|
91
|
+
),
|
|
92
|
+
h('main', {}, ...s.page.sections.map(Section))
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function Section(section) {
|
|
97
|
+
return h('section', { class: 'card mb-4 p-6' },
|
|
98
|
+
h('h2', { class: 'text-2xl font-bold mb-2' }, section.title),
|
|
99
|
+
h('p', { class: 'text-content2' }, section.body)
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function main() {
|
|
104
|
+
state.page = await loadData('./data/index.json');
|
|
105
|
+
render();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
main();
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## flatspace.config.js
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
module.exports = {
|
|
115
|
+
input: './content',
|
|
116
|
+
output: './docs/data',
|
|
117
|
+
collections: {
|
|
118
|
+
pages: { dir: 'pages', format: 'markdown' },
|
|
119
|
+
posts: { dir: 'posts', format: 'markdown', sortBy: 'date', order: 'desc' },
|
|
120
|
+
data: { dir: 'data', format: 'json' }
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## GH Actions Workflow — pages.yml
|
|
126
|
+
|
|
127
|
+
```yaml
|
|
128
|
+
name: Deploy GitHub Pages
|
|
129
|
+
|
|
130
|
+
on:
|
|
131
|
+
push:
|
|
132
|
+
branches: [main]
|
|
133
|
+
workflow_dispatch:
|
|
134
|
+
|
|
135
|
+
permissions:
|
|
136
|
+
contents: write
|
|
137
|
+
pages: write
|
|
138
|
+
id-token: write
|
|
139
|
+
|
|
140
|
+
jobs:
|
|
141
|
+
build:
|
|
142
|
+
runs-on: ubuntu-latest
|
|
143
|
+
steps:
|
|
144
|
+
- uses: actions/checkout@v4
|
|
145
|
+
|
|
146
|
+
- uses: actions/setup-node@v4
|
|
147
|
+
with:
|
|
148
|
+
node-version: '20'
|
|
149
|
+
|
|
150
|
+
- name: Build content with flatspace
|
|
151
|
+
run: npx flatspace
|
|
152
|
+
|
|
153
|
+
- name: Commit built data
|
|
154
|
+
run: |
|
|
155
|
+
git config user.name "github-actions[bot]"
|
|
156
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
157
|
+
git add docs/data/
|
|
158
|
+
git diff --staged --quiet || git commit -m "chore: build content [skip ci]"
|
|
159
|
+
git push
|
|
160
|
+
|
|
161
|
+
- name: Upload Pages artifact
|
|
162
|
+
uses: actions/upload-pages-artifact@v3
|
|
163
|
+
with:
|
|
164
|
+
path: docs/
|
|
165
|
+
|
|
166
|
+
deploy:
|
|
167
|
+
needs: build
|
|
168
|
+
runs-on: ubuntu-latest
|
|
169
|
+
environment:
|
|
170
|
+
name: github-pages
|
|
171
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
172
|
+
steps:
|
|
173
|
+
- id: deployment
|
|
174
|
+
uses: actions/deploy-pages@v4
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Scaffolding Steps
|
|
178
|
+
|
|
179
|
+
When user says "set up pages" or "create GH pages site":
|
|
180
|
+
|
|
181
|
+
1. **Read** existing `docs/` and `content/` if present — never clobber existing content
|
|
182
|
+
2. **Create** directory structure above
|
|
183
|
+
3. **Write** `docs/index.html` with correct site title
|
|
184
|
+
4. **Write** `docs/app.js` with webjsx app skeleton
|
|
185
|
+
5. **Write** `flatspace.config.js`
|
|
186
|
+
6. **Write** `.github/workflows/pages.yml`
|
|
187
|
+
7. **Write** `content/pages/index.md` with minimal frontmatter (`title`, `sections` array)
|
|
188
|
+
8. **Add** `docs/data/` to `.gitignore` (built by CI, not committed by humans)
|
|
189
|
+
9. **Verify** GH Pages setting is "GitHub Actions" in repo Settings — remind user if can't verify
|
|
190
|
+
|
|
191
|
+
## rippleui Component Classes Quick Reference
|
|
192
|
+
|
|
193
|
+
Use these directly in JSX className strings — no config needed:
|
|
194
|
+
|
|
195
|
+
| Component | Class |
|
|
196
|
+
|-----------|-------|
|
|
197
|
+
| Button | `btn btn-primary`, `btn btn-secondary`, `btn btn-ghost` |
|
|
198
|
+
| Card | `card p-4` |
|
|
199
|
+
| Input | `input input-primary` |
|
|
200
|
+
| Navbar | `navbar` + `navbar-brand` |
|
|
201
|
+
| Badge | `badge badge-primary` |
|
|
202
|
+
| Alert | `alert alert-success`, `alert alert-error` |
|
|
203
|
+
| Spinner | `spinner` |
|
|
204
|
+
| Divider | `divider` |
|
|
205
|
+
|
|
206
|
+
Background: `bg-backgroundPrimary`, `bg-backgroundSecondary`. Text: `text-content1`, `text-content2`.
|
|
207
|
+
|
|
208
|
+
**CSS variable warning**: rippleui color vars (e.g. `--gray-2`) are raw space-separated RGB tuples — not valid CSS colors. Never use them in `rgb()` directly from JS. Use the component classes instead.
|
|
209
|
+
|
|
210
|
+
## webjsx Patterns
|
|
211
|
+
|
|
212
|
+
**No JSX transpile needed** — use `h()` factory or import from CDN with importmap and write JSX in `.jsx` files served directly (Chrome supports importmap natively).
|
|
213
|
+
|
|
214
|
+
For `.js` files without transpile, use the `h` factory pattern shown above.
|
|
215
|
+
|
|
216
|
+
For `.jsx` with native importmap (no build):
|
|
217
|
+
```js
|
|
218
|
+
/** @jsxImportSource webjsx */
|
|
219
|
+
import { applyDiff } from 'webjsx';
|
|
220
|
+
```
|
|
221
|
+
Only works if server sets correct MIME type for `.jsx` — GH Pages does not. Use `.js` + `h()` factory.
|
|
222
|
+
|
|
223
|
+
**applyDiff signature**: `applyDiff(domNode, vnodeOrArray)` — never pass a string, always pass a vnode from `h()`.
|
|
224
|
+
|
|
225
|
+
**State updates**: mutate `state`, call `render()` — no reactive system, explicit re-render on every change.
|
|
226
|
+
|
|
227
|
+
## Content Format (flatspace input)
|
|
228
|
+
|
|
229
|
+
Markdown with YAML frontmatter:
|
|
230
|
+
```markdown
|
|
231
|
+
---
|
|
232
|
+
title: Home
|
|
233
|
+
sections:
|
|
234
|
+
- title: Welcome
|
|
235
|
+
body: Hello world
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
# Home
|
|
239
|
+
|
|
240
|
+
Full markdown body here.
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
flatspace outputs `docs/data/pages/index.json`:
|
|
244
|
+
```json
|
|
245
|
+
{ "title": "Home", "sections": [...], "body": "<p>Full markdown body here.</p>", "slug": "index" }
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Known Gotchas
|
|
249
|
+
|
|
250
|
+
**GH Pages must be set to "GitHub Actions"** in Settings → Pages. "Deploy from branch" ignores the deploy-pages action entirely.
|
|
251
|
+
|
|
252
|
+
**docs/data/ must be in .gitignore** but `docs/index.html` and `docs/app.js` must NOT be ignored — they are the committed source files.
|
|
253
|
+
|
|
254
|
+
**flatspace npx cold start**: first CI run downloads flatspace — takes ~10s extra. Subsequent runs use cache if `actions/setup-node` cache is configured.
|
|
255
|
+
|
|
256
|
+
**importmap browser support**: all modern browsers support importmap. No IE, no Safari < 16.4. For GH Pages this is fine.
|
|
257
|
+
|
|
258
|
+
**webjsx CDN version**: pin to explicit version in importmap (e.g. `@0.0.42`) — avoid `@latest` to prevent silent breakage on upstream updates.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: planning
|
|
3
|
+
description: State machine orchestrator. Mutable discovery, PRD construction, and full PLAN→EXECUTE→EMIT→VERIFY→COMPLETE lifecycle. Invoke at session start and on any new unknown.
|
|
4
|
+
allowed-tools: Write
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Planning — State Machine Orchestrator
|
|
8
|
+
|
|
9
|
+
Root of all work. Runs `PLAN → EXECUTE → EMIT → VERIFY → UPDATE-DOCS → COMPLETE`.
|
|
10
|
+
|
|
11
|
+
**Entry**: prompt-submit hook → `gm` agent → invoke `planning` skill (here). Also re-entered any time a new unknown surfaces in any phase.
|
|
12
|
+
|
|
13
|
+
## STATE MACHINE
|
|
14
|
+
|
|
15
|
+
**FORWARD**: PLAN complete → `gm-execute` | EXECUTE complete → `gm-emit` | EMIT complete → `gm-complete` | VERIFY .prd remains → `gm-execute` | VERIFY .prd empty+pushed → `update-docs`
|
|
16
|
+
|
|
17
|
+
**REGRESSIONS**: new unknown at any state → re-invoke `planning` | EXECUTE unresolvable 2 passes → `planning` | EMIT logic error → `gm-execute` | EMIT new unknown → `planning` | VERIFY broken output → `gm-emit` | VERIFY logic wrong → `gm-execute` | VERIFY new unknown → `planning`
|
|
18
|
+
|
|
19
|
+
**Runs until**: .gm/prd.yml empty AND git clean AND all pushes confirmed AND CI green.
|
|
20
|
+
|
|
21
|
+
## ENFORCEMENT — COMPLETE EVERY TASK END-TO-END
|
|
22
|
+
|
|
23
|
+
**Cannot respond or stop while**:
|
|
24
|
+
- .gm/prd.yml exists and has items
|
|
25
|
+
- git has uncommitted changes
|
|
26
|
+
- git has unpushed commits
|
|
27
|
+
|
|
28
|
+
The skill chain MUST be followed completely end-to-end without exception. Partial execution = violation. After every phase: read .prd, check git, invoke next skill.
|
|
29
|
+
|
|
30
|
+
## PLAN PHASE — MUTABLE DISCOVERY
|
|
31
|
+
|
|
32
|
+
Planning = exhaustive fault-surface enumeration. For every aspect of the task:
|
|
33
|
+
- What do I not know? → mutable (UNKNOWN)
|
|
34
|
+
- What could go wrong? → edge case item with failure mode
|
|
35
|
+
- What depends on what? → blocking/blockedBy mapped explicitly
|
|
36
|
+
- What assumptions am I making? → each = unwitnessed hypothesis = mutable until execution proves it
|
|
37
|
+
|
|
38
|
+
**Fault surfaces**: file existence | API shape | data format | dependency versions | runtime behavior | environment differences | error conditions | concurrency hazards | integration seams | backwards compatibility | rollback paths | deployment steps | CI/CD correctness
|
|
39
|
+
|
|
40
|
+
**MANDATORY CODEBASE SCAN**: For every planned item, add `existingImpl=UNKNOWN`. Resolve via exec:codesearch. Existing code serving same concern → consolidation task, not addition. `exec:codesearch` indexes PDFs page-by-page alongside source — spec PDFs, papers, vendor manuals, and RFCs are searchable as code. When planning against a protocol, hardware, or compliance requirement, search the PDF corpus the same way you search source: two words, iterate. A constraint the PRD is missing because it only lives in a PDF is a fault surface — enumerate doc PDFs as scan targets during mutable discovery.
|
|
41
|
+
|
|
42
|
+
**EXIT PLAN**: zero new unknowns in last pass AND all .prd items have explicit acceptance criteria AND all dependencies mapped → launch subagents or invoke `gm-execute`.
|
|
43
|
+
|
|
44
|
+
**SELF-LOOP**: new items discovered → add to .prd → plan again.
|
|
45
|
+
|
|
46
|
+
**Skip planning entirely** (this is the DEFAULT for small work) if ANY of these apply:
|
|
47
|
+
- Single-file, single-concern edit
|
|
48
|
+
- Task is trivially bounded and under ~5 minutes
|
|
49
|
+
- User gave explicit surgical instructions ("change X to Y")
|
|
50
|
+
- Bug fix where root cause is already identified
|
|
51
|
+
- Zero unknowns / no mutables to resolve
|
|
52
|
+
|
|
53
|
+
Heavy ceremony (PRD + parallel subagents) is for multi-file architectural work or genuinely unknown fault surfaces. Writing a 7-item PRD for a 3-line change is waste. Err toward skipping — if a new unknown surfaces mid-work, THAT is when you regress to planning, not preemptively.
|
|
54
|
+
|
|
55
|
+
**Contrast examples:**
|
|
56
|
+
- "Fix the hold-detect logic at apcKey25.cpp:163" → SKIP planning. Read, edit, done.
|
|
57
|
+
- "Add drift correction and watchdog and observability across the USB audio path" → DO plan. Multi-file, multiple unknowns.
|
|
58
|
+
|
|
59
|
+
## OBSERVABILITY ENUMERATION — MANDATORY EVERY PASS
|
|
60
|
+
|
|
61
|
+
During every planning pass, enumerate every possible aspect of the app's runtime observability that can be improved. The goal is permanent structures — not ad-hoc logs — that make any future debugging session start from a complete, live picture of system state.
|
|
62
|
+
|
|
63
|
+
**Server-side permanent structures**: Every internal subsystem — state machine, queue, cache, connection pool, active task map, process registry, RPC handler, hook dispatcher — must expose a named, queryable inspection endpoint (e.g. `/debug/<subsystem>`). State must be readable, filterable, and ideally modifiable without restart. Profiling hooks on every hot path. Structured logs with subsystem tag, severity, and timestamp — filterable at runtime by subsystem, not just log level. Any internal state that requires a restart to inspect is an observability gap.
|
|
64
|
+
|
|
65
|
+
**Client-side permanent structures**: `window.__debug` must be a live, structured registry — not a dump. Every component's state, every active request, every event queue, every WebSocket connection, every rendered prop, every error boundary — all addressable by key, all queryable without refreshing. New modules register themselves into `window.__debug` on mount and deregister on unmount. Any execution path not traceable via `window.__debug` is an observability gap.
|
|
66
|
+
|
|
67
|
+
**Permanent vs ad-hoc**: `console.log` = ad-hoc = not observability. A structured logger with subsystem routing = permanent. `window.__debug.myModule.state` = permanent. `window.__debug = { ...window.__debug, tmp: x }` = ad-hoc = not acceptable. Permanent structures survive deploys and accumulate diagnostic value across sessions.
|
|
68
|
+
|
|
69
|
+
**Mandate**: on discovery of any observability gap → immediately add a .prd item. Observability improvements are highest-priority — never deferred. The agent must be able to see specifically anything it wants and nothing else — no guessing, no blind spots.
|
|
70
|
+
|
|
71
|
+
## .PRD FORMAT
|
|
72
|
+
|
|
73
|
+
Path: `./.gm/prd.yml`. YAML via `exec:nodejs` (use `fs.writeFileSync`). Ensure `.gm/` dir exists before writing. Delete when empty — never leave empty file. Delete `.gm/` dir when completely empty.
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
- id: kebab-id
|
|
77
|
+
subject: Imperative verb phrase
|
|
78
|
+
status: pending
|
|
79
|
+
description: Precise criterion
|
|
80
|
+
effort: small|medium|large
|
|
81
|
+
category: feature|bug|refactor|infra
|
|
82
|
+
blocking: []
|
|
83
|
+
blockedBy: []
|
|
84
|
+
acceptance:
|
|
85
|
+
- binary criterion
|
|
86
|
+
edge_cases:
|
|
87
|
+
- failure mode
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Status: `pending` → `in_progress` → `completed` (remove completed items). Effort: small <15min | medium <45min | large >1h.
|
|
91
|
+
|
|
92
|
+
## PARALLEL SUBAGENT LAUNCH
|
|
93
|
+
|
|
94
|
+
After .prd written, launch ≤3 parallel `gm:gm` subagents for all independent items simultaneously. Never sequential.
|
|
95
|
+
|
|
96
|
+
`Agent(subagent_type="gm:gm", prompt="Work on .prd item: <id>. .prd path: <path>. Item: <full YAML>.")`
|
|
97
|
+
|
|
98
|
+
After each wave: read .prd, find newly unblocked items, launch next wave. Exception: browser tasks serialize.
|
|
99
|
+
|
|
100
|
+
When parallelism not applicable: invoke `gm-execute` skill directly.
|
|
101
|
+
|
|
102
|
+
## MUTABLE DISCIPLINE
|
|
103
|
+
|
|
104
|
+
Each mutable: name | expected | current | resolution method. Resolve by witnessed execution only. Zero variance = resolved. Unresolved after 2 passes = new unknown = re-invoke `planning`. Mutables live in conversation only.
|
|
105
|
+
|
|
106
|
+
## CODE EXECUTION
|
|
107
|
+
|
|
108
|
+
`exec:<lang>` only. Bash body: `exec:<lang>\n<code>`
|
|
109
|
+
|
|
110
|
+
`exec:nodejs` | `exec:bash` | `exec:python` | `exec:typescript` | `exec:go` | `exec:rust` | `exec:c` | `exec:cpp` | `exec:java` | `exec:deno` | `exec:cmd`
|
|
111
|
+
|
|
112
|
+
File I/O: exec:nodejs + require('fs'). Git only in Bash directly. `Bash(node/npm/npx/bun)` = violation.
|
|
113
|
+
|
|
114
|
+
Pack runs: `Promise.allSettled` for parallel ops. Each idea its own try/catch. Under 12s per call.
|
|
115
|
+
|
|
116
|
+
Background: `exec:sleep <id>` | `exec:status <id>` | `exec:close <id>`. Runner: `exec:runner start|stop|status`.
|
|
117
|
+
|
|
118
|
+
## CODEBASE EXPLORATION
|
|
119
|
+
|
|
120
|
+
`exec:codesearch` only. Glob/Grep/Read/Explore/WebSearch = hook-blocked. Start 2 words → change one word → add third → minimum 4 attempts before concluding absent.
|
|
121
|
+
|
|
122
|
+
## BROWSER AUTOMATION
|
|
123
|
+
|
|
124
|
+
Invoke `browser` skill. Escalation: (1) `exec:browser <js>` → (2) browser skill → (3) navigate/click → (4) screenshot last resort. Browser tasks serialize — one Chrome instance per project.
|
|
125
|
+
|
|
126
|
+
## SKILL REGISTRY
|
|
127
|
+
|
|
128
|
+
`gm-execute` → `gm-emit` → `gm-complete` → `update-docs` | `browser` | `memorize` (sub-agent, background only)
|
|
129
|
+
|
|
130
|
+
`memorize`: `Agent(subagent_type='memorize', model='haiku', run_in_background=true, prompt='## CONTEXT TO MEMORIZE\n<what>')`
|
|
131
|
+
|
|
132
|
+
## MANDATORY DEV WORKFLOW
|
|
133
|
+
|
|
134
|
+
No comments. No scattered test files. 200-line limit — split before continuing. Fail loud. No duplication. Scan before every edit. Duplicate concern = regress to PLAN. Errors throw with context — no `|| default`, no `catch { return null }`. `window.__debug` exposes all client state. AGENTS.md via memorize only. CHANGELOG.md: append per commit.
|
|
135
|
+
|
|
136
|
+
**Minimal code / maximal DX process**: Before writing any logic, run this process in order — stop at the first step that resolves the need:
|
|
137
|
+
1. **Native first** — does the language or runtime already do this? Use it exactly as designed.
|
|
138
|
+
2. **Library second** — does an existing dependency already solve this pattern? Use its API directly.
|
|
139
|
+
3. **Structure third** — can the problem be encoded as data (map, table, pipeline) so the structure enforces correctness and eliminates branching entirely?
|
|
140
|
+
4. **Write last** — only author new logic when the above three are exhausted. New logic = new surface area = new bugs.
|
|
141
|
+
|
|
142
|
+
When structure eliminates a whole class of wrong states — name that pattern explicitly. Dispatch tables replacing switch chains, pipelines replacing loop-with-accumulator, maps replacing if/else forests — these are not just style preferences, they are correctness properties. Code that cannot be wrong because of how it is shaped is the goal. Readable top-to-bottom without mental simulation = done right. Requires decoding = not done.
|
|
143
|
+
|
|
144
|
+
## SINGLE INTEGRATION TEST POLICY
|
|
145
|
+
|
|
146
|
+
Every project maintains exactly one `test.js` at project root. 200-line max. No other test files anywhere — no `.test.js`, `.spec.js`, `__tests__/`, `fixtures/`, `mocks/`. Delete all scattered tests on discovery and consolidate coverage into `test.js`.
|
|
147
|
+
|
|
148
|
+
**test.js replaces all unit tests.** It tests the real system end-to-end with real data. No mocks, no stubs, no test frameworks. Plain node assertions or process exit codes.
|
|
149
|
+
|
|
150
|
+
**Creation**: if `test.js` does not exist, create it during EXECUTE phase covering all testable surface of current work.
|
|
151
|
+
|
|
152
|
+
**Maintenance**: every code change that adds or modifies behavior must update `test.js` to cover it. Every bug fix must add a regression case that would have caught the bug.
|
|
153
|
+
|
|
154
|
+
**Structure**: group by subsystem, each subsystem gets a section. When approaching 200 lines, compress older stable tests into tighter assertions to make room for new coverage.
|
|
155
|
+
|
|
156
|
+
**Execution**: `gm-complete` runs `test.js` before allowing completion. Failure = regression to EXECUTE.
|
|
157
|
+
|
|
158
|
+
## RESPONSE POLICY
|
|
159
|
+
|
|
160
|
+
Terse like smart caveman. Technical substance stays. Fluff dies. Default: **full**. Switch: `/caveman lite|full|ultra`.
|
|
161
|
+
|
|
162
|
+
Drop: articles, filler, pleasantries, hedging. Fragments OK. Short synonyms. Technical terms exact. Code unchanged. Pattern: `[thing] [action] [reason]. [next step].`
|
|
163
|
+
|
|
164
|
+
Levels: **lite** = no filler, full sentences | **full** = drop articles, fragments OK | **ultra** = abbreviate all, arrows for causality | **wenyan-full** = 文言文, 80-90% compression | **wenyan-ultra** = max classical terse.
|
|
165
|
+
|
|
166
|
+
Auto-Clarity: drop caveman for security warnings, irreversible confirmations, ambiguous sequences. Resume after. Code/commits/PRs write normal. "stop caveman" / "normal mode": revert.
|
|
167
|
+
|
|
168
|
+
## CONSTRAINTS
|
|
169
|
+
|
|
170
|
+
**Tier 0**: no_crash, no_exit, ground_truth_only, real_execution, fail_loud
|
|
171
|
+
**Tier 1**: max_file_lines=200, hot_reloadable, checkpoint_state
|
|
172
|
+
**Tier 2**: no_duplication, no_hardcoded_values, modularity
|
|
173
|
+
**Tier 3**: no_comments, convention_over_code
|
|
174
|
+
|
|
175
|
+
**Never**: `Bash(node/npm/npx/bun)` | skip planning | partial execution | stop while .gm/prd.yml has items | stop while git dirty | sequential independent items | screenshot before JS exhausted | fallback/demo modes | silently swallow errors | duplicate concern | leave comments | create scattered test files (only root test.js) | write if/else chains where a map or pipeline suffices | write one-liners that require decoding | branch on enumerated cases when a dispatch table exists
|
|
176
|
+
|
|
177
|
+
**Always**: invoke named skill at every state transition | regress to planning on any new unknown | witnessed execution only | scan codebase before edits | enumerate every possible observability improvement every planning pass | follow skill chain completely end-to-end on every task without exception | prefer dispatch tables over switch/if chains | prefer pipelines over loop-with-accumulator | make wrong states structurally impossible | name patterns when structure eliminates a whole class of bugs
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ssh
|
|
3
|
+
description: Run shell commands on remote SSH hosts via exec:ssh. Reads targets from ~/.claude/ssh-targets.json. Use for deploying, monitoring, or controlling remote machines.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# exec:ssh — Remote SSH Execution
|
|
7
|
+
|
|
8
|
+
**Use gm subagents for all independent work items. Invoke all skills in the chain: planning → gm-execute → gm-emit → gm-complete → update-docs.**
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
Runs shell commands on a remote host over SSH. No shell open, no manual connection — just write the command.
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
Create `~/.claude/ssh-targets.json`:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"default": {
|
|
20
|
+
"host": "192.168.1.10",
|
|
21
|
+
"port": 22,
|
|
22
|
+
"username": "pi",
|
|
23
|
+
"password": "yourpassword"
|
|
24
|
+
},
|
|
25
|
+
"prod": {
|
|
26
|
+
"host": "10.0.0.1",
|
|
27
|
+
"username": "ubuntu",
|
|
28
|
+
"keyPath": "/home/user/.ssh/id_rsa"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Fields: `host` (required), `port` (default 22), `username` (required), `password` OR `keyPath` + optional `passphrase`.
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
exec:ssh
|
|
39
|
+
<shell command>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Target a named host with `@name` on the first line:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
exec:ssh
|
|
46
|
+
@prod
|
|
47
|
+
sudo systemctl restart myapp
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Multi-line scripts work:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
exec:ssh
|
|
54
|
+
cd /var/log && tail -20 syslog
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Process Persistence
|
|
58
|
+
|
|
59
|
+
SSH sessions kill child processes on close. To keep a process running after the command returns:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
exec:ssh
|
|
63
|
+
sudo systemctl reset-failed myunit 2>/dev/null; systemd-run --unit=myunit bash -c 'your-long-running-command'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Always call `systemctl reset-failed <unit>` before reusing a unit name, or use a unique timestamped name:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
exec:ssh
|
|
70
|
+
systemd-run --unit=job-$(date +%s) bash -c 'nohup myprogram &'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Fallback if systemd unavailable:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
exec:ssh
|
|
77
|
+
setsid nohup bash -c 'myprogram > /tmp/out.log 2>&1' &
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Dependency
|
|
81
|
+
|
|
82
|
+
Requires `ssh2` npm package. Install in `~/.claude/gm-tools`:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
exec:bash
|
|
86
|
+
cd ~/.claude/gm-tools && npm install ssh2
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The plugin searches: `~/.claude/gm-tools/node_modules/ssh2`, `~/.claude/plugins/node_modules/ssh2`, then global.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: update-docs
|
|
3
|
+
description: UPDATE-DOCS phase. Refresh README.md, AGENTS.md, and docs/index.html to reflect changes made this session. Commits and pushes doc updates. Terminal phase — declares COMPLETE.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GM UPDATE-DOCS — Documentation Refresh
|
|
7
|
+
|
|
8
|
+
You are in the **UPDATE-DOCS** phase. Feature work is verified and pushed. Refresh all documentation to match the actual codebase state right now.
|
|
9
|
+
|
|
10
|
+
**GRAPH POSITION**: `PLAN → EXECUTE → EMIT → VERIFY → [UPDATE-DOCS] → COMPLETE`
|
|
11
|
+
- **Entry**: Feature work verified, committed, and pushed. Entered from `gm-complete`.
|
|
12
|
+
|
|
13
|
+
## TRANSITIONS
|
|
14
|
+
|
|
15
|
+
**FORWARD**: All docs updated, committed, and pushed → COMPLETE (session ends)
|
|
16
|
+
|
|
17
|
+
**BACKWARD**:
|
|
18
|
+
- Diff reveals unknown architecture change → invoke `planning` skill, restart chain
|
|
19
|
+
- Doc write fails post-emit verify → fix and re-verify before advancing
|
|
20
|
+
|
|
21
|
+
## EXECUTION SEQUENCE
|
|
22
|
+
|
|
23
|
+
**Step 1 — Understand what changed**:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
exec:bash
|
|
27
|
+
git log -5 --oneline
|
|
28
|
+
git diff HEAD~1 --stat
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Witness which files changed. Identify doc-sensitive changes: new skills, new states in the state machine, new platforms, modified architecture, new constraints, renamed files.
|
|
32
|
+
|
|
33
|
+
**Step 2 — Read current docs**:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
exec:nodejs
|
|
37
|
+
const fs = require('fs');
|
|
38
|
+
['README.md', 'AGENTS.md', 'docs/index.html',
|
|
39
|
+
'gm-starter/agents/gm.md'].forEach(f => {
|
|
40
|
+
try { console.log(`=== ${f} ===\n` + fs.readFileSync(f, 'utf8')); }
|
|
41
|
+
catch(e) { console.log(`MISSING: ${f}`); }
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Identify every section that no longer matches the actual codebase state.
|
|
46
|
+
|
|
47
|
+
**Step 3 — Write updated docs**:
|
|
48
|
+
|
|
49
|
+
Write only sections that changed. Do not rewrite unchanged content. Rules per file:
|
|
50
|
+
|
|
51
|
+
**README.md**: platform count matches adapters in `platforms/`, skill tree diagram matches current state machine, quick start commands work.
|
|
52
|
+
|
|
53
|
+
**AGENTS.md**: Launch memorize sub-agent in background with session learnings. Do not inline-edit AGENTS.md — the memorize agent handles extraction, deduplication, and writing. Use: `Agent(subagent_type='memorize', model='haiku', run_in_background=true, prompt='## CONTEXT TO MEMORIZE\n<session learnings>')`
|
|
54
|
+
|
|
55
|
+
**docs/index.html**: `PHASES` array matches current skill state machine phases. Platform lists match `platforms/` directory. State machine diagram updated if new phases added.
|
|
56
|
+
|
|
57
|
+
**gm-starter/agents/gm.md**: Skill chain on the `gm skill →` line updated if new skills were added.
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
exec:nodejs
|
|
61
|
+
const fs = require('fs');
|
|
62
|
+
fs.writeFileSync('/abs/path/file.md', updatedContent);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Step 4 — Verify from disk**:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
exec:nodejs
|
|
69
|
+
const fs = require('fs');
|
|
70
|
+
const content = fs.readFileSync('/abs/path/file.md', 'utf8');
|
|
71
|
+
console.log(content.includes('expectedString'), content.length);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Witness each written file from disk. Any variance from expected content → fix and re-verify.
|
|
75
|
+
|
|
76
|
+
**Step 5 — Commit and push**:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
exec:bash
|
|
80
|
+
git add README.md docs/index.html gm-starter/agents/gm.md
|
|
81
|
+
git diff --cached --stat
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Witness staged files. Then commit and push:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
exec:bash
|
|
88
|
+
git commit -m "docs: update documentation to reflect session changes"
|
|
89
|
+
git push -u origin HEAD
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Witness push confirmation. Zero variance = COMPLETE.
|
|
93
|
+
|
|
94
|
+
## DOC FIDELITY RULES
|
|
95
|
+
|
|
96
|
+
Every claim in docs must be verifiable against disk right now:
|
|
97
|
+
- State machine phase names must match skill file `name:` frontmatter
|
|
98
|
+
- Platform names must match adapter class names in `platforms/`
|
|
99
|
+
- File paths must exist on disk
|
|
100
|
+
- Constraint counts must match actual constraints
|
|
101
|
+
|
|
102
|
+
If a doc section cannot be verified against disk: remove it, do not speculate.
|
|
103
|
+
|
|
104
|
+
## CONSTRAINTS
|
|
105
|
+
|
|
106
|
+
**Never**: skip diff analysis | write docs from memory alone | push without verifying from disk | add comments to doc content | claim done without witnessed push output
|
|
107
|
+
|
|
108
|
+
**Always**: witness git diff first | read current file before overwriting | verify each file from disk after write | push doc changes | confirm with witnessed push output
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
**→ COMPLETE**: Docs committed and pushed → session ends.
|
|
113
|
+
**↩ SNAKE to PLAN**: New unknown about codebase state → invoke `planning` skill.
|