@sema-agent/server 1.196.0 → 1.197.0
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/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -1
- package/dist/config.js.map +1 -1
- package/package.json +2 -1
- package/skills/code-review.md +28 -0
- package/skills/commit-push-pr.md +77 -0
- package/skills/dataviz/SKILL.md +112 -0
- package/skills/dataviz/references/anti-patterns.md +119 -0
- package/skills/dataviz/references/choosing-a-form.md +57 -0
- package/skills/dataviz/references/color-formula.md +113 -0
- package/skills/dataviz/references/components.md +39 -0
- package/skills/dataviz/references/interaction.md +60 -0
- package/skills/dataviz/references/marks-and-anatomy.md +97 -0
- package/skills/dataviz/references/palette.md +149 -0
- package/skills/dataviz/scripts/validate_palette.js +262 -0
- package/skills/find-skills.md +148 -0
- package/skills/init.md +28 -0
- package/skills/keybindings-help.md +294 -0
- package/skills/loop.md +50 -0
- package/skills/run-skill-generator.md +493 -0
- package/skills/run.md +148 -0
- package/skills/schedule.md +48 -0
- package/skills/security-review.md +181 -0
- package/skills/simplify.md +64 -0
- package/skills/update-config.md +93 -0
- package/skills/verify.md +334 -0
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: run-skill-generator
|
|
3
|
+
description: Author or improve the run-<unit> skill - a per-project skill that tells agents how to build, launch, and drive this project's app. Use when the user asks to set up the project, get it running, write run instructions, or verify build/run steps work from a clean environment.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Your job is to produce a **skill** at `<unit>/skills/run-<unit-name>/`
|
|
7
|
+
that lets a future agent build, launch, and **drive** this project from
|
|
8
|
+
a clean machine.
|
|
9
|
+
|
|
10
|
+
The skill has two parts that live together:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
<unit>/skills/run-<unit-name>/
|
|
14
|
+
SKILL.md ← agent-facing instructions — SHORT. Points at the driver.
|
|
15
|
+
driver.mjs ← (or driver.py, smoke.sh, … — or none: web apps use
|
|
16
|
+
browser-cli off-the-shelf, and the heredoc in
|
|
17
|
+
SKILL.md is the script)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
(*browser-cli* here = your environment's off-the-shelf headless-browser
|
|
21
|
+
driver CLI, e.g. Playwright-based; if none ships, a small Playwright
|
|
22
|
+
script is the driver.)
|
|
23
|
+
|
|
24
|
+
That almost always means **writing code**, not just prose. If the app
|
|
25
|
+
has any interactive surface (GUI, TUI, long-running server, REPL), the
|
|
26
|
+
future agent needs a programmatic way to poke it. A markdown file by
|
|
27
|
+
itself cannot click a button — but sometimes the button-clicker
|
|
28
|
+
already exists: for web apps it's `browser-cli`, for servers it's
|
|
29
|
+
`curl`. You build (or script) that harness now, commit it alongside
|
|
30
|
+
the skill, and the `SKILL.md` documents how to use it.
|
|
31
|
+
|
|
32
|
+
## Definition of done
|
|
33
|
+
|
|
34
|
+
You are done when **all** of these are true:
|
|
35
|
+
|
|
36
|
+
1. **You launched the app in this container and interacted with it** —
|
|
37
|
+
not its test suite, the actual running app. For anything with a GUI,
|
|
38
|
+
that means you have a screenshot file on disk that you took.
|
|
39
|
+
2. **The interaction harness is committed** next to the skill. A driver
|
|
40
|
+
script, a REPL wrapper, a smoke test, or the `browser-cli` heredoc
|
|
41
|
+
inline in `SKILL.md` — whatever you used to drive the app in step 1.
|
|
42
|
+
(Graduated into `scripts/`/`e2e/`? — fine, point at it. Web app with
|
|
43
|
+
`browser-cli` off-the-shelf? — the inline script is the harness; no
|
|
44
|
+
separate file.)
|
|
45
|
+
3. **The `SKILL.md` documents the harness** as the primary agent path —
|
|
46
|
+
the section a future agent reads first is "run this driver / pipe
|
|
47
|
+
these commands to `browser-cli`," not "run `npm start` and a window
|
|
48
|
+
opens."
|
|
49
|
+
4. **Every code block in `SKILL.md` is a command you ran that worked.**
|
|
50
|
+
This session. This container. Not from the README, not inferred.
|
|
51
|
+
|
|
52
|
+
If you're about to write the skill and you don't have (1), **stop.** You
|
|
53
|
+
are about to paraphrase existing docs. That document already exists —
|
|
54
|
+
it's called the README, and the whole reason you're here is that it
|
|
55
|
+
wasn't enough.
|
|
56
|
+
|
|
57
|
+
## The deliverables are code AND docs
|
|
58
|
+
|
|
59
|
+
Typical output is a skill directory containing both:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
<unit>/skills/run-<unit>/
|
|
63
|
+
SKILL.md ← SHORT. Points at the driver. Has the frontmatter
|
|
64
|
+
that lets the agent auto-load it when someone asks
|
|
65
|
+
to "run <unit>" or "screenshot <unit>".
|
|
66
|
+
driver.mjs ← (or driver.py, smoke.sh, … — or none: web apps
|
|
67
|
+
use browser-cli off-the-shelf, and the heredoc
|
|
68
|
+
in SKILL.md is the script)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The driver lives **inside the skill directory** by default. They are a
|
|
72
|
+
pair — the skill's instructions and the code that implements them. A
|
|
73
|
+
driver that lives here is allowed to be a bit messier than production
|
|
74
|
+
code; it's agent tooling, not product surface.
|
|
75
|
+
|
|
76
|
+
**Graduation:** if the driver grows into something the project's own
|
|
77
|
+
test suite wants to reuse — shared launch helpers, a real e2e harness —
|
|
78
|
+
move it to `scripts/` or `e2e/` and update `SKILL.md` to reference the
|
|
79
|
+
new path. The skill stays; the driver finds a better home.
|
|
80
|
+
|
|
81
|
+
The exact shape depends on the project, but the principle is constant:
|
|
82
|
+
**the driver is the deliverable.** The `SKILL.md` is its man page. For
|
|
83
|
+
a web app, the driver already exists — `browser-cli`
|
|
84
|
+
(see the `run` skill's browser-driven pattern) — and the skill is
|
|
85
|
+
the script that runs it. For a desktop app
|
|
86
|
+
(see the `run` skill's GUI pattern), the driver is a custom
|
|
87
|
+
REPL under tmux that exposes `launch`/`ss`/`click`/`eval`. For a server,
|
|
88
|
+
the driver is `curl`. Whatever shape it takes, without something that
|
|
89
|
+
reaches into the running app, the skill is a description of a window
|
|
90
|
+
nobody can touch.
|
|
91
|
+
|
|
92
|
+
## Where the skill goes
|
|
93
|
+
|
|
94
|
+
The skill lives at `<unit>/skills/run-<unit-name>/`, where
|
|
95
|
+
`<unit>` is the directory for **one deployable thing** — an app, a
|
|
96
|
+
service, a library.
|
|
97
|
+
|
|
98
|
+
The agent shell **discovers** project skills from nested `skills/`
|
|
99
|
+
directories (discovery root is shell/deployment-configurable - adjust
|
|
100
|
+
paths to where your shell loads project skills): an agent working
|
|
101
|
+
anywhere inside `<unit>` will see
|
|
102
|
+
`/run-<unit-name>` as an available skill, and it auto-loads when the
|
|
103
|
+
request matches its description (e.g. "run the desktop app," "take a
|
|
104
|
+
screenshot of billing").
|
|
105
|
+
|
|
106
|
+
- **Single-project repo:** `skills/run-<repo-name>/` at repo root.
|
|
107
|
+
- **Large repo with many apps:** one per app, colocated —
|
|
108
|
+
`apps/billing/skills/run-billing/`,
|
|
109
|
+
`apps/desktop/skills/run-desktop/`.
|
|
110
|
+
- **App with multiple binaries:** still **one** skill at the app's
|
|
111
|
+
root with a section per binary. They share setup. Start from the
|
|
112
|
+
closest single-binary example and add a `## Run: <name>` section
|
|
113
|
+
per binary.
|
|
114
|
+
|
|
115
|
+
If you're not sure where the unit boundary is, **ask the user.**
|
|
116
|
+
|
|
117
|
+
Slugify the directory name: lowercase, dashes for spaces, no slashes
|
|
118
|
+
(`run-billing-api`, not `run-billing/api`). The directory name and
|
|
119
|
+
the frontmatter `name:` should match — that's the slash command.
|
|
120
|
+
|
|
121
|
+
## Process
|
|
122
|
+
|
|
123
|
+
### 0. Find any existing skill about running this app
|
|
124
|
+
|
|
125
|
+
List the project's skills with their descriptions (same probe `/run`
|
|
126
|
+
uses — users name these variously, so match on description, not name):
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
d=$PWD; while :; do
|
|
130
|
+
grep -Hm1 '^description:' "$d"/skills/*/SKILL.md 2>/dev/null
|
|
131
|
+
[ -e "$d/.git" ] || [ "$d" = / ] && break
|
|
132
|
+
d=$(dirname "$d")
|
|
133
|
+
done
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
If one is about launching/driving this app — whatever it's named —
|
|
137
|
+
**refine, don't rewrite**: verify its claims, fix what's wrong, add
|
|
138
|
+
what's missing, preserve what works. Re-run the driver if there is
|
|
139
|
+
one. Keep its existing name.
|
|
140
|
+
|
|
141
|
+
If none exists, decide where to create it (see above) and continue.
|
|
142
|
+
|
|
143
|
+
### 1. Discover — and treat every claim as disprovable
|
|
144
|
+
|
|
145
|
+
Figure out what you're authoring for:
|
|
146
|
+
|
|
147
|
+
- Manifest right here (`package.json`, `go.mod`, `pyproject.toml`…) and
|
|
148
|
+
it's one self-contained thing → this is the unit.
|
|
149
|
+
- Looks like a mega-repo root (`apps/`, `packages/`, `services/`) →
|
|
150
|
+
**ask which one.** List candidates, let them pick, `cd` there.
|
|
151
|
+
- Genuinely ambiguous → ask.
|
|
152
|
+
|
|
153
|
+
Survey the usual places: `README.md`, `package.json` scripts,
|
|
154
|
+
`Dockerfile`, `Makefile`, `.github/workflows/`, `CONTRIBUTING.md`. CI
|
|
155
|
+
configs are often more accurate than READMEs.
|
|
156
|
+
|
|
157
|
+
**Every claim in existing docs is a hypothesis.** Especially the
|
|
158
|
+
negative ones:
|
|
159
|
+
|
|
160
|
+
| When docs say… | What you do |
|
|
161
|
+
|---|---|
|
|
162
|
+
| "Requires macOS/Windows" | Launch it on Linux anyway. Apps rarely refuse to start — they crash on a missing `.so`, which `apt-get` fixes. Native modules for *your host's* keychain/notifications may no-op; the core usually runs. |
|
|
163
|
+
| "Requires a GPU" | Try software rendering. Electron/Chrome fall back with `--disable-gpu`. |
|
|
164
|
+
| "Requires a paid account / feature flag" | The gate is code you can read. Find it (env var? build define? SSR-embedded JSON?) and patch it for your local run. Document the patch. |
|
|
165
|
+
| "Run `npm start`" | That's the human path (spawns a window, waits forever). Find or build the *programmatic* path — `electron-forge start` to build then launch via Playwright, or equivalent. |
|
|
166
|
+
|
|
167
|
+
"Not supported on Linux" in a README written by a macOS developer
|
|
168
|
+
means "I never tried." You're about to try. **If you give up here, the
|
|
169
|
+
skill you write is the README with extra steps.**
|
|
170
|
+
|
|
171
|
+
### 2. Execute — and BUILD the harness you need
|
|
172
|
+
|
|
173
|
+
You're in a headless Linux container. The app is going to fight you.
|
|
174
|
+
That fight is the content of the skill.
|
|
175
|
+
|
|
176
|
+
Keep a running `NOTES.md` as you go. Every error → every fix → every
|
|
177
|
+
command that finally worked. This scratchpad becomes the
|
|
178
|
+
Troubleshooting section.
|
|
179
|
+
|
|
180
|
+
**Work up to a real interaction:**
|
|
181
|
+
|
|
182
|
+
- **Install + build.** When something's missing, note the exact
|
|
183
|
+
`apt-get` / `npm install` that fixed it.
|
|
184
|
+
- **Launch the app.** Not the test suite — the app. A desktop GUI
|
|
185
|
+
(Electron, native) needs `xvfb-run` and a handful of `lib*`
|
|
186
|
+
packages; a web app driven by `browser-cli` runs headless and
|
|
187
|
+
needs neither. Launch timeouts and cryptic crashes are normal at
|
|
188
|
+
this stage. Read the stack trace, install the missing thing, try
|
|
189
|
+
again.
|
|
190
|
+
- **Build a harness to drive it.** You need a handle on the running
|
|
191
|
+
app that lets you send input and observe output programmatically.
|
|
192
|
+
The shape depends on the project (see table below).
|
|
193
|
+
|
|
194
|
+
**Cover the layer(s) PRs actually touch.** A tmux driver that pokes
|
|
195
|
+
the CLI's user surface is the right handle for UI changes — and the
|
|
196
|
+
wrong one for a PR that touches one internal function. For the
|
|
197
|
+
latter an agent wants `NODE_ENV=test bun run script.ts` (or
|
|
198
|
+
equivalent): import the function, call it, observe. If most PRs
|
|
199
|
+
here touch internals, that direct-invocation path is the driver's
|
|
200
|
+
main entry point, and the tmux launch is secondary. Look at recent
|
|
201
|
+
merged PRs: what layer do they touch? Cover that.
|
|
202
|
+
|
|
203
|
+
For a **web** app, `browser-cli` is the driver — you script it,
|
|
204
|
+
you don't write it (see the `run` skill's browser-driven pattern).
|
|
205
|
+
For a **desktop** GUI (Electron), write a REPL driver (stdin
|
|
206
|
+
commands → click/type/screenshot), run it inside tmux, and use
|
|
207
|
+
`send-keys` / `capture-pane`. You will iterate on that driver — it
|
|
208
|
+
starts minimal (`launch`, `ss`, `quit`) and grows whatever commands
|
|
209
|
+
you need to reach the interesting part of the app.
|
|
210
|
+
- **Do one real user flow end-to-end.** Click the button. Fill the
|
|
211
|
+
form. See the result in the DOM. Take a screenshot. **Actually look
|
|
212
|
+
at the screenshot.** If it's blank or showing an error page, you're
|
|
213
|
+
not done.
|
|
214
|
+
- **Then run the tests.** Unit tests are a sanity check, not the main
|
|
215
|
+
event.
|
|
216
|
+
- **Stop cleanly.**
|
|
217
|
+
|
|
218
|
+
**Obstacles are content.** You will hit weird ones — coordinate systems
|
|
219
|
+
that don't line up, APIs that return empty on this Electron version,
|
|
220
|
+
feature gates that hide the thing you need to test. Each of these gets
|
|
221
|
+
a bullet in Gotchas and (often) a helper in your driver. The gold
|
|
222
|
+
standard is a Gotchas section full of things nobody could have guessed.
|
|
223
|
+
|
|
224
|
+
**The driver script gets committed alongside the skill.** It is not
|
|
225
|
+
scaffolding. It is the way future agents (and humans) will drive this
|
|
226
|
+
app. It defaults to living inside the skill directory (for a web app
|
|
227
|
+
using `browser-cli`, that means inline in `SKILL.md` — the heredoc
|
|
228
|
+
is the script). If it outgrows that — if the project's real test
|
|
229
|
+
suite wants to import from it — move it to `scripts/` or `e2e/` and
|
|
230
|
+
update `SKILL.md` to point there.
|
|
231
|
+
|
|
232
|
+
### 3. Write SKILL.md
|
|
233
|
+
|
|
234
|
+
Short. Point at the driver. Use the template in the Appendix at the end of this document as the
|
|
235
|
+
starting structure — it has the frontmatter shape.
|
|
236
|
+
|
|
237
|
+
**The frontmatter matters.** The `name:` becomes the slash command
|
|
238
|
+
(`/run-billing`). The `description:` is what the agent scans to decide
|
|
239
|
+
whether to auto-load this skill — put the **verbs an agent would
|
|
240
|
+
actually type** in it: "run," "start," "build," "test," "screenshot."
|
|
241
|
+
Generic descriptions ("helpful utilities for billing") won't match.
|
|
242
|
+
|
|
243
|
+
Body structure:
|
|
244
|
+
|
|
245
|
+
1. One-paragraph intro: what this app is, how it's driven —
|
|
246
|
+
`<driver-path>` under xvfb/tmux for desktop, `browser-cli` for
|
|
247
|
+
web, `curl` for a server.
|
|
248
|
+
2. **Prerequisites** — the exact `apt-get install` line you ran.
|
|
249
|
+
3. **Build** — the exact commands, in order. Include any patches you
|
|
250
|
+
had to apply (feature gates, config overrides) with the exact `sed`
|
|
251
|
+
or edit.
|
|
252
|
+
4. **Run (agent path)** — FIRST. How to launch the driver, what
|
|
253
|
+
commands it accepts, where screenshots land. If it's a REPL, show
|
|
254
|
+
the tmux wrapping. This is the section the next agent will actually
|
|
255
|
+
use.
|
|
256
|
+
5. **Run (human path)** — SECOND, if different. `npm start` → window
|
|
257
|
+
opens → Ctrl-C. Brief. Note that it's useless headless.
|
|
258
|
+
6. **Gotchas** — the battle scars. The things that look like they
|
|
259
|
+
should work but don't, and the workaround. If this section is
|
|
260
|
+
generic, you didn't fight hard enough.
|
|
261
|
+
7. **Troubleshooting** — symptom → fix. Only errors you actually hit.
|
|
262
|
+
|
|
263
|
+
Keep it **verified** (you ran it), **prescriptive** (one path, not
|
|
264
|
+
options), **honest** (flaky? slow? say so).
|
|
265
|
+
|
|
266
|
+
**Paths in SKILL.md are relative to `<unit>/`,** not to the skill
|
|
267
|
+
directory. State this at the top if there's any ambiguity. When the
|
|
268
|
+
driver lives inside the skill, its path from `<unit>` is
|
|
269
|
+
`skills/run-<unit-name>/driver.mjs` — it's long, but explicit.
|
|
270
|
+
|
|
271
|
+
### 4. Verify
|
|
272
|
+
|
|
273
|
+
Fresh shell, `cd` into the unit, follow the skill's `SKILL.md`
|
|
274
|
+
line-by-line without deviating. Any improvisation = a gap. Fix it.
|
|
275
|
+
|
|
276
|
+
## Project-type patterns
|
|
277
|
+
|
|
278
|
+
Pick a starting shape for your driver. These per-project-type patterns
|
|
279
|
+
are shared with the `run` skill (they are its fallback when no
|
|
280
|
+
project-specific run skill exists) — if you're authoring a new one,
|
|
281
|
+
start from the matching pattern documented there.
|
|
282
|
+
|
|
283
|
+
| Project type | Driver shape |
|
|
284
|
+
|---|---|
|
|
285
|
+
| Web server / API | Background-launch + `curl`-based smoke script |
|
|
286
|
+
| CLI tool | Representative-args smoke script, check exit codes + output |
|
|
287
|
+
| TUI / interactive terminal | tmux wrapper: `send-keys` / `capture-pane` |
|
|
288
|
+
| Electron / desktop GUI | Playwright `_electron` REPL driver under xvfb, screenshots, tmux-wrapped |
|
|
289
|
+
| Browser-driven | dev server + `browser-cli` script |
|
|
290
|
+
| Library / SDK | Import-and-call smoke script |
|
|
291
|
+
|
|
292
|
+
For a web app, start from the `run` skill's browser-driven pattern —
|
|
293
|
+
drive it with `browser-cli`, no custom driver needed. For a desktop
|
|
294
|
+
app, write a Playwright `_electron` REPL driver (launch/ss/click/eval
|
|
295
|
+
commands over stdin), run it under xvfb inside tmux, and grow it as
|
|
296
|
+
you fight the app.
|
|
297
|
+
|
|
298
|
+
## What to include
|
|
299
|
+
|
|
300
|
+
- **Prerequisites** — OS packages, runtimes, tools. Ubuntu `apt-get`
|
|
301
|
+
lines. The exact ones.
|
|
302
|
+
- **Setup** — install deps, configure, any patches.
|
|
303
|
+
- **Build** — compile/bundle.
|
|
304
|
+
- **Run (agent path)** — the driver. Commands. Screenshot location.
|
|
305
|
+
- **Direct invocation** — if callable: how to import and run internal
|
|
306
|
+
code without the full app. The env var / flag that bypasses init
|
|
307
|
+
guards. Many PRs need only this.
|
|
308
|
+
- **Run (human path)** — if meaningfully different.
|
|
309
|
+
- **Test** — the test suite command.
|
|
310
|
+
- **Gotchas** — non-obvious traps you hit.
|
|
311
|
+
- **Troubleshooting** — error → fix.
|
|
312
|
+
- **The driver itself** — committed in the skill dir (or graduated
|
|
313
|
+
to `scripts/`/`e2e/`), or inline in `SKILL.md` for `browser-cli`
|
|
314
|
+
web apps; referenced from `SKILL.md` either way.
|
|
315
|
+
|
|
316
|
+
## What to leave out
|
|
317
|
+
|
|
318
|
+
- **Anything you didn't run.** If the README says `yarn start:prod` and
|
|
319
|
+
you never ran it, it's not in the skill. Full stop.
|
|
320
|
+
- **Documented happy paths for platforms you're not on.** You're in a
|
|
321
|
+
Linux container. A macOS-only section you can't verify is
|
|
322
|
+
speculation. Mention it exists; don't elaborate.
|
|
323
|
+
- **Exhaustive options.** One working path.
|
|
324
|
+
- **Architecture prose.** That's other docs.
|
|
325
|
+
- **Generic troubleshooting.** "If the build fails, check your Node
|
|
326
|
+
version" — useless. Only include errors you actually hit and fixed.
|
|
327
|
+
|
|
328
|
+
## Red flags — you are about to ship the wrong thing
|
|
329
|
+
|
|
330
|
+
Stop and reconsider if:
|
|
331
|
+
|
|
332
|
+
- **You haven't taken a screenshot** of a GUI app. You didn't run it.
|
|
333
|
+
- **Your skill has no driver/smoke script** to point at, and the app
|
|
334
|
+
is interactive. The next agent has no way to drive it. (Web app
|
|
335
|
+
using `browser-cli`? — the heredoc in `SKILL.md` is the driver;
|
|
336
|
+
no separate file needed.)
|
|
337
|
+
- **Your skill reads like the README.** Same structure, same
|
|
338
|
+
commands, same caveats. You paraphrased.
|
|
339
|
+
- **Your Troubleshooting section is generic.** Real execution produces
|
|
340
|
+
specific, weird errors. Generic errors = you didn't execute.
|
|
341
|
+
- **You wrote "not supported on this platform"** without trying to
|
|
342
|
+
launch it. The README author was on a Mac. You are not. Try.
|
|
343
|
+
- **Everything worked first try.** Either this project is trivially
|
|
344
|
+
simple, or you ran the test suite and called it done.
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Appendix — template.md
|
|
349
|
+
|
|
350
|
+
````markdown
|
|
351
|
+
---
|
|
352
|
+
name: run-<unit-name>
|
|
353
|
+
description: Build, run, and drive <unit-name>. Use when asked to start <unit-name>, run its tests, build it, take a screenshot of its UI, or interact with the running app.
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
<One-sentence description: what this is and how an agent drives it.
|
|
357
|
+
Name the handle here — "drive it via
|
|
358
|
+
`skills/run-<unit-name>/driver.mjs` under xvfb" for a desktop
|
|
359
|
+
app, or "start the dev server then drive it via `browser-cli`" for a
|
|
360
|
+
web app — so an agent knows where to look first.>
|
|
361
|
+
|
|
362
|
+
<If the unit isn't at repo root:>
|
|
363
|
+
All paths below are relative to `<unit-dir>/`.
|
|
364
|
+
|
|
365
|
+
## Prerequisites
|
|
366
|
+
|
|
367
|
+
<System-level requirements. The exact `apt-get install` line you ran —
|
|
368
|
+
not a generic list, the one that actually worked. Target Ubuntu.>
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
sudo apt-get update
|
|
372
|
+
sudo apt-get install -y <packages-you-actually-installed>
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
<Runtime versions if they matter:>
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
# Example: Node 20 via nvm, Python 3.12 via uv, etc.
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Setup
|
|
382
|
+
|
|
383
|
+
<One-time setup after clone: install deps, configure, apply any
|
|
384
|
+
patches (feature-gate overrides, config stubs) with the exact command.>
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
<commands>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
<Env vars — required vs optional, with sensible defaults:>
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
export FOO_API_KEY=... # required — get from <where>
|
|
394
|
+
export BAR_MODE=dev # optional — default is prod
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## Build
|
|
398
|
+
|
|
399
|
+
<Skip if no separate build step. Otherwise the exact command:>
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
<command>
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Run (agent path)
|
|
406
|
+
|
|
407
|
+
<This is the section a future agent actually uses. If you built a
|
|
408
|
+
driver/REPL/smoke script, this documents how to launch it and what it
|
|
409
|
+
does. If the app is simple enough that `curl` or a one-liner suffices,
|
|
410
|
+
that one-liner goes here.>
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
<launch-the-driver-or-smoke-script>
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
<For REPL-style drivers, show the tmux wrapping. Poll for a ready marker
|
|
417
|
+
between send-keys and capture-pane — faster than a fixed sleep and fails
|
|
418
|
+
loudly instead of capturing a half-rendered screen:>
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
tmux new-session -d -s app -x 200 -y 50
|
|
422
|
+
tmux send-keys -t app '<launch command>' Enter
|
|
423
|
+
timeout 30 bash -c 'until tmux capture-pane -t app -p | grep -q "<ready-marker>"; do sleep 0.2; done'
|
|
424
|
+
tmux send-keys -t app '<first driver command>' Enter
|
|
425
|
+
tmux capture-pane -t app -p
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
<Where artifacts land (screenshots, logs) — absolute paths:>
|
|
429
|
+
|
|
430
|
+
Screenshots → `/tmp/shots/`. Logs → `/tmp/<app>.log`.
|
|
431
|
+
|
|
432
|
+
<If the driver has commands, a table:>
|
|
433
|
+
|
|
434
|
+
| command | what it does |
|
|
435
|
+
|---|---|
|
|
436
|
+
| `<cmd>` | <description> |
|
|
437
|
+
|
|
438
|
+
## Run (human path)
|
|
439
|
+
|
|
440
|
+
<If meaningfully different from the agent path. Brief — agents won't
|
|
441
|
+
use this, humans can figure it out.>
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
<command> # → <what happens>. <how to stop>.
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Test
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
<command>
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
<Expected result — "N suites pass", or specific known-flaky tests.>
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
<Optional sections below — include only if relevant and only with
|
|
458
|
+
content you actually hit, not generic advice.>
|
|
459
|
+
|
|
460
|
+
## Gotchas
|
|
461
|
+
|
|
462
|
+
<Non-obvious traps. The things that look like they should work but
|
|
463
|
+
don't, with the workaround. If this section is generic, delete it.>
|
|
464
|
+
|
|
465
|
+
- **<specific thing>** — <why it breaks> → <what to do instead>
|
|
466
|
+
|
|
467
|
+
## Troubleshooting
|
|
468
|
+
|
|
469
|
+
<Symptom → fix. Only errors you actually encountered.>
|
|
470
|
+
|
|
471
|
+
- **<exact error message or symptom>**: <cause>. <fix>.
|
|
472
|
+
|
|
473
|
+
<---
|
|
474
|
+
|
|
475
|
+
NOTE ON THE FRONTMATTER ABOVE:
|
|
476
|
+
- Replace <unit-name> in both `name:` and `description:`. The `name:`
|
|
477
|
+
becomes the slash command (/run-<unit-name>) and must match the
|
|
478
|
+
directory name.
|
|
479
|
+
- The `description:` is what the agent scans to decide whether to load this
|
|
480
|
+
skill automatically. Keep the verbs — "start," "run," "build," "test,"
|
|
481
|
+
"screenshot" — they're what an asking agent will actually type.
|
|
482
|
+
|
|
483
|
+
NOTE ON THE DRIVER:
|
|
484
|
+
- If you wrote a driver script, it lives in this same directory (next
|
|
485
|
+
to this file) by default. Reference it from the Run section.
|
|
486
|
+
- For a web app there's usually no driver file — the `browser-cli`
|
|
487
|
+
heredoc in the Run section is the harness.
|
|
488
|
+
- If the driver grows into something the project's test suite wants —
|
|
489
|
+
shared launch helpers, a real e2e harness — move it to scripts/ or
|
|
490
|
+
e2e/ in the unit, and update the paths here. The skill stays put.
|
|
491
|
+
|
|
492
|
+
Delete everything from `---` above onwards before committing. --->
|
|
493
|
+
````
|
package/skills/run.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: run
|
|
3
|
+
description: Launch and drive this project's app to see a change working. Use when asked to run, start, or screenshot the app, or to confirm a change works in the real app (not just tests). First looks for a project-provided launch recipe; otherwise falls back to built-in patterns per project type (CLI, server, TUI, desktop GUI, browser-driven, library).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
**Running means launching the actual app and interacting with it** —
|
|
7
|
+
not the test suite, not an `import` of an internal function and a
|
|
8
|
+
`console.log`. The app as a user (human or programmatic) would meet
|
|
9
|
+
it: the CLI at its command, the server at its socket, the GUI at its
|
|
10
|
+
window.
|
|
11
|
+
|
|
12
|
+
## First: does a project recipe already cover this?
|
|
13
|
+
|
|
14
|
+
A project-provided recipe that launches this app is the repo's
|
|
15
|
+
verified path — its author already cold-started and committed what
|
|
16
|
+
worked: the exact install line, the env vars, the patches, the
|
|
17
|
+
driver. Use it instead of rediscovering. Look in, roughly in order:
|
|
18
|
+
|
|
19
|
+
- your available skills (a launch/verify recipe for this project or
|
|
20
|
+
this kind of app);
|
|
21
|
+
- the repo's own entry points: README "getting started", Makefile /
|
|
22
|
+
justfile targets, package.json scripts, docker-compose files,
|
|
23
|
+
CI workflow steps that boot the app.
|
|
24
|
+
|
|
25
|
+
- **One describes launching/driving this app** → follow it verbatim.
|
|
26
|
+
Don't paraphrase; don't skip the patches.
|
|
27
|
+
- **Mega-repo, several plausible, no clear match** → ask the user
|
|
28
|
+
which unit to run.
|
|
29
|
+
- **Stale** (fails on mechanics unrelated to your task) → tell the
|
|
30
|
+
user; offer to refresh it.
|
|
31
|
+
- **Nothing about running** → fall back to the patterns below.
|
|
32
|
+
|
|
33
|
+
## Otherwise: match the shape, use the pattern
|
|
34
|
+
|
|
35
|
+
Pick the row closest to your project.
|
|
36
|
+
|
|
37
|
+
| Project type | Handle | Pattern |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| CLI tool | direct invocation, exit code, stdin/stdout | invoke it below |
|
|
40
|
+
| Web server / API | background launch + `curl` smoke | lifecycle below |
|
|
41
|
+
| TUI / interactive terminal | tmux `send-keys` / `capture-pane` | tmux pattern below |
|
|
42
|
+
| Desktop GUI | drive it headless (xvfb + an automation driver), screenshot | adapt the browser pattern |
|
|
43
|
+
| Browser-driven web app | dev server + headless browser script | browser pattern below |
|
|
44
|
+
| Library / SDK | import-and-call smoke script at the package boundary | library pattern below |
|
|
45
|
+
|
|
46
|
+
If nothing fits, start from the closest match and adapt.
|
|
47
|
+
|
|
48
|
+
### CLI
|
|
49
|
+
|
|
50
|
+
No lifecycle, no ports. Get the binary runnable (build, or install in
|
|
51
|
+
editable/dev mode so it lands on PATH), confirm with `--version` or
|
|
52
|
+
`--help`, then run a representative command and check exit code and
|
|
53
|
+
output:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
mytool process input.json
|
|
57
|
+
# → Processed 42 records, wrote output.json
|
|
58
|
+
echo $? # meaningful exit codes are part of the interface
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If the tool reads stdin, pipe test data in.
|
|
62
|
+
|
|
63
|
+
### Web server / API
|
|
64
|
+
|
|
65
|
+
Start in the background with logs captured, poll for readiness (never
|
|
66
|
+
a fixed sleep), then hit the routes:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
<start-command> &> /tmp/server.log &
|
|
70
|
+
SERVER_PID=$!
|
|
71
|
+
for i in {1..30}; do curl -sf localhost:PORT/health >/dev/null && break; sleep 1; done
|
|
72
|
+
curl -si localhost:PORT/api/thing # status + headers + body
|
|
73
|
+
kill $SERVER_PID
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
No health endpoint? Poll the route you're about to test until it
|
|
77
|
+
stops returning connection-refused.
|
|
78
|
+
|
|
79
|
+
### TUI / interactive terminal app
|
|
80
|
+
|
|
81
|
+
Interactive terminal apps (editors, REPLs, curses UIs) take over the
|
|
82
|
+
terminal — you can't drive them directly from a shell tool. Wrap them
|
|
83
|
+
in tmux: start detached, send keystrokes, capture the pane, kill the
|
|
84
|
+
session when done.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
tmux new-session -d -s app -x 120 -y 40 './myapp'
|
|
88
|
+
|
|
89
|
+
# poll until the ready marker appears (fails loudly if it never does)
|
|
90
|
+
timeout 10 bash -c 'until tmux capture-pane -t app -p | grep -q "Ready"; do sleep 0.2; done'
|
|
91
|
+
tmux capture-pane -t app -p
|
|
92
|
+
|
|
93
|
+
# send input and wait for the screen to reflect it
|
|
94
|
+
tmux send-keys -t app 's'
|
|
95
|
+
timeout 5 bash -c 'until tmux capture-pane -t app -p | grep -q "Settings"; do sleep 0.2; done'
|
|
96
|
+
tmux send-keys -t app 'Down' 'Down' 'Space'
|
|
97
|
+
tmux capture-pane -t app -p
|
|
98
|
+
|
|
99
|
+
# quit
|
|
100
|
+
tmux send-keys -t app 'q'
|
|
101
|
+
tmux kill-session -t app 2>/dev/null || true
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Details that matter: pick a known-good terminal size (`-x`/`-y` —
|
|
105
|
+
some TUIs break at small widths); poll for a ready string rather than
|
|
106
|
+
sleeping; learn the app's keybindings (they're its API); always
|
|
107
|
+
`kill-session` as a fallback exit. If `capture-pane` output is hard
|
|
108
|
+
to read, `-e` keeps escape sequences and `-J` joins wrapped lines.
|
|
109
|
+
Use a private socket (`tmux -L name`) so you don't collide with other
|
|
110
|
+
sessions on the box.
|
|
111
|
+
|
|
112
|
+
### Browser-driven web app
|
|
113
|
+
|
|
114
|
+
Start the dev server (background + readiness poll, as above), then
|
|
115
|
+
drive the page with a headless browser script (e.g. Playwright):
|
|
116
|
+
navigate, click the flow the change touches, screenshot. **Look at
|
|
117
|
+
the screenshot** — a blank frame is a failure to launch, not a pass.
|
|
118
|
+
|
|
119
|
+
### Library / SDK
|
|
120
|
+
|
|
121
|
+
There's no process to start. "Running" it is: build from source, then
|
|
122
|
+
a minimal smoke program that imports the library **through its public
|
|
123
|
+
package boundary** and does one real thing:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
python -c '
|
|
127
|
+
from mylib import Client
|
|
128
|
+
print(Client().ping())
|
|
129
|
+
'
|
|
130
|
+
# → pong
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Drive it, don't just launch it
|
|
134
|
+
|
|
135
|
+
Launching with no interaction proves the entrypoint resolves. That's
|
|
136
|
+
not running the app — it's typechecking with extra steps. Drive it to
|
|
137
|
+
a point where a user would see something:
|
|
138
|
+
|
|
139
|
+
- CLI → type a representative command, check the exit code and output.
|
|
140
|
+
- Server → hit the route the diff touches with `curl`, read the body.
|
|
141
|
+
- TUI → `send-keys` a navigation, `capture-pane` the result.
|
|
142
|
+
- GUI → click the button, screenshot the window. **Look at the
|
|
143
|
+
screenshot.** A blank frame is a failure to launch.
|
|
144
|
+
|
|
145
|
+
If the fallback pattern didn't work out of the box — you had to
|
|
146
|
+
install packages, set env vars, patch config, or write a driver —
|
|
147
|
+
record the exact recipe that worked in your report so it can be
|
|
148
|
+
captured as a project skill. If it just worked, don't.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: schedule
|
|
3
|
+
description: Create, list, or delete scheduled tasks that fire on a cron schedule, at an absolute time, or after a delay, via the sema scheduler. - When the user wants to schedule recurring work ("every morning run X"), a one-time reminder ("remind me at 3pm", "in 30 minutes check Y"), or to inspect/cancel existing scheduled tasks. Tasks run locally through the sema scheduler daemon, not in a cloud service.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /schedule — sema scheduled tasks
|
|
7
|
+
|
|
8
|
+
sema schedules work through three engine tools backed by the local scheduler daemon: `CronCreate`, `CronList`, `CronDelete`. There are no cloud routines: a scheduled task fires on THIS machine while sema's scheduler daemon is running, in a fresh unattended run — it will not see this conversation.
|
|
9
|
+
|
|
10
|
+
## Creating a task: CronCreate
|
|
11
|
+
|
|
12
|
+
Parameters:
|
|
13
|
+
|
|
14
|
+
- `prompt` (string, required): fully self-contained instructions for the future task. It runs unattended — inline every path, id, and acceptance criterion it needs; never reference "the file we discussed".
|
|
15
|
+
- `schedule` (union, required) — pick the kind by intent:
|
|
16
|
+
- Recurring: `{ "kind": "cron", "expr": "M H DoM Mon DoW" }` — standard 5-field cron in the user's LOCAL timezone (a 6-field form with leading seconds is also accepted). `"0 9 * * *"` means 9am local; no timezone conversion needed.
|
|
17
|
+
- One-shot at a wall-clock time: `{ "kind": "at", "atMs": <epoch ms> }`.
|
|
18
|
+
- One-shot after a delay: `{ "kind": "delay", "delaySec": <seconds> }`.
|
|
19
|
+
- `label` (string, optional): short name. Also the dedup key — creating again with the same schedule+label upserts (idempotent), so use a stable label when updating a task instead of piling up duplicates.
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
|
|
23
|
+
- "check the deploy in 30 minutes" → `{ "kind": "delay", "delaySec": 1800 }`
|
|
24
|
+
- "tomorrow at 8:57am run the smoke test" → `{ "kind": "at", "atMs": <epoch ms of that local time> }`
|
|
25
|
+
- "every 5 minutes" → `{ "kind": "cron", "expr": "*/5 * * * *" }`
|
|
26
|
+
- "weekdays around 9am" → `{ "kind": "cron", "expr": "57 8 * * 1-5" }`
|
|
27
|
+
|
|
28
|
+
**Avoid the :00 and :30 minute marks when the request is approximate.** Every user who asks for "hourly" gets `0 *`, so the fleet stampedes on the hour. Nudge a few minutes early or late (`7 * * * *`, `57 8 * * *`) unless the user names an exact time and clearly means it.
|
|
29
|
+
|
|
30
|
+
Invalid cron expressions are rejected with a specific field error, including calendar-impossible dates ("Feb 31") that would never fire — fix and retry rather than switching kinds.
|
|
31
|
+
|
|
32
|
+
## Inspecting and cancelling
|
|
33
|
+
|
|
34
|
+
- `CronList` (no parameters): lists your scheduled tasks — `id`, human-readable schedule, `label`. It deliberately does NOT return each task's prompt (security boundary); track what a task does via its label.
|
|
35
|
+
- `CronDelete` with `{ "id": "<id from CronCreate/CronList>" }`: cancels a task. Idempotent — deleting an already-gone id reports that instead of erroring.
|
|
36
|
+
|
|
37
|
+
## Execution model and limits
|
|
38
|
+
|
|
39
|
+
- **Backend**: the sema shell scheduler daemon persists tasks to `scheduled_tasks.json` under the sema config home (`SEMA_CONFIG_DIR`, default `~/.sema`), so durable tasks survive shell restarts; the daemon polls the store and launches each firing as a new unattended run.
|
|
40
|
+
- **Scope isolation**: list/cancel only see tasks in your own scope; the task runs as the principal that scheduled it (pinned at schedule time — a task cannot escalate privileges).
|
|
41
|
+
- **Default caps** (deployment-tunable): at most 32 scheduled tasks per scope, minimum delay 10s, minimum cron interval 60s, scheduling horizon 30 days.
|
|
42
|
+
- **Locality caveat**: if the machine (or the scheduler daemon) is off at fire time, the task does not run in a cloud fallback. Tell the user this when they schedule something that clearly assumes an always-on service.
|
|
43
|
+
|
|
44
|
+
## When NOT to use this
|
|
45
|
+
|
|
46
|
+
- One-off work the user wants NOW — just do it.
|
|
47
|
+
- Recurring-interval loops phrased as "/loop" or "keep checking X" — use the loop skill, which layers parsing and self-pacing (ScheduleWakeup) on top of these same tools.
|
|
48
|
+
- Fleet/server-side scheduling for TOB deployments — that is service-plane configuration, not a session tool call.
|