@zenera/cli 1.1.24 → 1.1.25
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/README.md +53 -0
- package/dist/ask.js +28 -5
- package/dist/banner.js +2 -2
- package/dist/batch.d.ts +6 -0
- package/dist/batch.js +76 -1
- package/dist/catalog.d.ts +11 -1
- package/dist/catalog.js +80 -7
- package/dist/commands/inspect.d.ts +47 -1
- package/dist/commands/inspect.js +167 -18
- package/dist/commands/memory.js +128 -29
- package/dist/commands/meta.js +311 -21
- package/dist/commands/models.js +96 -12
- package/dist/commands/open.js +4 -4
- package/dist/commands/run.js +38 -4
- package/dist/commands/sandbox.js +76 -14
- package/dist/engine.d.ts +5 -0
- package/dist/engine.js +1 -0
- package/dist/eventlog.d.ts +59 -0
- package/dist/eventlog.js +146 -0
- package/dist/liveness.d.ts +7 -0
- package/dist/liveness.js +15 -1
- package/dist/meta/editor.d.ts +9 -0
- package/dist/meta/editor.js +60 -0
- package/dist/meta/finetune/children.d.ts +8 -0
- package/dist/meta/finetune/children.js +76 -0
- package/dist/meta/finetune/command.d.ts +30 -0
- package/dist/meta/finetune/command.js +338 -0
- package/dist/meta/finetune/dataset/anchors.d.ts +41 -0
- package/dist/meta/finetune/dataset/anchors.js +239 -0
- package/dist/meta/finetune/dataset/changes.d.ts +36 -0
- package/dist/meta/finetune/dataset/changes.js +319 -0
- package/dist/meta/finetune/dataset/command.d.ts +17 -0
- package/dist/meta/finetune/dataset/command.js +1011 -0
- package/dist/meta/finetune/dataset/drift.d.ts +33 -0
- package/dist/meta/finetune/dataset/drift.js +71 -0
- package/dist/meta/finetune/dataset/export.d.ts +26 -0
- package/dist/meta/finetune/dataset/export.js +51 -0
- package/dist/meta/finetune/dataset/index.d.ts +2 -0
- package/dist/meta/finetune/dataset/index.js +2 -0
- package/dist/meta/finetune/dataset/sample.d.ts +50 -0
- package/dist/meta/finetune/dataset/sample.js +197 -0
- package/dist/meta/finetune/dataset/schema.d.ts +33 -0
- package/dist/meta/finetune/dataset/schema.js +216 -0
- package/dist/meta/finetune/dataset/store.d.ts +35 -0
- package/dist/meta/finetune/dataset/store.js +177 -0
- package/dist/meta/finetune/dataset/types.d.ts +125 -0
- package/dist/meta/finetune/dataset/types.js +39 -0
- package/dist/meta/finetune/failure.d.ts +15 -0
- package/dist/meta/finetune/failure.js +26 -0
- package/dist/meta/finetune/feedback.d.ts +45 -0
- package/dist/meta/finetune/feedback.js +85 -0
- package/dist/meta/finetune/improvements.d.ts +51 -0
- package/dist/meta/finetune/improvements.js +244 -0
- package/dist/meta/finetune/index.d.ts +2 -0
- package/dist/meta/finetune/index.js +2 -0
- package/dist/meta/finetune/journal.d.ts +35 -0
- package/dist/meta/finetune/journal.js +135 -0
- package/dist/meta/finetune/live.d.ts +74 -0
- package/dist/meta/finetune/live.js +226 -0
- package/dist/meta/finetune/loop.d.ts +3 -0
- package/dist/meta/finetune/loop.js +114 -0
- package/dist/meta/finetune/memories.d.ts +47 -0
- package/dist/meta/finetune/memories.js +154 -0
- package/dist/meta/finetune/report.d.ts +33 -0
- package/dist/meta/finetune/report.js +1284 -0
- package/dist/meta/finetune/retry.d.ts +24 -0
- package/dist/meta/finetune/retry.js +96 -0
- package/dist/meta/finetune/sampler.d.ts +18 -0
- package/dist/meta/finetune/sampler.js +41 -0
- package/dist/meta/finetune/system.d.ts +27 -0
- package/dist/meta/finetune/system.js +132 -0
- package/dist/meta/finetune/train.d.ts +39 -0
- package/dist/meta/finetune/train.js +391 -0
- package/dist/meta/finetune/tui.d.ts +16 -0
- package/dist/meta/finetune/tui.js +291 -0
- package/dist/meta/finetune/tuning.d.ts +167 -0
- package/dist/meta/finetune/tuning.js +289 -0
- package/dist/meta/finetune/usage.d.ts +62 -0
- package/dist/meta/finetune/usage.js +225 -0
- package/dist/meta/host.d.ts +14 -0
- package/dist/meta/host.js +20 -0
- package/dist/meta/index.d.ts +11 -0
- package/dist/meta/index.js +11 -0
- package/dist/meta/launch.d.ts +81 -0
- package/dist/meta/launch.js +286 -0
- package/dist/meta/model.d.ts +44 -0
- package/dist/meta/model.js +119 -0
- package/dist/meta/prompts.d.ts +18 -0
- package/dist/meta/prompts.js +61 -0
- package/dist/meta/relay.d.ts +20 -0
- package/dist/meta/relay.js +123 -0
- package/dist/meta/tokens.d.ts +52 -0
- package/dist/meta/tokens.js +226 -0
- package/dist/meta/window.d.ts +61 -0
- package/dist/meta/window.js +198 -0
- package/dist/meta/wire.d.ts +42 -0
- package/dist/meta/wire.js +129 -0
- package/dist/modelref.d.ts +16 -0
- package/dist/modelref.js +41 -0
- package/dist/narrate.js +5 -2
- package/dist/podman.d.ts +26 -0
- package/dist/podman.js +83 -3
- package/dist/projects.d.ts +0 -5
- package/dist/projects.js +2 -15
- package/dist/sandbox.d.ts +2 -0
- package/dist/sandbox.js +10 -3
- package/dist/scaffold.d.ts +15 -6
- package/dist/scaffold.js +5 -60
- package/dist/session.js +4 -29
- package/dist/term.d.ts +2 -0
- package/dist/term.js +11 -2
- package/dist/trace.js +53 -2
- package/dist/tui/models.d.ts +33 -0
- package/dist/tui/models.js +389 -0
- package/dist/tui/wrap.d.ts +5 -0
- package/dist/tui/wrap.js +12 -0
- package/dist/usage.d.ts +78 -0
- package/dist/usage.js +51 -0
- package/package.json +3 -2
- package/templates/editor/.github/copilot-instructions.md +31 -102
- package/templates/editor/.github/prompts/analyze.prompt.md +31 -0
- package/templates/editor/.github/prompts/dataset.prompt.md +108 -0
- package/templates/editor/.github/prompts/finetune-apply.prompt.md +91 -0
- package/templates/editor/.github/prompts/finetune.prompt.md +691 -198
- package/templates/editor/.github/prompts/new-agent.prompt.md +3 -1
- package/templates/editor/.github/prompts/new-skill.prompt.md +2 -0
- package/templates/editor/.github/prompts/project-review.prompt.md +4 -3
- package/templates/editor/.github/skills/zen-analyze-run/SKILL.md +483 -0
- package/templates/editor/.github/skills/zen-cli/SKILL.md +9 -1
- package/templates/editor/.github/skills/zen-cli/references/dataset.md +34 -0
- package/templates/editor/.github/skills/zen-cli/references/finetune.md +77 -0
- package/templates/editor/.github/skills/zen-cli/references/inspect.md +47 -9
- package/templates/editor/.github/skills/zen-cli/references/memory.md +33 -10
- package/templates/editor/.github/skills/zen-cli/references/meta.md +61 -0
- package/templates/editor/.github/skills/zen-cli/references/models.md +5 -1
- package/templates/editor/.github/skills/zen-cli/references/rag.md +24 -6
- package/templates/editor/.github/skills/zen-cli/references/sandbox.md +10 -1
- package/templates/editor/.github/skills/zen-code-python/SKILL.md +123 -0
- package/templates/editor/.github/skills/zen-code-python/references/code_python.md +48 -0
- package/templates/editor/.github/skills/zen-dataset/SKILL.md +253 -0
- package/templates/editor/.github/skills/zen-finetune/SKILL.md +1449 -658
- package/templates/editor/.github/skills/zen-finetune/references/readme-template.md +268 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/batch.mjs +390 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/difficult.mjs +243 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/memory.mjs +280 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/next.mjs +398 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/report.mjs +797 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/select.mjs +354 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/usage.mjs +722 -0
- package/templates/editor/.github/skills/zen-inspect/SKILL.md +60 -25
- package/templates/editor/.github/skills/zen-inspect-ask/SKILL.md +270 -0
- package/templates/editor/.github/skills/zen-memory/SKILL.md +18 -14
- package/templates/editor/.github/skills/zen-rag-docs/SKILL.md +20 -8
- package/templates/editor/.github/skills/zen-review/SKILL.md +5 -3
- package/templates/editor/.github/skills/zen-review/scripts/check-paths.sh +5 -4
- package/templates/editor/.github/skills/zen-sandbox/SKILL.md +7 -3
- package/templates/editor/.github/skills/zen-sandbox-capacity/SKILL.md +2 -2
- package/templates/editor/.github/skills/zen-topology/SKILL.md +283 -0
- package/templates/editor/.vscode/settings.json +1 -0
- package/templates/project/agents/files-instructions.md +29 -20
- package/templates/project/agents/memory-instructions.md +31 -32
- package/templates/project/agents/tools-instructions.md +7 -4
- package/templates/project/gitignore +2 -0
- package/dist/meta.d.ts +0 -221
- package/dist/meta.js +0 -684
- package/templates/editor/.github/skills/zen-finetune/scripts/collect.sh +0 -432
- package/templates/editor/.github/skills/zen-finetune/scripts/sample.sh +0 -199
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# `zen meta finetune` - tuning the project, one case at a time
|
|
2
|
+
|
|
3
|
+
Trains the project's prose - prompts, skills, house rules - on every case of
|
|
4
|
+
its dataset (`zen meta dataset`). Nothing here touches model weights.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
zen meta finetune start [-N 4] [-M 4] [--tries 4] [--mem-tries 3] [--merge-every 3] [--seed 1] \
|
|
8
|
+
[--class <c>] [--id <glob>] [--rubric yes|no] [--limit <n>] [--force]
|
|
9
|
+
zen meta finetune [status]
|
|
10
|
+
zen meta finetune stop
|
|
11
|
+
zen meta finetune session <case>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## What one case goes through
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
without memory, up to --tries times:
|
|
18
|
+
zen run (empty memory) -> /analyze -> done? go on : park until the next apply
|
|
19
|
+
with memory, up to --mem-tries times, from the memory the passing run wrote:
|
|
20
|
+
zen run -> /analyze -> done? completed : park until the next apply
|
|
21
|
+
tries used up -> difficult
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- **N workers**, each training one case at a time. Cases come in the dataset's
|
|
25
|
+
own order: classes taking turns, cases with a rubric first, then seeded
|
|
26
|
+
random. Cases added to the dataset are picked up as it goes.
|
|
27
|
+
- **A parked case gives its worker back**, so another case runs while it waits
|
|
28
|
+
for an apply; once woken, it takes a worker before any new case does.
|
|
29
|
+
- **Applies are batched.** Parked cases' improvement requests are applied
|
|
30
|
+
together by `/finetune-apply` once **M** cases are parked, or once nothing is
|
|
31
|
+
running and no case is left to start. No run starts during an apply; runs in flight finish
|
|
32
|
+
first. `zen check` must pass afterwards, or the edit is undone and tried once
|
|
33
|
+
more; a second failure stops the tuning. Each apply gets its own
|
|
34
|
+
`applies/<NNN>/APPLY.md`: every request and improvement, what was decided for
|
|
35
|
+
each, the apply agent's account of what it changed and why, every file
|
|
36
|
+
changed with its diff, and the `zen check` result.
|
|
37
|
+
- **No run shares a memory.** Every try runs on its own private directory:
|
|
38
|
+
empty without memory, a copy of the case's passing memory with it. A case
|
|
39
|
+
whose with-memory run passes keeps a copy in `memories/submitted/`; every
|
|
40
|
+
`--merge-every` kept memories are merged, with the last merge, into
|
|
41
|
+
`memories/merged/mNN/` - numbered, never rewritten, each listing the cases it
|
|
42
|
+
holds. Whatever is left is merged when the tuning ends.
|
|
43
|
+
- **Each case keeps one analyze session**, so every analysis of it remembers
|
|
44
|
+
the earlier tries. `session <case>` prints the command to resume it.
|
|
45
|
+
- **Stop and resume freely.** `stop` (or Ctrl-C once) lets the steps in flight
|
|
46
|
+
finish, then exits; Ctrl-C twice kills them. `start` again carries on: every
|
|
47
|
+
step's result is on disk, and nothing finished is repeated.
|
|
48
|
+
- `start` refuses a dataset that has drifted from its sources - run `/dataset`
|
|
49
|
+
first, or pass `--force`.
|
|
50
|
+
|
|
51
|
+
## What it leaves
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
finetune/
|
|
55
|
+
STATUS.md the whole tuning: summary (spend per phase, tuning and memory
|
|
56
|
+
effect), workers, queue, applies, cases - generated
|
|
57
|
+
loop.json the settings; flags on start update it
|
|
58
|
+
events.jsonl every step, in order
|
|
59
|
+
cases/<id>/
|
|
60
|
+
FEEDBACK.md that case: rubric, latest analysis, decisions, history, metrics
|
|
61
|
+
of every try and how they moved - generated
|
|
62
|
+
r<rev>/session its analyze session
|
|
63
|
+
r<rev>/result.json completed or difficult, once it ends
|
|
64
|
+
r<rev>/<NN>-<nomem|mem>/ one try: request.json, run.json, memory/,
|
|
65
|
+
feedback.json, analysis.md, run.log, analyze.log
|
|
66
|
+
applies/<NNN>/ APPLY.md (generated), inputs.json, apply.log, check.log, changes.md,
|
|
67
|
+
decisions.json, diff.patch
|
|
68
|
+
memories/ submissions.jsonl, merges.jsonl, submitted/<case>@r<rev>/, merged/mNN/
|
|
69
|
+
systems/ systems.jsonl + a copy of agents.yaml and agents/ per version
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Open `STATUS.md` first; every row links to the detail behind it. Its Summary
|
|
73
|
+
says whether the tuning is working: the fixes, as a case's first try without
|
|
74
|
+
memory against its passing one, and memory, as the passing try without memory
|
|
75
|
+
against the passing try with it - tokens, calls, tool errors and time, totalled
|
|
76
|
+
over the same cases. A case's `FEEDBACK.md` has the same metrics per try and per
|
|
77
|
+
model, each try against the one before it in its phase.
|
|
@@ -13,7 +13,8 @@ Four ways to read one run, for two different readers.
|
|
|
13
13
|
| `report` | you | `report.html` - every message, payload and cost |
|
|
14
14
|
| `graph` | a model | the whole trajectory as one Mermaid flowchart |
|
|
15
15
|
| `node <id...>` | a model | those nodes in full, payloads resolved |
|
|
16
|
-
| `ask <id> <question>` |
|
|
16
|
+
| `ask <id> <question>` | a model | one replayed answer on stdout; never prompts |
|
|
17
|
+
| `ask [<id>]` | you | a conversation with that call, at a terminal |
|
|
17
18
|
|
|
18
19
|
`report` is the default, so `zen inspect` on its own is unchanged.
|
|
19
20
|
|
|
@@ -26,6 +27,7 @@ Four ways to read one run, for two different readers.
|
|
|
26
27
|
| `--dir <dir>` | all | A run directory, as `zen run --json` reports it |
|
|
27
28
|
| `--memory <dir>` | report, graph | Read this memory instead of the one the run recorded |
|
|
28
29
|
| `--model <ref>` | ask | Answer with this model instead of the run's own |
|
|
30
|
+
| `--question-file <f>` | ask | Read the question from a file; `-` is stdin |
|
|
29
31
|
| `--part <name>` | node | Print this part in full. Repeatable, prefix-matched |
|
|
30
32
|
| `--full` | node | Print every part, the recorded `request` included |
|
|
31
33
|
| `--open` | report | Open the report in a browser |
|
|
@@ -39,10 +41,13 @@ session that has one. "Newest" means the newest session that actually recorded a
|
|
|
39
41
|
run, not simply the newest session: a session exists before its first run, so
|
|
40
42
|
the latest one is routinely empty.
|
|
41
43
|
|
|
42
|
-
**Neither `node` nor `ask` has room for a run.** Every positional
|
|
43
|
-
a node id, and `ask` takes
|
|
44
|
-
|
|
45
|
-
as an id and fails.
|
|
44
|
+
**Neither `node` nor `ask` has room for a positional run.** Every positional
|
|
45
|
+
`node` takes is a node id, and every positional `ask` takes is the id followed
|
|
46
|
+
by the question, so name the run with `--run`, `--session` or `--dir`.
|
|
47
|
+
`zen inspect node <run> n13` reads the run id as an id and fails. `ask`
|
|
48
|
+
without a question is the interactive mode (below) and needs a terminal; a
|
|
49
|
+
script, `--json` call or agent passes the id and the question and never sees a
|
|
50
|
+
prompt.
|
|
46
51
|
|
|
47
52
|
For `report` and `graph` the positional is a run id unless it contains a `/`, in
|
|
48
53
|
which case it is read as a run directory. A run id is a stamp and never has a
|
|
@@ -100,13 +105,13 @@ zen inspect graph --dir "$(zen run --json 'fix the tests' | jq -r .run.dir)"
|
|
|
100
105
|
%% n24 joins docs (researcher, ok), tests (researcher, ok)
|
|
101
106
|
%% compacted 3 nodes are marked "hidden by" a later summary
|
|
102
107
|
%% they still ran; the model simply stopped seeing them
|
|
103
|
-
%%
|
|
108
|
+
%% ---
|
|
104
109
|
%% reading nN is a node id · t+ counts from the start of the turn
|
|
105
110
|
%% dotted edges are fork/join and calls answered out of order
|
|
106
111
|
%% nodes are declared in run order; every edge is in one block below
|
|
107
112
|
%% detail zen inspect node n1 n2 n5..n9 --dir <run dir>
|
|
108
113
|
%% why zen inspect ask n5 "why did you do that?" --dir <run dir>
|
|
109
|
-
%%
|
|
114
|
+
%% ---
|
|
110
115
|
flowchart TD
|
|
111
116
|
n11["n11 llm claude-opus-5 · 4.2k in 310 out · calls run_command · t+32.7s"]
|
|
112
117
|
n12["n12 run_command npm test -- --run · t+34.7s · took 3.0s"]
|
|
@@ -214,10 +219,43 @@ ready to paste.
|
|
|
214
219
|
|
|
215
220
|
`node` shows what a model was given. `ask` asks the model what it made of it.
|
|
216
221
|
|
|
222
|
+
`ask` has two modes, and which one runs is decided by one thing: whether the
|
|
223
|
+
question is given.
|
|
224
|
+
|
|
225
|
+
| Mode | Trigger | For | Behaviour |
|
|
226
|
+
| ----------- | ------------------------------------------------------ | ---------------------- | ------------------------------------------------------------------------------------------------ |
|
|
227
|
+
| One-shot | a question on the line, `--question-file`, or `--json` | a script or a model | no banner, no prompt, no picker; one model call, the raw answer on stdout and nothing else, exit |
|
|
228
|
+
| Interactive | no question | a person at a terminal | asks for whatever is not named - session, run, `llm_call` - then the question; a conversation |
|
|
229
|
+
|
|
230
|
+
One-shot never reads the terminal, even when there is one: an unnamed run is
|
|
231
|
+
the newest, not a picker, so name it with `--dir`, `--run` or `--session`.
|
|
232
|
+
Interactive without a terminal is a usage error, never a wait.
|
|
233
|
+
|
|
217
234
|
```sh
|
|
218
235
|
zen inspect ask n11 "why run python -c when the skill says npm test?" --dir <run dir>
|
|
219
236
|
```
|
|
220
237
|
|
|
238
|
+
In the interactive mode only calls with a recorded request appear in the node
|
|
239
|
+
list. Each question and Markdown answer is drawn in its own labelled panel, with
|
|
240
|
+
the model and token counts on stderr. It keeps asking on the same node,
|
|
241
|
+
retaining earlier exchanges as context, until an empty question is submitted.
|
|
242
|
+
|
|
243
|
+
```sh
|
|
244
|
+
zen inspect ask # pick everything
|
|
245
|
+
zen inspect ask n11 --dir <run dir> # straight to the questions
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
A question with quotes, apostrophes, backticks, `$` or more than one line goes
|
|
249
|
+
in a file, so no shell parses it. The file is the whole question; `-` reads it
|
|
250
|
+
from stdin. Words on the line as well are an error.
|
|
251
|
+
|
|
252
|
+
```sh
|
|
253
|
+
zen inspect ask n11 --question-file .tmp/ask/<run-id>/n11-tests.md --dir <run dir>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Do not build the question with `"$(cat <<'EOF' ... )"`: macOS `/bin/bash` 3.2
|
|
257
|
+
misparses a heredoc inside `$( )` when its body holds an apostrophe.
|
|
258
|
+
|
|
221
259
|
The `llm_call` node named by the id is replayed: its recorded system prompt, its
|
|
222
260
|
messages and its tool schemas, exactly as the provider received them, with the
|
|
223
261
|
answer it gave put back as its own turn and your question as one more after
|
|
@@ -247,8 +285,8 @@ command says so on stderr, because an answer from a different model is a second
|
|
|
247
285
|
opinion rather than the model examining itself. Either way the run's full system
|
|
248
286
|
prompt goes to that provider.
|
|
249
287
|
|
|
250
|
-
`graph`, `node` and `ask` print no banner. Their stdout is the
|
|
251
|
-
ready to paste.
|
|
288
|
+
`graph`, `node` and non-interactive `ask` print no banner. Their stdout is the
|
|
289
|
+
answer, whole and ready to paste.
|
|
252
290
|
|
|
253
291
|
## Where it comes from
|
|
254
292
|
|
|
@@ -18,16 +18,21 @@ skill.
|
|
|
18
18
|
|
|
19
19
|
## Subcommands
|
|
20
20
|
|
|
21
|
-
| Command | What it does
|
|
22
|
-
| ------------------------- |
|
|
23
|
-
| `zen memory stats` | Size, vocabulary, whether it is embedded
|
|
24
|
-
| `zen memory ls` | Nodes, newest first
|
|
25
|
-
| `zen memory search <q>` | Recall it, the way an agent does. Ranked
|
|
26
|
-
| `zen memory grep <pat>` | Every node containing it, with the lines
|
|
27
|
-
| `zen memory show <id>` | One node in full, with what it links to
|
|
28
|
-
| `zen memory
|
|
29
|
-
| `zen memory
|
|
30
|
-
| `zen memory
|
|
21
|
+
| Command | What it does |
|
|
22
|
+
| ------------------------- | --------------------------------------------------- |
|
|
23
|
+
| `zen memory stats` | Size, vocabulary, whether it is embedded |
|
|
24
|
+
| `zen memory ls` | Nodes, newest first: kind, audience, revision, text |
|
|
25
|
+
| `zen memory search <q>` | Recall it, the way an agent does. Ranked |
|
|
26
|
+
| `zen memory grep <pat>` | Every node containing it, with the lines |
|
|
27
|
+
| `zen memory show <id>` | One node in full, with what it links to |
|
|
28
|
+
| `zen memory diff <base>` | What this memory holds that `<base>` did not |
|
|
29
|
+
| `zen memory export [f]` | The whole graph as one HTML page |
|
|
30
|
+
| `zen memory merge <dir…>` | Fold other memories into this one |
|
|
31
|
+
| `zen memory forget <id…>` | Remove nodes, their vectors and their files |
|
|
32
|
+
|
|
33
|
+
`ls` cuts the text to the terminal's width; piped, or run by an agent, it prints
|
|
34
|
+
all of it. Never read `graph.json` directly - `ls --json` is the same nodes in a
|
|
35
|
+
shape that does not change under you.
|
|
31
36
|
|
|
32
37
|
| Flag | Meaning |
|
|
33
38
|
| ----------------------------- | ---------------------------------------------- |
|
|
@@ -99,6 +104,24 @@ remembered file it could not read - too big, binary, missing - is named rather
|
|
|
99
104
|
than silently skipped, because a file that went unsearched must not pass for one
|
|
100
105
|
with no match.
|
|
101
106
|
|
|
107
|
+
## `diff` says what a run did to a copy
|
|
108
|
+
|
|
109
|
+
A run started from a copy of a memory leaves the whole copy behind, so `ls` on
|
|
110
|
+
it shows everything the base held too. `diff` shows only what changed:
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
zen memory diff <candidate> --dir <batch-dir>/<id>/memory
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- **added** - each with the nearest node `<base>` held and its score. One
|
|
117
|
+
`merge` would fold onto it is marked a twin: the run said again what the
|
|
118
|
+
memory already held.
|
|
119
|
+
- **revised** - same id, new revision.
|
|
120
|
+
- **used** - nodes `memory_load` returned, and how often: what the run read.
|
|
121
|
+
- **removed**, and new `SUPERSEDES` edges.
|
|
122
|
+
|
|
123
|
+
It reads both sides without the lock, so it works on a memory a run is writing.
|
|
124
|
+
|
|
102
125
|
Superseded nodes are left out unless you ask: `--all` includes them marked, and
|
|
103
126
|
`--stale` narrows to them alone.
|
|
104
127
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# `zen meta` - the meta agent, on this project
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
zen meta run [project] "<question>" ask it something
|
|
5
|
+
zen meta run [project] /<name> [words] run .github/prompts/<name>.prompt.md
|
|
6
|
+
zen meta prompts [project] list the stored prompts
|
|
7
|
+
zen meta resume [project] [session] carry on a run that stopped
|
|
8
|
+
zen meta model [ref] show or set the model it uses
|
|
9
|
+
zen meta dataset <verb> see dataset.md
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`zen meta --help` has every option.
|
|
13
|
+
|
|
14
|
+
## `--json`
|
|
15
|
+
|
|
16
|
+
`zen meta run --json` prints ONE object on stdout when the run ends:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"project": "/path/to/project",
|
|
21
|
+
"provider": "vertex",
|
|
22
|
+
"model": "vertex/gemini-3.8-flash",
|
|
23
|
+
"sessionId": "…",
|
|
24
|
+
"exitCode": 0,
|
|
25
|
+
"resumes": 0,
|
|
26
|
+
"usage": {},
|
|
27
|
+
"tokens": {
|
|
28
|
+
"calls": 12,
|
|
29
|
+
"inputTokens": 0,
|
|
30
|
+
"cachedInputTokens": 0,
|
|
31
|
+
"outputTokens": 0,
|
|
32
|
+
"reasoningTokens": 0
|
|
33
|
+
},
|
|
34
|
+
"answer": "the final answer, as markdown",
|
|
35
|
+
"answerFile": "/path/to/project/.tmp/logs/meta.<when>.md"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`tokens` is summed over every model call of the run; `usage` is the meta
|
|
40
|
+
agent's own end-of-session summary, passed through as it came, and may be absent.
|
|
41
|
+
|
|
42
|
+
- Progress goes to stderr as plain lines: no box, no animation, no status row.
|
|
43
|
+
stdout carries the object and nothing else, so redirect it to keep it:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
zen meta run acme /analyze --json > analyze.json
|
|
47
|
+
zen meta run acme /analyze --json > analyze.json 2> analyze.log
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- Nothing is asked. A `run` with no question, no `/<name>` and nothing piped
|
|
51
|
+
in is a usage error (exit 2) that lists the prompts, not a menu.
|
|
52
|
+
- A run the meta agent ends in failure still prints the object, then exits 1.
|
|
53
|
+
Check `exitCode`; `sessionId` is what `zen meta resume` takes. A run that
|
|
54
|
+
never starts (no key, bad model) prints no object, only the error.
|
|
55
|
+
- `--dry-run --json` gives `{project, provider, model, from, command, env}`,
|
|
56
|
+
secrets masked, and runs nothing.
|
|
57
|
+
- `zen meta prompts --json` gives `[{name, description, path}]`;
|
|
58
|
+
`zen meta model --json` gives `{model, from, sources}`.
|
|
59
|
+
|
|
60
|
+
The answer is also saved as markdown on every run, with or without `--json`;
|
|
61
|
+
`answerFile` is its path.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Models - `zen models`
|
|
2
2
|
|
|
3
3
|
```
|
|
4
|
-
zen models <providers|ls|search|show|test|pick> [ref] [options]
|
|
4
|
+
zen models <providers|ls|search|show|test|pick|browse> [ref] [options]
|
|
5
5
|
```
|
|
6
6
|
|
|
7
7
|
Alias: `model`.
|
|
@@ -21,6 +21,7 @@ but a credential.
|
|
|
21
21
|
| `zen models show <ref>` | One model, every field the vendor gave |
|
|
22
22
|
| `zen models test <ref> …` | One real minimal call per ref, and a verdict |
|
|
23
23
|
| `zen models pick` | The first ref that answers, printed on stdout |
|
|
24
|
+
| `zen models browse` | Interactive TUI for a person; needs a terminal |
|
|
24
25
|
|
|
25
26
|
Filters, on `ls` and `search`: `--chat`, `--embeddings`, `--images`, `--audio`,
|
|
26
27
|
`--tools`, `--vision`, `--free`, `--min-context <n>`, `--provider <name>`,
|
|
@@ -28,6 +29,9 @@ Filters, on `ls` and `search`: `--chat`, `--embeddings`, `--images`, `--audio`,
|
|
|
28
29
|
|
|
29
30
|
`pick` requires `--chat` or `--embedding`, and takes `--provider` and `--limit`.
|
|
30
31
|
|
|
32
|
+
`browse` is for a person at a terminal and refuses without one (exit 2). An
|
|
33
|
+
agent wants `ls --json`, `search` or `pick` instead.
|
|
34
|
+
|
|
31
35
|
## Where the lists come from
|
|
32
36
|
|
|
33
37
|
The providers themselves, cached for a day in `~/.zenera/neo/catalog`. When a
|
|
@@ -558,6 +558,7 @@ ordinary hybrid search and narrow by file or section.
|
|
|
558
558
|
zen rag docs list <files|sections|tables> [-f <pattern>] [-s <section>]
|
|
559
559
|
zen rag docs grep <pattern> [-f <pattern>] [--regex] [--case-sensitive]
|
|
560
560
|
zen rag docs show <file> [--section <name>] [--lines <from-to>]
|
|
561
|
+
zen rag docs show <target>... [--max-lines <n>]
|
|
561
562
|
```
|
|
562
563
|
|
|
563
564
|
`list sections` gives every heading with the lines it spans, which is how a
|
|
@@ -566,6 +567,23 @@ total even when `--limit` cuts the rows, so unlike a search it can answer
|
|
|
566
567
|
whether a string appears at all. `show` prints a document, a named section, or
|
|
567
568
|
a line range, verbatim.
|
|
568
569
|
|
|
570
|
+
### Reading several passages in one call
|
|
571
|
+
|
|
572
|
+
Name every passage you will read or cite in **one** `show`, as
|
|
573
|
+
`<document>:<a>-<b>`, `<document>:<a>` or `<document>#<heading>` - the form a
|
|
574
|
+
citation is written in, so a citation pastes back unchanged:
|
|
575
|
+
|
|
576
|
+
```sh
|
|
577
|
+
zen rag docs show -d <index-dir> "<doc-1>:24-60" "<doc-2>:25-40" "<doc-3>#<heading>"
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
Each target prints under a header that is itself a target, in the order given;
|
|
581
|
+
overlapping ranges in one document print once. A missing document or heading is
|
|
582
|
+
reported in place and the rest still print (exit 1 only when none could be
|
|
583
|
+
read). `--max-lines` (default 400) is shared fairly between targets, and a cut
|
|
584
|
+
block ends with the target that continues it. `--json` returns
|
|
585
|
+
`{results, printed, failed}`. `--section` and `--lines` read one document only.
|
|
586
|
+
|
|
569
587
|
### Reading a complete section or table
|
|
570
588
|
|
|
571
589
|
Search finds relevant passages, not necessarily every row of a table. When the
|
|
@@ -596,12 +614,12 @@ the answer needs every row.
|
|
|
596
614
|
|
|
597
615
|
`@zenera/rag/docs/tools` exports four tools in the group `docs`:
|
|
598
616
|
|
|
599
|
-
| Tool | For
|
|
600
|
-
| ------------- |
|
|
601
|
-
| `search_docs` | The search above, with the same narrowing parameters
|
|
602
|
-
| `list_docs` | The documents, their headings, or their tables - no ranking
|
|
603
|
-
| `grep_docs` | Every matching line, counted in full - the way to prove absence
|
|
604
|
-
| `read_docs` | A section or a line range, verbatim
|
|
617
|
+
| Tool | For |
|
|
618
|
+
| ------------- | ---------------------------------------------------------------- |
|
|
619
|
+
| `search_docs` | The search above, with the same narrowing parameters |
|
|
620
|
+
| `list_docs` | The documents, their headings, or their tables - no ranking |
|
|
621
|
+
| `grep_docs` | Every matching line, counted in full - the way to prove absence |
|
|
622
|
+
| `read_docs` | A section or a line range, verbatim; several at once via `reads` |
|
|
605
623
|
|
|
606
624
|
Only `search_docs` ranks. Every answer carries line numbers and `read_docs`
|
|
607
625
|
takes them, which is the loop the subject exists for: find the passage, read
|
|
@@ -119,7 +119,16 @@ distinguishes the two cases: a broken Dockerfile is an error, a laptop with no
|
|
|
119
119
|
Podman is a warning.
|
|
120
120
|
|
|
121
121
|
`zen sandbox clean` removes every container this CLI created - the way out of a
|
|
122
|
-
container left on a bad rootfs.
|
|
122
|
+
container left on a bad rootfs. `--idle` removes only what no live run is using:
|
|
123
|
+
stopped containers, and running ones whose run was killed before stopping them
|
|
124
|
+
(`zen sandbox status` marks those `orphaned`).
|
|
125
|
+
|
|
126
|
+
`could not create container … exceeded num_locks (2048)` means the engine is out
|
|
127
|
+
of locks: every container holds one, stopped ones included, and `persist: true`
|
|
128
|
+
leaves one stopped per session. `zen run` and `zen run batch` check this before
|
|
129
|
+
the first model call and exit `5` when the engine cannot hold them (a batch needs
|
|
130
|
+
one per item it runs at once). `zen sandbox status` shows a `locks` row when few
|
|
131
|
+
are left; `zen sandbox clean --idle` frees them.
|
|
123
132
|
|
|
124
133
|
For complete container architecture, the `sandbox:*` tools, mount rules, and
|
|
125
134
|
hardening details, load the `zen-sandbox` skill (`.github/skills/zen-sandbox/SKILL.md`).
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zen-code-python
|
|
3
|
+
description: Code an agent writes must be a reusable tool that can be remembered and re-run, never a one-off. Holds the coding rules (`references/code_python.md`) and decides where they go in the target project - a section of a dedicated code agent's system prompt, or a coding skill for generic agents that sometimes run code - how to adapt them, and what a prompt or skill for a code-writing agent must never say. Load before writing, editing or reviewing any agent prompt, skill or house rule for an agent that writes or runs code - any agent holding `sandbox:*` or `run_command` - and before shipping a script inside a skill.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Code an agent writes is a tool
|
|
7
|
+
|
|
8
|
+
A script an agent writes is worth more than the answer it printed. Written
|
|
9
|
+
generically - every changing value an argument, a name that says what it does -
|
|
10
|
+
it can be committed to memory as a `file` node and found again by the next
|
|
11
|
+
similar question, which runs it instead of writing it again. Written as a
|
|
12
|
+
one-off - this customer's id, this month, this path, as literals - it can only
|
|
13
|
+
ever answer the question that produced it, and memory fills up with near-copies
|
|
14
|
+
that never fold together.
|
|
15
|
+
|
|
16
|
+
Nothing in the runtime enforces this, and `zen check` does not report it. The
|
|
17
|
+
rules reach an agent only through what you write into the target project.
|
|
18
|
+
|
|
19
|
+
## The reference
|
|
20
|
+
|
|
21
|
+
`references/code_python.md` is the rule set, in wording that has been tested on
|
|
22
|
+
models. It is a source to build from, not a file to copy. Start from its
|
|
23
|
+
sentences - copying and then editing them works; rewriting them from scratch in
|
|
24
|
+
your own words loses the mechanical phrasing that makes them obeyed.
|
|
25
|
+
|
|
26
|
+
**Keep in substance, and never soften:**
|
|
27
|
+
|
|
28
|
+
- every value that would change for the next similar question is a named
|
|
29
|
+
argument, never a literal
|
|
30
|
+
- the file is named for what it does, and describes itself through `--help`
|
|
31
|
+
- the result goes to stdout, a produced file to an `--output` path
|
|
32
|
+
- the script is written to a file and the file is run - no `python -c`, no
|
|
33
|
+
heredoc
|
|
34
|
+
- before using the output, the script is checked against a different question
|
|
35
|
+
of the same kind
|
|
36
|
+
- with memory: search before writing, commit the working script after
|
|
37
|
+
|
|
38
|
+
**Adapt to the project:**
|
|
39
|
+
|
|
40
|
+
- the interpreter and language, if the sandbox image runs something other than
|
|
41
|
+
Python
|
|
42
|
+
- where scripts are written - `/workspace/scripts/` unless the project already
|
|
43
|
+
has a place
|
|
44
|
+
- libraries the image carries and the agent should prefer, and the output
|
|
45
|
+
format the project expects (JSON, CSV, a table)
|
|
46
|
+
- an example invocation from this project's own domain, values passed as
|
|
47
|
+
arguments
|
|
48
|
+
- the memory steps: keep them when the agent holds `memory_search` /
|
|
49
|
+
`memory_commit`, drop them when it never will. In a skill several agents may
|
|
50
|
+
load, keep them gated on the tool, as the reference does
|
|
51
|
+
|
|
52
|
+
## Decide where the rules go
|
|
53
|
+
|
|
54
|
+
List the agents that hold `sandbox:*` or `run_command`, and read each one's
|
|
55
|
+
prompt for what its job is. Then:
|
|
56
|
+
|
|
57
|
+
| The project has | Write |
|
|
58
|
+
| ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
59
|
+
| A **dedicated code agent** - a runner, an executor, an analyst whose answers are scripts | A `## Writing code` section in that agent's `agents/prompts/<name>.md` |
|
|
60
|
+
| **No dedicated code agent** - generic agents that sometimes run code | A coding skill, `agents/skills/code_python/SKILL.md` |
|
|
61
|
+
| Both | The prompt section, and the generic agents hand the code work to that agent rather than writing it - see below |
|
|
62
|
+
| No agent that writes or runs code | Nothing |
|
|
63
|
+
|
|
64
|
+
**A dedicated code agent gets the rules in its system prompt.** It writes code
|
|
65
|
+
on nearly every turn, so the rules are part of its job description: a skill
|
|
66
|
+
would cost a load on every case, and preloading one is the same text in the
|
|
67
|
+
prefix with an extra file to keep in step. Put the section after the agent's
|
|
68
|
+
identity and procedure, before its prohibitions.
|
|
69
|
+
|
|
70
|
+
**Generic agents get a skill.** Most of their turns write no code, so the rules
|
|
71
|
+
should cost nothing until one does. The `description` is the routing key - name
|
|
72
|
+
the condition, not the topic:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
description: Before writing, changing or running any Python script - how to write it as a reusable tool rather than a one-off.
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Leave it in the agent's index; do not preload it. If `allow` is used, add
|
|
79
|
+
`code_python` to it for every agent holding `sandbox:*`.
|
|
80
|
+
|
|
81
|
+
**With both, one copy.** Generic agents that can reach a code agent should
|
|
82
|
+
`fork:` to it for an answer, or hand off to it, rather than writing code
|
|
83
|
+
themselves - then the rules have one home and the scripts one author. Grant
|
|
84
|
+
them no `sandbox:*` for code work. If they must keep a shell of their own, they
|
|
85
|
+
need the skill too, and its rules are the same sentences as the prompt section:
|
|
86
|
+
a second wording is how one copy ends up softer than the other, and the softer
|
|
87
|
+
one is the one obeyed.
|
|
88
|
+
|
|
89
|
+
Run `zen check` after any change to `agents.yaml` or a skill.
|
|
90
|
+
|
|
91
|
+
## Writing anything else around it
|
|
92
|
+
|
|
93
|
+
- **One home per agent.** Once an agent has the rules - in its prompt or in its
|
|
94
|
+
skill - no house rule, other skill or prompt line restates them. A prompt that
|
|
95
|
+
needs to point at the skill names it: _"Follow `code_python` for every
|
|
96
|
+
script."_
|
|
97
|
+
- **Never add an exemption.** _"Hard-coding is fine for a quick one-off check"_
|
|
98
|
+
is a permission: every probe is a one-off by construction, so the exception
|
|
99
|
+
admits exactly what the rule forbids. The same goes for `python -c`.
|
|
100
|
+
- **Never show a one-off as an example.** A prompt or skill that shows
|
|
101
|
+
`python -c "..."`, or a script with a literal id, date or path in its body,
|
|
102
|
+
teaches the shape the rule forbids. Every example invocation passes its values
|
|
103
|
+
as named arguments:
|
|
104
|
+
`python /workspace/scripts/list_overdue_invoices.py --customer-id 42`.
|
|
105
|
+
- **Scripts shipped inside a skill** (`agents/skills/<name>/scripts/`, §3.4.1 of
|
|
106
|
+
the copilot instructions) follow the same rules: named arguments, a `--help`,
|
|
107
|
+
the result on stdout, an `--output` path under `/workspace` for any file,
|
|
108
|
+
since `/skills` is read-only.
|
|
109
|
+
- **Memory is what makes the reuse happen.** A code-writing agent without
|
|
110
|
+
memory still writes reusable scripts, but cannot find them in a later session.
|
|
111
|
+
Say so if the project expects reuse and that agent has no `memory:`.
|
|
112
|
+
|
|
113
|
+
## Review
|
|
114
|
+
|
|
115
|
+
- [ ] Every agent that writes or runs code has the rules - a prompt section for
|
|
116
|
+
a dedicated code agent, the `code_python` skill reachable for the others
|
|
117
|
+
- [ ] Every rule under _Keep in substance_ is there, none softened, and the
|
|
118
|
+
memory steps match whether the agent holds the memory tools
|
|
119
|
+
- [ ] Generic agents beside a dedicated code agent hand code work to it, or
|
|
120
|
+
carry the same wording - not a second paraphrase
|
|
121
|
+
- [ ] No other prompt, skill or house rule restates the rules, adds an
|
|
122
|
+
exemption, or shows `python -c` or a script with literal values
|
|
123
|
+
- [ ] Every script shipped in a skill takes its values as named arguments
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Writing Python scripts
|
|
2
|
+
|
|
3
|
+
Every script you write is a tool for the next question like this one, not an
|
|
4
|
+
answer to this one. Write it once, generically, so it can be remembered and run
|
|
5
|
+
again unchanged.
|
|
6
|
+
|
|
7
|
+
## Before writing
|
|
8
|
+
|
|
9
|
+
If you hold `memory_search`, search for a script that already answers this kind
|
|
10
|
+
of question, and load the best match with `memory_load`. If it fits, run it with
|
|
11
|
+
this question's arguments and write nothing new. If it needs a change, change
|
|
12
|
+
it the way the rest of this skill says - usually by adding an argument - and
|
|
13
|
+
commit the new version as superseding the old one.
|
|
14
|
+
|
|
15
|
+
## Writing
|
|
16
|
+
|
|
17
|
+
1. **Solve the kind of question, not this one.** Anything that would differ the
|
|
18
|
+
next time - inputs, ids, names, paths, urls, dates and date ranges, filters,
|
|
19
|
+
thresholds, limits, the output path - is a named `argparse` argument such as
|
|
20
|
+
`--resource-id`, never a literal in the code. A default is allowed only for a
|
|
21
|
+
value that is the same for every question.
|
|
22
|
+
2. **Name the file for what it does**, verb first: `list_overdue_invoices.py`,
|
|
23
|
+
`compare_quarterly_revenue.py`. Never `script.py`, `test.py`, `tmp.py` or a
|
|
24
|
+
name that only makes sense in this conversation.
|
|
25
|
+
3. **Describe it.** Line one is a docstring saying what question it answers. The
|
|
26
|
+
same sentence is the `argparse` description, and every argument has a
|
|
27
|
+
`help=`, so `--help` is all a later reader needs.
|
|
28
|
+
4. **Print the result to stdout** and anything else to stderr. Exit non-zero
|
|
29
|
+
with a message saying what failed when it cannot answer. A file it produces
|
|
30
|
+
goes to the path given by `--output`.
|
|
31
|
+
5. **Take credentials from environment variables by name.** Never write a key,
|
|
32
|
+
token or password into the code or an argument default.
|
|
33
|
+
6. **Use only what the sandbox image already has.** Do not `pip install` from
|
|
34
|
+
the script or before running it.
|
|
35
|
+
7. **Write it to a file and run the file**:
|
|
36
|
+
`python /workspace/scripts/<name>.py --resource-id 42`. Never run Python
|
|
37
|
+
with `python -c` or a heredoc.
|
|
38
|
+
|
|
39
|
+
## Before using its output
|
|
40
|
+
|
|
41
|
+
- Run it, and fix the script - not the output - when it fails or prints
|
|
42
|
+
something wrong.
|
|
43
|
+
- Read your own code against a different question of the same kind. If
|
|
44
|
+
answering it would mean editing the script rather than passing other
|
|
45
|
+
arguments, a value is still hard-coded: make it an argument and run again.
|
|
46
|
+
- If you hold `memory_commit`, commit the working script as a `file` node. Its
|
|
47
|
+
text says what kind of question it answers and names its arguments, so that a
|
|
48
|
+
later search for a similar question finds it.
|