🤖 Gremlins MVP: SKILL.md
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
name: gremlins
|
||||||
|
description: Trains one headless implementer (the base) per build with `claude -p` and forks a gremlin from it per block, so each gremlin starts from the base's reading at prompt-cache prices.
|
||||||
|
allowed-tools: Bash(uv:*)
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gremlins
|
||||||
|
|
||||||
|
A **base** is a headless `claude -p` session that reads the code a build touches, writes the trunk notes and changes nothing. A **gremlin** is a fork of the base's session (`--resume <base> --fork-session`) that works on one block with a brief.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
`G` = `uv run --script "${CLAUDE_SKILL_DIR}/gremlins.py"`. Every command prints one JSON object on stdout. Exit codes: 0 ok, 1 the call ended `error` or `stopped`, 2 refused or a usage error.
|
||||||
|
|
||||||
|
| Command | Does | Boxes |
|
||||||
|
|---|---|---|
|
||||||
|
| `G init --run R --model M [--effort E] [--cwd D] [--agent A] [--binary P]` | Writes `run.json`: the launch fingerprint (binary, full model id, flags, cwd, appended prompt) and the argv, stored once. Refuses to overwrite an existing run. | B1 |
|
||||||
|
| `G train --run R --base B --brief F` | One blocking call with `--session-id`; on `ok` it writes `bases/B.json`. Prints `{status, session_id, cost, …}`. | B1 |
|
||||||
|
| `G spawn --run R --base B --job J --brief F` | One blocking fork of B, reusing the stored argv verbatim. The prompt is the spawn template plus a delta header (git changes since the base's commit) plus the brief. Prints `{status, cache, note, cost, …}`. | B2, B3, B5 |
|
||||||
|
| `G rebase --run R --base B --brief F` | Resumes B without a fork, with the delta header and the brief, then updates `bases/B.json` (the session id comes from the result). Warns when jobs of B are still `running`. | B7 |
|
||||||
|
| `G status --run R [--job J]` | Bases with their warmth (`warm`/`expiring`/`cold`, `warm_until`, `ttl_left_s`), and the job records. | B6, B3 |
|
||||||
|
|
||||||
|
`R` is the run log `.md`; `M` is a full model id (for example `claude-opus-5-5[1m]`; aliases are refused). The helper has no `kill`, `wait`, `ping` or `continue` command.
|
||||||
|
|
||||||
|
## Call sequence
|
||||||
|
|
||||||
|
1. `G init …` (foreground).
|
||||||
|
2. `G train …` as a blocking Bash call with `timeout: 600000`. If it runs past the timeout, the harness moves it to the background, and the completion notice carries the result.
|
||||||
|
3. Each `G spawn …` as its own Bash call with `run_in_background: true`. Several spawns run at once as several background calls. Read the result JSON from each completion notice; do not poll.
|
||||||
|
4. `G status …` to see warmth before spawning again, or to re-read a job record.
|
||||||
|
|
||||||
|
Every call is reported in `ledger.jsonl` with the real model (from `modelUsage`), four token columns and the cost delta against the base (B5). Warmth is reported only; nothing keeps a base warm (B6).
|
||||||
|
|
||||||
|
## Stopping a gremlin
|
||||||
|
|
||||||
|
Use `TaskStop` on the backgrounded Bash call (B4). That kills `claude` and its bash wrappers. Known leftover (spec §7): a command the gremlin had in flight (for example a long test run through its Bash) can survive as an orphan and run to its own end. After a hard stop, the job file may stay `running` with no ledger line. You know which calls you stopped, so `status` shows that record as it was written.
|
||||||
|
|
||||||
|
## Briefs carry the rules
|
||||||
|
|
||||||
|
The spawn template sets no commit rule. Each brief states whether that gremlin commits, which paths it may touch, and what its gate is. For gremlins that run in parallel, say "do not commit" and list the paths.
|
||||||
|
|
||||||
|
## State dir
|
||||||
|
|
||||||
|
`<run log without .md>-gremlins/`, next to the run log:
|
||||||
|
|
||||||
|
- `run.json` (written once by `init`), `mcp-empty.json`, `preamble.md` (a frozen copy, so the system prompt and the cache stay stable)
|
||||||
|
- `bases/<B>.json` (written by `train` and `rebase` only); `jobs/<J>.json` (each written by its own command)
|
||||||
|
- `ledger.jsonl` (one appended line per finished or stopped call)
|
||||||
|
- `raw/<J>.jsonl` (the stream) and `raw/<J>.err`; `briefs/<J>.md` (the full prompt sent)
|
||||||
|
- `notes/<J>.md` (the gremlins' handoff notes); `logs/` (their gate and test output)
|
||||||
|
|
||||||
|
## Cache hits
|
||||||
|
|
||||||
|
A fork hits the base's cache only with the same argv, the same pinned env, the same cwd and an unchanged system prompt. `spawn` reports `cache: hit|partial|miss`; a miss is reported, not an error. The env scrub removes Desktop, SDK and uv variables from every launch. The helper uses no platform-specific process code, and it runs on Windows Git Bash, WSL, Linux and macOS (B8).
|
||||||
Reference in New Issue
Block a user