@zenera/cli 1.1.23 → 1.1.24
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 +35 -2
- package/dist/ask.d.ts +51 -0
- package/dist/ask.js +143 -0
- package/dist/batch.d.ts +77 -0
- package/dist/batch.js +338 -0
- package/dist/command.d.ts +6 -0
- package/dist/commands/inspect.d.ts +11 -0
- package/dist/commands/inspect.js +388 -89
- package/dist/commands/list.js +128 -19
- package/dist/commands/memory.js +342 -12
- package/dist/commands/models.js +14 -2
- package/dist/commands/run.js +139 -34
- package/dist/commands/sandbox.js +72 -1
- package/dist/engine.d.ts +19 -0
- package/dist/engine.js +60 -8
- package/dist/liveness.js +6 -3
- package/dist/main.js +5 -2
- package/dist/podman.d.ts +16 -0
- package/dist/podman.js +115 -2
- package/dist/progress.d.ts +33 -0
- package/dist/progress.js +402 -0
- package/dist/request.d.ts +45 -0
- package/dist/request.js +300 -0
- package/dist/sandbox.js +10 -0
- package/dist/session.d.ts +26 -1
- package/dist/session.js +42 -3
- package/dist/term.d.ts +3 -0
- package/dist/term.js +17 -1
- package/dist/trace.d.ts +84 -0
- package/dist/trace.js +686 -0
- package/dist/validate.js +25 -3
- package/package.json +2 -2
- package/templates/editor/.github/copilot-instructions.md +11 -6
- package/templates/editor/.github/prompts/finetune.prompt.md +251 -0
- package/templates/editor/.github/skills/zen-cli/SKILL.md +9 -3
- package/templates/editor/.github/skills/zen-cli/references/check.md +7 -5
- package/templates/editor/.github/skills/zen-cli/references/inspect.md +262 -21
- package/templates/editor/.github/skills/zen-cli/references/memory.md +89 -19
- package/templates/editor/.github/skills/zen-cli/references/models.md +1 -1
- package/templates/editor/.github/skills/zen-cli/references/projects.md +12 -5
- package/templates/editor/.github/skills/zen-cli/references/run.md +201 -4
- package/templates/editor/.github/skills/zen-finetune/SKILL.md +1000 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/collect.sh +432 -0
- package/templates/editor/.github/skills/zen-finetune/scripts/sample.sh +199 -0
- package/templates/editor/.github/skills/zen-inspect/SKILL.md +396 -0
- package/templates/editor/.github/skills/zen-memory/SKILL.md +74 -29
- package/templates/editor/.github/skills/zen-memory-warmup/SKILL.md +363 -531
- package/templates/editor/.github/skills/zen-sandbox/SKILL.md +19 -0
- package/templates/editor/.github/skills/zen-sandbox-capacity/SKILL.md +334 -0
- package/templates/editor/.github/skills/zen-sandbox-capacity/references/loadtest.md +181 -0
- package/templates/editor/.github/skills/zen-sandbox-capacity/scripts/preflight_sandbox.sh +457 -0
- package/templates/editor/.vscode/agents.schema.json +1 -1
- package/templates/editor/.vscode/settings.json +1 -0
- package/templates/project/agents/files-instructions.md +13 -0
- package/templates/project/agents/fork-instructions.md +27 -0
- package/templates/project/agents/memory-instructions.md +80 -7
- package/templates/project/gitignore +3 -0
package/dist/validate.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EXA_GROUP, FileSkillProvider, SANDBOX_MOUNT, Sandbox, exaTools, frontmatter, projectRegistry, readProjectConfig, sandboxTools, selectTools, toList,
|
|
1
|
+
import { EXA_GROUP, FileSkillProvider, SANDBOX_MOUNT, Sandbox, exaTools, fileTools, frontmatter, projectRegistry, readProjectConfig, sandboxTools, selectTools, toList, } from '@zenera/neo';
|
|
2
2
|
import { existsSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, } from 'node:fs';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
@@ -35,10 +35,17 @@ const FILE_TOOLS = [
|
|
|
35
35
|
'find_files',
|
|
36
36
|
'write_file',
|
|
37
37
|
'apply_patch',
|
|
38
|
+
'copy_file',
|
|
38
39
|
'move_file',
|
|
39
40
|
'delete_file',
|
|
40
41
|
];
|
|
41
|
-
const FILE_WRITE_TOOLS = new Set([
|
|
42
|
+
const FILE_WRITE_TOOLS = new Set([
|
|
43
|
+
'write_file',
|
|
44
|
+
'apply_patch',
|
|
45
|
+
'copy_file',
|
|
46
|
+
'move_file',
|
|
47
|
+
'delete_file',
|
|
48
|
+
]);
|
|
42
49
|
function activeFileTools(selectors) {
|
|
43
50
|
const active = new Set();
|
|
44
51
|
if (!selectors?.length) {
|
|
@@ -607,7 +614,7 @@ export function availableTools(root, config) {
|
|
|
607
614
|
// Constructed, not started: a pool creates its container on the first
|
|
608
615
|
// command, so naming one here costs nothing and needs no container engine.
|
|
609
616
|
return [
|
|
610
|
-
...
|
|
617
|
+
...fileTools({
|
|
611
618
|
root,
|
|
612
619
|
mount: config.sandbox?.workdir ?? SANDBOX_MOUNT,
|
|
613
620
|
}),
|
|
@@ -1543,6 +1550,21 @@ function checkModels(root, config, keys, add, probe = false) {
|
|
|
1543
1550
|
if (resolved !== name) {
|
|
1544
1551
|
report.ref = resolved;
|
|
1545
1552
|
}
|
|
1553
|
+
// Reported here rather than left to the probe below: a knob for the
|
|
1554
|
+
// wrong vendor is a config mistake that wants naming whether or not
|
|
1555
|
+
// there is a credential to build the model with.
|
|
1556
|
+
if (role === 'model') {
|
|
1557
|
+
for (const stray of registry.knobs(ref)) {
|
|
1558
|
+
add({
|
|
1559
|
+
severity: 'error',
|
|
1560
|
+
code: 'model.knob',
|
|
1561
|
+
where: whereFor(config, role, name, usedBy),
|
|
1562
|
+
message: `\`${stray.knob}\` means nothing to a ${stray.target} model — ` +
|
|
1563
|
+
'it would never reach the request',
|
|
1564
|
+
fix: `this model takes: ${stray.supported.join(', ')}`,
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1546
1568
|
}
|
|
1547
1569
|
catch (err) {
|
|
1548
1570
|
add({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenera/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.24",
|
|
4
4
|
"description": "Command-line front end for @zenera/neo: agentic projects you can run, share and commit.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@google/genai": "^2.18.0",
|
|
53
53
|
"@inkjs/ui": "^2.0.0",
|
|
54
54
|
"@openrouter/sdk": "^1.2.80",
|
|
55
|
-
"@zenera/neo": "^1.1.
|
|
55
|
+
"@zenera/neo": "^1.1.24",
|
|
56
56
|
"google-auth-library": "^10.0.0",
|
|
57
57
|
"ink": "^7.1.1",
|
|
58
58
|
"openai": "^6.0.0",
|
|
@@ -47,7 +47,8 @@ visible in `agents.yaml` and that `zen check` does not report.** Before
|
|
|
47
47
|
reviewing or changing a project, list the capabilities it has turned on and load
|
|
48
48
|
the editor skill for each one - `zen-memory` for a `memory:` block,
|
|
49
49
|
`zen-sandbox` for sandbox configuration or shell tools, `zen-rag-schema` or
|
|
50
|
-
`zen-rag-docs` for an index, `zen-
|
|
50
|
+
`zen-rag-docs` for an index, `zen-sandbox-capacity` before any `zen run batch`,
|
|
51
|
+
`zen-cli` always. A capability that is already
|
|
51
52
|
configured and already passing `zen check` is exactly the case that looks
|
|
52
53
|
finished and is not: the obligation lives in the skill, so a review that never
|
|
53
54
|
opens the skill cannot find what is missing. This applies whatever prompted the
|
|
@@ -810,7 +811,7 @@ committed shows up as a skill with no files.
|
|
|
810
811
|
### 3.5 Tools
|
|
811
812
|
|
|
812
813
|
A tool is what an agent can _do_ rather than say. `zen run` provides three
|
|
813
|
-
groups - the
|
|
814
|
+
groups - the file tools (§3.6), the sandbox tools (§3.7) and the web tools
|
|
814
815
|
(§3.8) - and `agents.yaml` decides which agent holds which. Nothing else reaches
|
|
815
816
|
the machine, so `tools:` is the whole permission model: an agent that does not
|
|
816
817
|
name a tool cannot use it, whatever its prompt says.
|
|
@@ -846,6 +847,7 @@ them cannot see a file at all.
|
|
|
846
847
|
| `find_files` | Paths containing a substring, case-insensitive |
|
|
847
848
|
| `write_file` | Creates or overwrites a whole file, making parent directories |
|
|
848
849
|
| `apply_patch` | Edits by surrounding context rather than line numbers; several files atomically |
|
|
850
|
+
| `copy_file` | Copies, bytes never touching the context; the source may be a read-only mount |
|
|
849
851
|
| `move_file` | Moves or renames; refuses to clobber without `overwrite` |
|
|
850
852
|
| `delete_file` | Deletes; a directory needs `recursive` |
|
|
851
853
|
|
|
@@ -876,8 +878,8 @@ agents:
|
|
|
876
878
|
tools: [files:*]
|
|
877
879
|
|
|
878
880
|
- name: reviewer
|
|
879
|
-
# Everything except the
|
|
880
|
-
tools: [files:*, -write_file, -apply_patch, -move_file, -delete_file]
|
|
881
|
+
# Everything except the five that can change something.
|
|
882
|
+
tools: [files:*, -write_file, -apply_patch, -copy_file, -move_file, -delete_file]
|
|
881
883
|
```
|
|
882
884
|
|
|
883
885
|
Selectors apply in the order written, so a `-` line reads as an exception to the
|
|
@@ -1638,7 +1640,9 @@ over one connection.
|
|
|
1638
1640
|
| `includeThoughts` | gemini | Thought summaries; default `true` |
|
|
1639
1641
|
| `routing` / `fallbacks` | openrouter | Upstream provider preferences, and models to fall back to - §7.5 |
|
|
1640
1642
|
|
|
1641
|
-
Knobs that do not apply to the chosen vendor are
|
|
1643
|
+
Knobs that do not apply to the chosen vendor are rejected, not dropped: the
|
|
1644
|
+
schema accepts every one on every model, and building it fails with `does not
|
|
1645
|
+
read "<knob>"`. `zen check` reports the same thing as `model.knob`.
|
|
1642
1646
|
`api:` exists only for the OpenAI protocol - naming it on a Gemini or Anthropic
|
|
1643
1647
|
model is an error.
|
|
1644
1648
|
|
|
@@ -2012,7 +2016,8 @@ candidates; these are the judgements to make about each one)**
|
|
|
2012
2016
|
- [ ] No agent holds `write_file` without `apply_patch`, or `read_file` without
|
|
2013
2017
|
`list_dir` and `find_files`
|
|
2014
2018
|
- [ ] An agent that only reads is not holding `write_file`, `apply_patch`,
|
|
2015
|
-
`move_file` or `delete_file` - subtract them from `files:*`
|
|
2019
|
+
`copy_file`, `move_file` or `delete_file` - subtract them from `files:*`
|
|
2020
|
+
(or `workspace:*`)
|
|
2016
2021
|
- [ ] `sandbox:*` is granted only where a shell is actually needed
|
|
2017
2022
|
- [ ] `sandbox.persist: true`, unless a throwaway rootfs is wanted on purpose
|
|
2018
2023
|
- [ ] The `sandbox:` image carries what the work needs, rather than the prompt
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Fine-tune this project against a training set in two stages - first without memory, tuning the prose; then with memory, tuning recall for speed.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Tune this project against real queries. Nothing here touches model weights: the
|
|
6
|
+
parameters are the agent prompts, the skills and the house rules under `agents/`,
|
|
7
|
+
and the evidence is the trajectories the queries produce.
|
|
8
|
+
|
|
9
|
+
**Load the `zen-finetune` skill before anything else**, and load `zen-inspect`
|
|
10
|
+
before you grade, `zen-instructions` before you write a policy file, and
|
|
11
|
+
`zen-sandbox-capacity` if a batch dies at 137 or 124. This prompt is the order of
|
|
12
|
+
the work; the skill is how each step is done, and it holds the rules that are
|
|
13
|
+
easy to get wrong.
|
|
14
|
+
|
|
15
|
+
This prompt is **reentrant**. Tuning is long and gets interrupted - a batch dies,
|
|
16
|
+
a session ends, I stop you mid-round. Every step leaves its result on disk under
|
|
17
|
+
`.finetune/`, so a second invocation does not start over: it reads that state,
|
|
18
|
+
works out which stage and which step the work stopped at, says so, and carries
|
|
19
|
+
on from there unless I tell you otherwise.
|
|
20
|
+
|
|
21
|
+
## The two stages
|
|
22
|
+
|
|
23
|
+
This is two stages, run in order, never interleaved. Say which stage you are in
|
|
24
|
+
at the top of every report.
|
|
25
|
+
|
|
26
|
+
**Stage 1 - without memory.** Every batch runs against an empty memory, so every
|
|
27
|
+
run starts from nothing and the result is attributable to the prose. Here you
|
|
28
|
+
tune agent prompts, `agents/instructions.md`, and the project's skills - creating
|
|
29
|
+
or updating them. The runs still _write_ memory, into their own throwaway graphs,
|
|
30
|
+
and what they write is graded too: the commits have to be generalisable, durable
|
|
31
|
+
facts, not cached live readings. Stage 1 optimises **correctness**.
|
|
32
|
+
|
|
33
|
+
**Stage 2 - with memory.** Only once stage 1 is stable and well behaved. The
|
|
34
|
+
prompts, skills and house rules are now frozen; the merged memory from the last
|
|
35
|
+
good cold batch is copied to every item, which reads it and writes into its own
|
|
36
|
+
copy, and the only file you edit is `agents/memory-policy-instructions.md`.
|
|
37
|
+
Stage 2 optimises **memory use and memory correctness**, and the expected result
|
|
38
|
+
is a dramatic drop in tokens and wall clock through reuse, with no verdict
|
|
39
|
+
changed.
|
|
40
|
+
|
|
41
|
+
Do not start stage 2 while any sample still fails cold. Memory will hide the
|
|
42
|
+
defect and it will come back the day the graph is rebuilt.
|
|
43
|
+
|
|
44
|
+
## Where you are - work this out before anything else
|
|
45
|
+
|
|
46
|
+
Do this every time this prompt runs, including the first - on a project that has
|
|
47
|
+
never been tuned it costs one `ls` and tells you to start at section 0.
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
ls .finetune/dataset.json .finetune/rounds 2>/dev/null
|
|
51
|
+
for r in .finetune/rounds/*/; do
|
|
52
|
+
printf '%s ' "$r"
|
|
53
|
+
for f in cases.json batch/batch.json findings.md changes.md; do
|
|
54
|
+
[ -e "$r$f" ] && printf '%s ' "$f"
|
|
55
|
+
done
|
|
56
|
+
echo
|
|
57
|
+
done
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The rounds are ordered by name, so the last one is the live one. Read its
|
|
61
|
+
`findings.md` heading for the stage - it says `COLD` or `WARM` - and its
|
|
62
|
+
`changes.md` for what was already applied. Then resume by the artefacts the round
|
|
63
|
+
is missing:
|
|
64
|
+
|
|
65
|
+
| State of the last round | Where the work stopped | Resume at |
|
|
66
|
+
| --------------------------------------- | ----------------------------------- | -------------------------------------------------------------------------- |
|
|
67
|
+
| no `.finetune/` at all | nothing has been done | section 0, then 1 |
|
|
68
|
+
| `dataset.json`, no `rounds/` | dataset built, never sampled | section 2 (stage 1) |
|
|
69
|
+
| `cases.json` only | sampled, batch never started | preflight, then run the batch into this same round |
|
|
70
|
+
| `batch/` present, no `batch/batch.json` | the batch was interrupted or killed | the round is **void** - see below, then re-run it |
|
|
71
|
+
| `batch/batch.json`, no `findings.md` | the batch finished, nothing graded | section 3 - `collect.sh oom` first |
|
|
72
|
+
| `findings.md`, no `changes.md` | graded, nothing applied yet | section 4 |
|
|
73
|
+
| `findings.md` and `changes.md` | edits applied, never measured | re-run the same cases into a **new** round: section 5 cold, section 6 warm |
|
|
74
|
+
| the last round's heading says `WARM` | stage 2 is in progress | the same rows, read against section 6 |
|
|
75
|
+
|
|
76
|
+
Two things the table does not see, so check them by hand:
|
|
77
|
+
|
|
78
|
+
- **Uncommitted edits under `agents/` with no `changes.md` to explain them.** An
|
|
79
|
+
apply was interrupted part-way. Read `git status --short agents/` and the diff,
|
|
80
|
+
finish writing `changes.md` from what is actually on disk, then re-run - do not
|
|
81
|
+
layer new edits on top of edits you have not recorded.
|
|
82
|
+
- **`zen check` before you resume anything.** A project left broken mid-edit
|
|
83
|
+
fails every item identically and looks like a catastrophic regression.
|
|
84
|
+
|
|
85
|
+
A round whose batch never wrote `batch.json` produced no evidence. Move it aside
|
|
86
|
+
rather than grading it or deleting it - `mv .finetune/rounds/rN/batch
|
|
87
|
+
.finetune/rounds/rN/batch.partial` - and re-run that round from the same
|
|
88
|
+
`cases.json`. The same applies to a round `collect.sh oom` calls void.
|
|
89
|
+
|
|
90
|
+
Resuming never re-samples and never re-merges. Re-use the first round's
|
|
91
|
+
`cases.json` and, in stage 2, the merged graph already sitting in the stage's
|
|
92
|
+
round directory - an interruption is not a reason to change the thing every
|
|
93
|
+
earlier round was measured against. Re-derive nothing from memory of the last
|
|
94
|
+
session either: `findings.md` and `changes.md` are the record, so read them.
|
|
95
|
+
|
|
96
|
+
Then tell me, in three lines before you do any work: which stage, which round and
|
|
97
|
+
step you are resuming at, and what you are about to run. Continue without waiting
|
|
98
|
+
for me up to the next natural checkpoint - the end of a round's report - because
|
|
99
|
+
that is where this prompt already stops and asks. If I named a stage or a round,
|
|
100
|
+
do that instead of what the state says.
|
|
101
|
+
|
|
102
|
+
**If nothing is left to do** - the last round is WARM, it met the stage-2 exit
|
|
103
|
+
criteria, and no prose or policy edit has landed since - do not start another
|
|
104
|
+
tuning round. Run one confirmation round instead: the same `cases.json`, the same
|
|
105
|
+
merged graph, the same flags, the same machine, into
|
|
106
|
+
`.finetune/rounds/rN-verify/`. Grade it, write `findings.md` with the heading
|
|
107
|
+
`VERIFIED` if no verdict regressed and the saving still holds, and change nothing.
|
|
108
|
+
If something did regress, that is a real finding: report it and re-open the stage
|
|
109
|
+
it belongs to.
|
|
110
|
+
|
|
111
|
+
## 0. Before the first round
|
|
112
|
+
|
|
113
|
+
Name the training set. If I have not given you one, ask - a specification
|
|
114
|
+
section, a file of examples, a transcript, a CSV. Fewer than about eight queries
|
|
115
|
+
is a debugging session, not a tuning loop; say so and read the runs singly
|
|
116
|
+
instead.
|
|
117
|
+
|
|
118
|
+
Then run the mechanical checks and report what they say:
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
zen check
|
|
122
|
+
.github/skills/zen-review/scripts/check-paths.sh
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
A project that does not load fails every item for one reason. Do not start a
|
|
126
|
+
round until `zen check` passes.
|
|
127
|
+
|
|
128
|
+
## 1. Dataset
|
|
129
|
+
|
|
130
|
+
Build `.finetune/dataset.json` if it is not there, and read it if it is. Read the
|
|
131
|
+
source yourself and write the structure out - do not write a parser. Rubrics are
|
|
132
|
+
copied **verbatim**, one entry per bullet. Classify only the distinctions the
|
|
133
|
+
source already makes, and rate complexity by the trajectory the query demands,
|
|
134
|
+
not by the length of the sentence. Keep ids stable across re-extractions.
|
|
135
|
+
|
|
136
|
+
## 2. Stage 1: sample, preflight, run cold
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
.github/skills/zen-finetune/scripts/sample.sh -n 16 --seed 1 -o .finetune/rounds/r1/cases.json
|
|
140
|
+
.github/skills/zen-sandbox-capacity/scripts/preflight_sandbox.sh --concurrency 8
|
|
141
|
+
zen run batch --input .finetune/rounds/r1/cases.json \
|
|
142
|
+
--batch-dir .finetune/rounds/r1/batch --memory .finetune/empty --concurrency 8
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Every stage-1 round is cold and every round re-uses the first round's
|
|
146
|
+
`cases.json`. A warm graph lets a run succeed by recall instead of by
|
|
147
|
+
instruction, and a re-sampled batch means a moved score has two causes and you
|
|
148
|
+
cannot tell which.
|
|
149
|
+
|
|
150
|
+
## 3. Stage 1: grade
|
|
151
|
+
|
|
152
|
+
`collect.sh oom` first - a round with any exit 137 is void, is not graded, and
|
|
153
|
+
its tokens are compared to nothing. Then read the graphs before the numbers.
|
|
154
|
+
Grade every item against all eight criteria in the skill: rubric compliance,
|
|
155
|
+
optimality, memory hygiene, fork, delegation, tools and skills, grounding,
|
|
156
|
+
failure handling. **Cite a node id for every finding.** A finding you cannot
|
|
157
|
+
point at in the graph did not happen.
|
|
158
|
+
|
|
159
|
+
Grade the memory each item _wrote_ as seriously as the answer it gave. Read
|
|
160
|
+
`<id>/memory/` across the batch: every commit should be an operation, a pointer,
|
|
161
|
+
a shape or a rule that is still true next week. A cached live reading poisons
|
|
162
|
+
every future run, and committing nothing after learning something durable throws
|
|
163
|
+
the round away. Commit policy is fixed here, cold, while the cause is still
|
|
164
|
+
attributable - not in stage 2.
|
|
165
|
+
|
|
166
|
+
Write `.finetune/rounds/rN/findings.md`: the verdict block first - `PROGRESS`,
|
|
167
|
+
`NO CHANGE`, `REGRESSION`, `MIXED` or `VOID`, the `memory:` and `machine:` lines
|
|
168
|
+
as printed, and the `compare` table - then the per-sample grading. The heading
|
|
169
|
+
says `COLD` or `WARM`.
|
|
170
|
+
|
|
171
|
+
## 4. Stage 1: generalise, then apply
|
|
172
|
+
|
|
173
|
+
Collect every finding into one table before writing a word of instruction. The
|
|
174
|
+
unit of change is a pattern across findings, not a finding: three items missing
|
|
175
|
+
the same beat is a rule, one item is a note in `findings.md`. Write the rule one
|
|
176
|
+
level up from the sample that produced it - a rule that names the dataset's own
|
|
177
|
+
endpoints makes the eval pass and the product fail. Prefer mechanical wording,
|
|
178
|
+
and remember that a prohibition with a self-judged exemption is a permission.
|
|
179
|
+
|
|
180
|
+
Route each rule by what kind of thing it is: one agent's behaviour to its prompt,
|
|
181
|
+
a fact or a procedure to a skill - update an existing one or create a new one, a
|
|
182
|
+
standing rule to `agents/instructions.md`, a rule about one capability to a new
|
|
183
|
+
`agents/<topic>-policy-instructions.md`.
|
|
184
|
+
|
|
185
|
+
You may edit prompts, skills, house rules and new policy files. You may not edit
|
|
186
|
+
`agents/memory-instructions.md`, `agents/fork-instructions.md`,
|
|
187
|
+
`agents/tools-instructions.md` or `agents/files-instructions.md` - `zen check
|
|
188
|
+
--fix` overwrites them. You may not change a rubric to make a run pass. Tell me
|
|
189
|
+
before you change `agents.yaml`; that finding is structural.
|
|
190
|
+
|
|
191
|
+
Record every edit and the finding numbers behind it in
|
|
192
|
+
`.finetune/rounds/rN/changes.md`, then run `zen check` again.
|
|
193
|
+
|
|
194
|
+
## 5. Stage 1: loop, and leave the stage
|
|
195
|
+
|
|
196
|
+
Re-run the same cases into a new round directory and compare per sample and on
|
|
197
|
+
the aggregate. The verdict column decides, not the token column. A sample that
|
|
198
|
+
passed and now fails is the most valuable result in the round and is almost
|
|
199
|
+
always the new instruction. If the instruction files grew by a third and the
|
|
200
|
+
score moved by one sample, revert and say so.
|
|
201
|
+
|
|
202
|
+
Report to me after each round and wait: the verdict block, what you changed, and
|
|
203
|
+
what you propose to change next. Stop when a round produces no generalisable
|
|
204
|
+
pattern - that is the remaining failure being the model's rather than the prose's.
|
|
205
|
+
|
|
206
|
+
Stage 1 ends when, on one cold round, **every sample holds** and **what the runs
|
|
207
|
+
wrote to memory is worth keeping**. Tell me both before proposing stage 2.
|
|
208
|
+
|
|
209
|
+
## 6. Stage 2: memory
|
|
210
|
+
|
|
211
|
+
Freeze the prompts, the skills and the house rules. Merge the last good cold
|
|
212
|
+
round's memory into one graph, read `zen memory stats`, and run the same cases
|
|
213
|
+
against it with the same flags the cold round used - `--memory <merged graph>`
|
|
214
|
+
and nothing else. Each item copies that graph, recalls from the copy and writes
|
|
215
|
+
back into the copy, so every item starts from the same memory and the source is
|
|
216
|
+
left untouched. Do not use `--memory-read-only`: it removes the commit tool and
|
|
217
|
+
changes the memory prose, which would make the warm round differ from its cold
|
|
218
|
+
baseline in two ways instead of one.
|
|
219
|
+
|
|
220
|
+
Compare against the cold round the memory came from.
|
|
221
|
+
|
|
222
|
+
The target is reuse: recall should replace the discovery the cold runs repeated
|
|
223
|
+
every time, so the warm batch is dramatically cheaper in tokens, calls and wall
|
|
224
|
+
clock with no verdict changed. A warm round that costs about the same, or more,
|
|
225
|
+
means memory was carried and not used - that is a recall-timing finding, not a
|
|
226
|
+
reason for more memory. A warm round that is much cheaper still needs one
|
|
227
|
+
trajectory opened to confirm the saving is recall replacing _discovery_ and not
|
|
228
|
+
recall replacing a _live reading_.
|
|
229
|
+
|
|
230
|
+
Grade what the warm items committed as well as what they recalled - this is the
|
|
231
|
+
one place it can be seen. A node that duplicates something the same run just
|
|
232
|
+
recalled is waste, and a correction committed without `SUPERSEDES` beside the
|
|
233
|
+
stale node it contradicts is worse than waste.
|
|
234
|
+
|
|
235
|
+
In stage 2 the only file you edit is `agents/memory-policy-instructions.md`. Keep
|
|
236
|
+
the merged graph byte-identical for the whole stage: do not re-merge between
|
|
237
|
+
rounds, and never merge a warm round's own copies back into it - either changes
|
|
238
|
+
the memory and the prose at once. If a finding cannot be written as a recall or
|
|
239
|
+
re-commit rule, it is a stage-1 finding that escaped - tell me, and we re-open
|
|
240
|
+
stage 1.
|
|
241
|
+
|
|
242
|
+
Stage 2 ends when no verdict regressed, the saving is obvious next to the noise
|
|
243
|
+
floor, every large saving is explained, and nothing was committed that memory
|
|
244
|
+
already held.
|
|
245
|
+
|
|
246
|
+
Commit `dataset.json`, `cases.json`, `findings.md` and `changes.md` - they are
|
|
247
|
+
the eval history, and they are what a resumed session reads to find out where it
|
|
248
|
+
got to. Write each of them as its step ends rather than at the end of the round,
|
|
249
|
+
so an interruption never costs more than the step it lands in. Add
|
|
250
|
+
`.finetune/rounds/*/batch/` and `.finetune/empty/` to `.gitignore` - the batch
|
|
251
|
+
directories are large and may hold live API responses.
|
|
@@ -17,14 +17,15 @@ failed, `2` usage, `3` invalid project, `4` no usable credential, `5` sandbox.
|
|
|
17
17
|
|
|
18
18
|
```
|
|
19
19
|
zen init [dir] [--name <name>] [--model <ref>] [--force]
|
|
20
|
-
zen list [--sessions] [--prune]
|
|
20
|
+
zen list [--sessions] [--runs] [--limit <n>] [--prune]
|
|
21
21
|
zen run [project] [prompt] [options]
|
|
22
|
+
zen run batch --input <file> [--batch-dir <dir>] [--concurrency <n>] [--memory-read-only]
|
|
22
23
|
zen open [project] [--editor <cmd>] [--wait]
|
|
23
24
|
zen key <ls|add|use|check|rm|show|env> [ref] [options]
|
|
24
25
|
zen models <providers|ls|search|show|test|pick> [ref] [options]
|
|
25
26
|
zen check [name|dir] [--project <name|dir>] [--no-sandbox] [--no-models] [--strict] [--quiet]
|
|
26
|
-
zen inspect [run] [--
|
|
27
|
-
zen memory [stats|ls|show|export|merge|forget] [args] [options]
|
|
27
|
+
zen inspect [report|graph|node|ask] [run] [--dir <run dir>] [--part <name>] [--full] [--open]
|
|
28
|
+
zen memory [stats|ls|search|grep|show|export|merge|forget] [args] [options]
|
|
28
29
|
zen export [project] [--out <file>] [--no-vectors] [--no-memory] [--force]
|
|
29
30
|
zen import <file.zip> [dir] [--name <name>] [--force] [--no-register]
|
|
30
31
|
zen sandbox [status|up|pull|clean|disk] [options]
|
|
@@ -46,11 +47,13 @@ guess a flag, and do not read them all.
|
|
|
46
47
|
| Global flags, `--json`, exit codes, environment, where files live | [frame.md](./references/frame.md) |
|
|
47
48
|
| Creating, finding or opening a project | [projects.md](./references/projects.md) |
|
|
48
49
|
| Running: the TUI, one-shot answers, sessions, workspaces, overrides | [run.md](./references/run.md) |
|
|
50
|
+
| Many questions at once: `zen run batch`, its file, where answers go | [run.md](./references/run.md) |
|
|
49
51
|
| Validating: `zen check`, what it can and cannot see | [check.md](./references/check.md) |
|
|
50
52
|
| API keys, providers, the keyring, "no credential" errors | [keys.md](./references/keys.md) |
|
|
51
53
|
| Which models exist, whether one works, recovering from a refusal | [models.md](./references/models.md) |
|
|
52
54
|
| The container shell commands run in, images, `persist` | [sandbox.md](./references/sandbox.md) (and `zen-sandbox` skill) |
|
|
53
55
|
| Run reports, trajectories, what a session directory holds | [inspect.md](./references/inspect.md) |
|
|
56
|
+
| Reading a run yourself: the node graph, opening a node by id | [inspect.md](./references/inspect.md) (and `zen-inspect` skill) |
|
|
54
57
|
| What the agents remember, why something was recalled, forgetting | [memory.md](./references/memory.md) |
|
|
55
58
|
| Sharing a project: archives, what travels, importing one safely | [export.md](./references/export.md) |
|
|
56
59
|
| `zen faker` - a mock API from an OpenAPI/Swagger document | [faker.md](./references/faker.md) |
|
|
@@ -63,7 +66,10 @@ zen init scaffold a project here, pick a model
|
|
|
63
66
|
zen check validate everything before spending a turn
|
|
64
67
|
zen run the TUI
|
|
65
68
|
zen run "what changed?" one answer, this directory as the workspace
|
|
69
|
+
zen run batch --input cases.json many questions at once, each isolated
|
|
66
70
|
zen inspect --open what the model was actually given
|
|
71
|
+
zen inspect graph --dir <run dir> the same run as a graph you can read
|
|
72
|
+
zen inspect node n14..n20 --dir <d> the nodes behind the ids, in full
|
|
67
73
|
zen memory export --open the whole memory graph, as a page
|
|
68
74
|
zen export the project as a zip you can send
|
|
69
75
|
zen import a.zip unpack one somebody sent, run nothing in it
|
|
@@ -73,9 +73,9 @@ assets.missing assets.overbroad sandbox.dockerfile.missing
|
|
|
73
73
|
sandbox.build sandbox.smoke sandbox.start / .unchecked
|
|
74
74
|
sandbox.pin.stale sandbox.pin.absent
|
|
75
75
|
provider.invalid model.none model.unresolvable
|
|
76
|
-
model.refused
|
|
77
|
-
embedding.refused
|
|
78
|
-
credential.*
|
|
76
|
+
model.knob model.refused model.unreachable
|
|
77
|
+
model.unusable embedding.refused embedding.unreachable
|
|
78
|
+
embedding.unusable credential.* service.credential
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
The report goes to **stdout** - it is the answer. `--json` gives the same
|
|
@@ -87,8 +87,10 @@ required it.
|
|
|
87
87
|
|
|
88
88
|
### What it cannot catch
|
|
89
89
|
|
|
90
|
-
Combinations that are only rejected by the provider at the first call.
|
|
91
|
-
|
|
90
|
+
Combinations that are only rejected by the provider at the first call. A knob
|
|
91
|
+
written for the wrong vendor is no longer one of them - `model.knob` names it,
|
|
92
|
+
and building the model refuses outright. The known one that remains:
|
|
93
|
+
**OpenAI reasoning and tools only meet on the responses API.** A
|
|
92
94
|
model with `reasoningEffort` and tools on the default chat-completions API is a
|
|
93
95
|
valid configuration that fails at runtime with _"Function tools with
|
|
94
96
|
reasoning_effort are not supported … in /v1/chat/completions"_. Set
|