@ethlete/agent-rules 0.1.0-next.30 → 0.1.0-next.31
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/CHANGELOG.md +17 -0
- package/content/hooks/context-warning.py +1 -0
- package/content/mods/plugins/e2e-progress/.claude-plugin/plugin.json +1 -1
- package/content/skills/agent-sessions/SKILL.md +1 -1
- package/content/skills/agent-sessions/agent-sessions.mjs +12 -6
- package/content/skills/codex-subagent/SKILL.md +8 -8
- package/content/skills/codex-subagent/codex-agent.mjs +1 -1
- package/content/skills/design-exploration/SKILL.md +31 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @ethlete/agent-rules
|
|
2
2
|
|
|
3
|
+
## 0.1.0-next.31
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- The design-exploration skill now describes the `ethlete-design` MCP server: its tools by job, when to use them instead of the `et design` CLI, and the `sketch_report` and `sketch_ready` rules.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- The Codex subagent skill lists gpt-6-luna, gpt-6.1-terra (the new default), gpt-6.1-sol and gpt-6-astra. The context hook gives gpt-6.1 a 500k pricing boundary.
|
|
12
|
+
- `agent-sessions restart` types the prompt after the clear even when a message woke the fresh session. Only typed text in its prompt holds the prompt back.
|
|
13
|
+
- The design exploration skill lists `et design sketch target add`.
|
|
14
|
+
- `agent-sessions restart` no longer reads the Claude Code IDE context chip (`[⧉ In file]`) on the prompt line as a draft, so it types the resume prompt after the clear.
|
|
15
|
+
- `control(markup, name)` from `@ethlete/components/design/control` renames a control that is already marked, so a design reuses a control part under its own control name.
|
|
16
|
+
- CONTROL-STATE counts an interaction word only as the last word of a state name, drops modifier words from the element name, and asks a component without controls to declare them (Q164).
|
|
17
|
+
- `et design check`, `sketch check`, `sketch ready` and `design complete` fail interaction states on a part that declares no control (`CONTROL-STATE`). `design complete` hints a state that changes under 10 % of its frame.
|
|
18
|
+
- Design checks report a drawn button, link, input or control role without `data-et-control` as `CONTROL-PART-INPUT`: a hint on merged parts, an error when a sketch adds one.
|
|
19
|
+
|
|
3
20
|
## 0.1.0-next.30
|
|
4
21
|
|
|
5
22
|
### Minor Changes
|
|
@@ -137,6 +137,7 @@ PREMIUM_BOUNDARY = 200_000
|
|
|
137
137
|
# Codex models whose long-context pricing starts above 272k input tokens. Models
|
|
138
138
|
# without that pricing rule use their reported context window instead.
|
|
139
139
|
CODEX_PREMIUM_BOUNDARIES = (
|
|
140
|
+
("gpt-6.1", 500_000),
|
|
140
141
|
("gpt-5.6", 272_000),
|
|
141
142
|
("gpt-5.5", 272_000),
|
|
142
143
|
("gpt-5.4-mini", None),
|
|
@@ -49,7 +49,7 @@ Nothing runs until you start it, so a person who does not use this does nothing.
|
|
|
49
49
|
|
|
50
50
|
`up codex=codex gemini=gemini` starts a detached `tmux` session per agent, named like its sender name, and runs the command in it. It also starts a session named `mailbox-dispatch` that runs `dispatch`. A running session is left alone. Attach to a session with `tmux attach -t <name>`. Detach with `Ctrl-b`, then `d`. The session and its agent keep running. Use `down` to stop the dispatcher and the named sessions.
|
|
51
51
|
|
|
52
|
-
`restart <name> <prompt...>` types the clear command (`/clear`, or `/new` for a `codex` name) and then the prompt into the session `<name>@<repo>`, no sooner than `--after` seconds (default 5). It waits until that session ended its turn and its prompt holds no typed text, and gives up after 30 minutes. The command returns at once, so end your turn after it. An agent uses it to clear itself and resume from its saved work state. It refuses any session other than the caller's own (from `$TMUX_PANE`), and the error names the caller's own sender name. Background commands of the old session still report into the new one.
|
|
52
|
+
`restart <name> <prompt...>` types the clear command (`/clear`, or `/new` for a `codex` name) and then the prompt into the session `<name>@<repo>`, no sooner than `--after` seconds (default 5). It waits until that session ended its turn and its prompt holds no typed text, and gives up after 30 minutes. After the clear, a new turn does not hold the prompt back: a message can wake the fresh session, and Claude Code queues input typed during a turn. Only typed text in its prompt holds the prompt back. After 60 seconds of typed text, it saves the prompt to `.ethlete/restart.prompt.<session>.txt` and logs why in `.ethlete/restart.log`. The command returns at once, so end your turn after it. An agent uses it to clear itself and resume from its saved work state. It refuses any session other than the caller's own (from `$TMUX_PANE`), and the error names the caller's own sender name. Background commands of the old session still report into the new one.
|
|
53
53
|
|
|
54
54
|
`shell-install` writes one shell function per agent into `~/.zshrc` or `~/.bashrc`, between two marker lines. A second run replaces the block, and `--remove` deletes it. Use `--file` for another startup file and `--dry-run` to preview. After a new terminal opens, typing `claude` or `codex` in a repo with this skill runs the agent through `run`. Elsewhere the function starts the plain command. Run `shell-install` only when the user asks: it changes a file the user owns. `shell-init` prints the same functions without writing a file.
|
|
55
55
|
|
|
@@ -116,14 +116,15 @@ const restartLog = (message) => {
|
|
|
116
116
|
|
|
117
117
|
/**
|
|
118
118
|
* Waits until the agent ended its turn and nobody types in its prompt, twice in a row; `false` after the time limit.
|
|
119
|
+
* With `allowBusy`, a running turn does not block, since Claude Code queues input typed during a turn.
|
|
119
120
|
* Each change of the reason it waits is logged to `restart.log` next to the mailbox.
|
|
120
121
|
*/
|
|
121
|
-
const waitForQuiet = (session, limitMs = RESTART_WAIT_MS) => {
|
|
122
|
+
const waitForQuiet = (session, limitMs = RESTART_WAIT_MS, allowBusy = false) => {
|
|
122
123
|
const end = Date.now() + limitMs;
|
|
123
124
|
let quiet = 0;
|
|
124
125
|
let reason = '';
|
|
125
126
|
while (Date.now() < end) {
|
|
126
|
-
const busy = busyLine(session);
|
|
127
|
+
const busy = allowBusy ? null : busyLine(session);
|
|
127
128
|
const draft = busy === null ? draftLine(session) : null;
|
|
128
129
|
const next = busy !== null ? `busy: ${busy.trim()}` : draft !== null ? `draft: ${draft}` : '';
|
|
129
130
|
if (next !== reason) restartLog(`${session} ${next ? `waits, ${next}` : 'is quiet'}`);
|
|
@@ -135,6 +136,8 @@ const waitForQuiet = (session, limitMs = RESTART_WAIT_MS) => {
|
|
|
135
136
|
return false;
|
|
136
137
|
};
|
|
137
138
|
|
|
139
|
+
/** The IDE context chip (`[⧉ In file.ts]`, `[⧉ 3 lines selected]`) shares the prompt line and survives `/clear`. */
|
|
140
|
+
const IDE_CHIP = /\[⧉ [^\]]*\]/g;
|
|
138
141
|
const draftLine = (session) => {
|
|
139
142
|
const pane = tmux('capture-pane', '-p', '-e', '-t', `=${session}:`).stdout ?? '';
|
|
140
143
|
const prompt = pane
|
|
@@ -155,7 +158,10 @@ const draftLine = (session) => {
|
|
|
155
158
|
return '';
|
|
156
159
|
})
|
|
157
160
|
.join('');
|
|
158
|
-
const text = visible
|
|
161
|
+
const text = visible
|
|
162
|
+
.replace(/^\s*[❯›]/, '')
|
|
163
|
+
.replace(IDE_CHIP, '')
|
|
164
|
+
.trim();
|
|
159
165
|
return text.length > 0 ? text : null;
|
|
160
166
|
};
|
|
161
167
|
const hasDraft = (session) => draftLine(session) !== null;
|
|
@@ -353,7 +359,7 @@ if (command === 'send' && sender) {
|
|
|
353
359
|
sleep(ENTER_DELAY_MS);
|
|
354
360
|
type('Enter');
|
|
355
361
|
sleep(RESTART_CLEAR_MS);
|
|
356
|
-
if (waitForQuiet(session, RESTART_CLEAR_WAIT_MS)) {
|
|
362
|
+
if (waitForQuiet(session, RESTART_CLEAR_WAIT_MS, true)) {
|
|
357
363
|
type('-l', words.join(' '));
|
|
358
364
|
sleep(ENTER_DELAY_MS);
|
|
359
365
|
type('Enter');
|
|
@@ -361,13 +367,13 @@ if (command === 'send' && sender) {
|
|
|
361
367
|
const saved = join(dirname(mailbox), `restart.prompt.${session}.txt`);
|
|
362
368
|
writeFileSync(saved, `${words.join(' ')}\n`);
|
|
363
369
|
restartLog(
|
|
364
|
-
`${session} not
|
|
370
|
+
`${session} prompt not empty ${RESTART_CLEAR_WAIT_MS / 1000}s after the clear, prompt not typed, saved to ${saved}`,
|
|
365
371
|
);
|
|
366
372
|
tmux(
|
|
367
373
|
'display-message',
|
|
368
374
|
'-t',
|
|
369
375
|
`=${session}:`,
|
|
370
|
-
`restart:
|
|
376
|
+
`restart: prompt not empty after the clear, prompt not typed. Saved to ${saved}`,
|
|
371
377
|
);
|
|
372
378
|
process.exitCode = 1;
|
|
373
379
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: codex-subagent
|
|
3
|
-
description: Delegate a task to a Codex agent (gpt-
|
|
3
|
+
description: Delegate a task to a Codex agent (gpt-6-luna, gpt-6.1-terra, gpt-6.1-sol, gpt-6-astra) instead of a Claude subagent - a second opinion from another model family, a review, or a cheap parallel lookup. Read before spawning a subagent when another model would answer better, and whenever the user says codex, GPT, or "second opinion".
|
|
4
4
|
kind: skill
|
|
5
5
|
scope: both
|
|
6
6
|
---
|
|
@@ -24,7 +24,7 @@ only the final message, so one run costs you a few hundred tokens instead of the
|
|
|
24
24
|
Below, `<skill-dir>` is the directory this file sits in.
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
node <skill-dir>/codex-agent.mjs -m gpt-
|
|
27
|
+
node <skill-dir>/codex-agent.mjs -m gpt-6.1-terra -e medium "<prompt>"
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Options: `-m` model, `-e` effort (`low`, `medium`, `high`, `xhigh`), `-C` working root,
|
|
@@ -36,12 +36,12 @@ id and the log path. Read the log only when a run fails.
|
|
|
36
36
|
|
|
37
37
|
## Pick the model
|
|
38
38
|
|
|
39
|
-
| Model | The work it fits
|
|
40
|
-
| --------------- |
|
|
41
|
-
| `gpt-
|
|
42
|
-
| `gpt-
|
|
43
|
-
| `gpt-
|
|
44
|
-
| `gpt-6-astra` | Complex, demanding work. The most expensive of the four, so ask the user before you pick it.
|
|
39
|
+
| Model | The work it fits |
|
|
40
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
41
|
+
| `gpt-6-luna` | Fast and cheap: a lookup, a grep, a question about one file. |
|
|
42
|
+
| `gpt-6.1-terra` | Balanced agentic coding. The default for real work, and the wrapper's default. |
|
|
43
|
+
| `gpt-6.1-sol` | A reliable workhorse for a straight task. Its usage limit runs out fast, so ask the user before you pick it. |
|
|
44
|
+
| `gpt-6-astra` | Complex, demanding work. The most expensive of the four, so ask the user before you pick it. |
|
|
45
45
|
|
|
46
46
|
Effort follows both the flag and the prompt. Pass `-e low` for a lookup and `-e high` for a
|
|
47
47
|
hard bug. Say "keep it brief" in the prompt when you want a short answer.
|
|
@@ -14,7 +14,7 @@ import { tmpdir } from 'node:os';
|
|
|
14
14
|
import { join } from 'node:path';
|
|
15
15
|
import { createInterface } from 'node:readline';
|
|
16
16
|
|
|
17
|
-
const DEFAULT_MODEL = 'gpt-
|
|
17
|
+
const DEFAULT_MODEL = 'gpt-6.1-terra';
|
|
18
18
|
const DEFAULT_TIMEOUT_SECONDS = 900;
|
|
19
19
|
|
|
20
20
|
const USAGE = `Usage: node codex-agent.mjs [options] "<prompt>"
|
|
@@ -122,6 +122,7 @@ answers. Variants are drawn at the same geometry, and one variant wins only agai
|
|
|
122
122
|
```bash
|
|
123
123
|
et design sketch new <layer>/<name> --variants a,b --by <model id> [--like <layer>/<name>] [--variant-note a=<text>]… [--product <p>] # each variant starts as a copy of the part
|
|
124
124
|
et design sketch new <layer>/<name> <layer>/<name>… --variants a --by <model id> # one change across several parts: one sketch, one ready, one merge
|
|
125
|
+
et design sketch target add <layer>/<name> <layer>/<name> --by <model id> # add a part to an open sketch's targets, seeded into each variant
|
|
125
126
|
et design sketch report <layer>/<name> --variant b --by <model id> "phone" # tell Studio what you build now
|
|
126
127
|
et design sketch report <layer>/<name> --variant b --by <model id> --done # you stopped drawing b; Studio shows its frames
|
|
127
128
|
et design sketch check [<layer>/<name>] [--fix] # each variant laid over the product
|
|
@@ -255,7 +256,7 @@ in progress) and `sketch release` it once the change is in.
|
|
|
255
256
|
|
|
256
257
|
Every command that writes takes `--by <model id>` and fails without it: `sketch new`, `variant`, `report`,
|
|
257
258
|
`ready`, `rebase`, `merge`, `discard`, `inbox done` and `comment reply`. The id is the exact model
|
|
258
|
-
id as free text, for example `claude-opus-5-5`, `gpt-
|
|
259
|
+
id as free text, for example `claude-opus-5-5`, `gpt-6.1-sol` or `gemini-3-argon`. Studio shows it
|
|
259
260
|
on the variant, the reply and the part, so the user sees which model made what.
|
|
260
261
|
|
|
261
262
|
**Never guess your id.** Use the one your prompt names. If your prompt names none and you do not
|
|
@@ -308,6 +309,27 @@ Pass `--question` only when you cannot go on without the user's answer. Studio l
|
|
|
308
309
|
threads under "Questions for you". A report of what you did is no question: reply without the
|
|
309
310
|
flag, and the thread shows as "answered" until the user withdraws it or replies.
|
|
310
311
|
|
|
312
|
+
### The `ethlete-design` MCP server
|
|
313
|
+
|
|
314
|
+
`ethlete-agents sync` registers `et design mcp` as `ethlete-design` in `.mcp.json` and
|
|
315
|
+
`.codex/config.toml` when `@ethlete/cli` is installed. When the tools are in your tool list, use them
|
|
316
|
+
instead of the CLI: each runs the `et design` command of the same name in the session's working
|
|
317
|
+
directory, takes its flags as arguments, and every write takes `by` (your model id). `product` may be
|
|
318
|
+
left out when the workspace has one. `shot` and `motion_shots` return the sheet image itself, so you
|
|
319
|
+
look at it without opening a PNG path.
|
|
320
|
+
|
|
321
|
+
- **Read:** `parts` (every part, as JSON), `call` (a call's `call.ts`, `fixture.ts`, the variant file to draw into and the frame URL; never change the fixture).
|
|
322
|
+
- **Check:** `check` (a product; with `call` and `variant` it lints, type-checks and renders that variant - run it after every edit of a variant), `sketch_check` (each variant laid over the product), `sketch_preview` (what a merge of a variant changes).
|
|
323
|
+
- **Shots:** `shot` (a part's states, `variants` for the open sketch), `motion_shots` (a motion at its keyframes, full and reduced, plus its tracks as JSON).
|
|
324
|
+
- **Sketch lifecycle:** `sketch_new`, `sketch_variant`, `sketch_round`, `sketch_report`, `sketch_ready`, `sketch_rebase`, `sketch_list`. `sketch_merge` and `sketch_discard` exist, but Studio runs them on the user's click; do not call them.
|
|
325
|
+
- **Comments:** `inbox` (what waits for you, then for the user), `comment_reply` (`question` waits for the user's answer), `inbox_done` (needs the new part `note`).
|
|
326
|
+
|
|
327
|
+
Part files are written with your own file tools; the server has no write tool for them. Call
|
|
328
|
+
`sketch_report` before every variant edit: it tells Studio what you build, and it moves a `ready`
|
|
329
|
+
sketch back to in progress, so call `sketch_ready` again when you are done. `sketch_ready` runs the
|
|
330
|
+
render check and refuses on any render issue; mark an element that renders wrong on purpose with
|
|
331
|
+
`data-et-skip="<rule>"`. A tool that fails returns the CLI's output; fix it and call again.
|
|
332
|
+
|
|
311
333
|
### Draw a flow
|
|
312
334
|
|
|
313
335
|
A flow joins states of pages into a path the user reads left to right in Studio's Flows view.
|
|
@@ -527,6 +549,14 @@ When each of several cases is drawn at rest and in the same interactions, build
|
|
|
527
549
|
from `@design-system` and spread the result into `definePart`; never write those states and the grid by hand.
|
|
528
550
|
`sketch check` prints `grid <rows> x <columns> ok`, or the states the grid leaves out; a state in two cells
|
|
529
551
|
fails it as `GRID`, in `design check` too.
|
|
552
|
+
Interaction states (a state name whose last word is hover, focus, pressed, active or selected, such as `row-hover`) live only on a control
|
|
553
|
+
part, one whose `controls` declare a control of a checked kind. On a shell, element or page they fail as
|
|
554
|
+
`CONTROL-STATE`: declare the component's controls (Q164), or extract the button or row as its own control part and draw its states there.
|
|
555
|
+
A drawn `button`, `a[href]`, `input`, `select`, `textarea` or control role without `data-et-control` on it or around
|
|
556
|
+
it is `CONTROL-PART-INPUT`: no control check sees it. Wrap it in `control(markup, name)` from
|
|
557
|
+
`@ethlete/components/design/control` and declare the name in `controls`; a sketch fails on one it adds,
|
|
558
|
+
`design check` only warns of one a merged part already draws. On a reused control part's render,
|
|
559
|
+
`control(drawn.body, name)` renames its control: never string-replace `data-et-control`.
|
|
530
560
|
`definePart({ interactions })` forces an interaction on the part's root only. To draw one element of the part
|
|
531
561
|
hovered, focused, pressed or disabled, such as one row of a list, wrap that element's markup in
|
|
532
562
|
`forceInteraction(markup, 'hover')` from `@design-system` inside `render`, driven by a prop; never write
|