@zenera/cli 1.1.40 → 1.1.42

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.
@@ -33,7 +33,7 @@ zen version
33
33
 
34
34
  zen meta <run|prompts|resume|model|dataset> [project] [args]
35
35
 
36
- zen gym <serve|build|cache|model> [spec...]
36
+ zen gym <serve|build|cache|world|model> [spec...]
37
37
  zen rag schema <index|restore|ready|search|list|grep|trace|show|stats> [spec...]
38
38
  zen rag docs <index|restore|ready|search|list|grep|show|stats> [path...]
39
39
  ```
@@ -103,7 +103,7 @@ A real environment variable always beats the keyring.
103
103
  projects.json the registry: name -> directory
104
104
  keys.json credentials (0600)
105
105
  keys/ key files, for providers that hold a file
106
- gym/ generator cache for `zen gym`
106
+ gym/ handlers, worlds, docs indexes and agent reports for `zen gym`
107
107
 
108
108
  <project>/
109
109
  zenera.json { version, name }
@@ -1,126 +1,155 @@
1
1
  # Agent API environments - `zen gym`
2
2
 
3
3
  ```
4
- zen gym <serve|build|cache|model> [spec...]
4
+ zen gym <serve|build|cache|world|model> [spec...]
5
5
  ```
6
6
 
7
7
  Provided by `@zenera/gym` - `npm i -g @zenera/gym` if
8
8
  `zen gym` says it is not installed.
9
9
 
10
- Serves a mock API from one or more OpenAPI/Swagger documents. For each
11
- operation a **model writes a Python generator**, which is self-tested inside a
12
- container and cached on disk. Answers are therefore schema-correct and
13
- plausible, not `"string"` repeated.
10
+ Serves a mock API from OpenAPI/Swagger documents, backed by a **stateful
11
+ world**. For each operation an agent writes a **TypeScript handler** (the
12
+ mechanics: which type, which filter, what a write changes), judged before it is
13
+ cached. Content comes from a second agent that fills the world on first read,
14
+ following an optional **story** (`--story`) and drawing on **reference
15
+ documents** (`--docs`). Lists and gets agree, writes are seen by later reads,
16
+ and several `zen gym` processes given the same story share one world. No
17
+ container engine is needed.
18
+
19
+ ## Inputs
20
+
21
+ Each is a file, a directory or a quoted pattern, and each is repeatable.
22
+
23
+ | Input | What it is | How agents get it |
24
+ | ------------------- | --------------------------------------------------------------------- | --------------------------- |
25
+ | `spec…`, `--schema` | API documents: `.yaml`/`.yml`/`.json` declaring `swagger:`/`openapi:` | API graph and types |
26
+ | `--story` | the state of the world: people, what is happening, what is not | quoted whole in prompts |
27
+ | `--docs` | reference material: knowledge base, guides, runbooks | searched (indexed at start) |
28
+
29
+ A directory given as `--schema` is walked and only real API documents are kept,
30
+ so a folder of mixed JSON — or an API index somebody built — works. A Markdown
31
+ file given as a schema is refused with a hint; so is an API document given as
32
+ `--story` or `--docs`. Quote globs (`--docs 'kb/*.md'`) so the shell leaves them
33
+ to gym.
14
34
 
15
35
  ## Subcommands
16
36
 
17
- | Command | What it does |
18
- | ----------------- | ---------------------------------------------------------- |
19
- | `serve <spec...>` | Serve the documents. Generators are written on demand |
20
- | `build <spec...>` | Write every generator now and exit |
21
- | `cache ls\|clear` | What has been generated, or throw it away |
22
- | `model [ref]` | Show or set the model; `--clear` forgets the stored choice |
37
+ | Command | What it does |
38
+ | --------------------- | --------------------------------------------------------------- |
39
+ | `serve [spec...]` | Index everything, then serve. Handlers are written on first use |
40
+ | `build [spec...]` | Index everything and write every handler, then exit |
41
+ | `cache ls\|clear` | Handlers, bindings and indexes; `clear` keeps worlds |
42
+ | `world ls\|rm <name>` | List worlds, or delete one |
43
+ | `model [ref]` | Show or set the chat model; `--embedding <ref\|none\|clear>` |
23
44
 
24
45
  ```
25
46
  zen gym serve openapi.yaml
26
- zen gym serve api/*.yaml --port 9000 --seed 7
27
- zen gym build openapi.yaml --concurrency 8
28
- zen gym cache clear
47
+ zen gym serve --schema specs/ --story world.md --docs kb/
48
+ zen gym serve specs/mail.yaml --story world.md --port 8787
49
+ zen gym serve specs/calendar.yaml --story world.md --port 8788 # same world as above
50
+ zen gym serve api.yaml --world demo --reset # a named world, emptied
51
+ zen gym build --schema 'api/*.yaml' --story world.md --docs kb/ --concurrency 8
52
+ zen gym world ls
29
53
  ```
30
54
 
31
- `build` is the one to run in CI or before a demo: it pays for every generator up
32
- front and exits non-zero, with a table, if any could not be written.
55
+ `build` is the one to run in CI or before a demo: it pays for every handler up
56
+ front and exits non-zero, with a table, if any could not be written. Content is
57
+ still made lazily, on first read.
33
58
 
34
59
  ## Options
35
60
 
36
- | Flag | Default | Meaning |
37
- | ------------------- | ------------------- | ----------------------------------------------- |
38
- | `--port <n>` | `8787` | Port to listen on |
39
- | `--host <h>` | `127.0.0.1` | Anything else is reachable off-machine |
40
- | `--model <ref>` | project default | Which model writes the generators |
41
- | `--image <ref>` | a baked image | Skip the baked image and use this one |
42
- | `--cache <dir>` | `~/.zenera/neo/gym` | Where generators live |
43
- | `--seed <n>` | - | Answer the same request the same way every time |
44
- | `--attempts <n>` | `3` | Tries per generator before giving up |
45
- | `--concurrency <n>` | `4` | Generators written at once |
46
- | `--timeout <s>` | `30` | Seconds one generator may take |
47
- | `--max-body <n>` | 1 MB | Largest request body accepted, in bytes |
48
- | `--rebuild` | - | Ignore what is cached and write it again |
49
- | `--no-cache` | - | Do not record what is written |
50
- | `--quiet` | - | No narration |
61
+ | Flag | Default | Meaning |
62
+ | ----------------------- | ------------------- | -------------------------------------------------------- |
63
+ | `--schema <path>` | - | API documents, in addition to bare arguments |
64
+ | `--story <path>` | - | The state of the world |
65
+ | `--docs <path>` | - | Reference material |
66
+ | `--world <name\|file>` | one per story | Which world; a name is under `<cache>/worlds/` |
67
+ | `--reset` | - | Start from an empty world |
68
+ | `--model <ref>` | recommended | Which model writes handlers and content |
69
+ | `--embedding <on\|ref>` | off (wording) | Also search `--docs` by meaning; `on` = configured model |
70
+ | `--port <n>` | `8787` | Port to listen on |
71
+ | `--host <h>` | `127.0.0.1` | Anything else is reachable off-machine |
72
+ | `--cache <dir>` | `~/.zenera/neo/gym` | Handlers, worlds, indexes, reports |
73
+ | `--seed <n>` | - | Same request, same randomness |
74
+ | `--attempts <n>` | `5` | Failed tests per handler before giving up |
75
+ | `--concurrency <n>` | `4` | Handlers written at once |
76
+ | `--timeout <s>` | `30` | Seconds a handler may run, agent time aside |
77
+ | `--max-body <n>` | 1 MB | Largest request body accepted, in bytes |
78
+ | `--rebuild` | - | Ignore what is cached and write it again |
79
+ | `--no-cache` | - | Do not record what is written |
80
+ | `--quiet` | - | No narration |
51
81
 
52
82
  Credentials come from the `zen` keyring - see [keys.md](keys.md).
53
- Model selection: `--model`, `ZENERA_GYM_MODEL`, `~/.zenera/neo/gym.json`,
54
- then the best model the available keys support.
83
+ Chat model: `--model`, `ZENERA_GYM_MODEL`, `zen gym model <ref>`, then the best
84
+ model the available keys support. It must call tools; for OpenAI reasoning
85
+ models use the Responses API, `openai/responses:<id>`. Embedding model: off by
86
+ default, so `--docs` are searched by wording (full-text). `--embedding <ref>`
87
+ searches by meaning too with that model; `--embedding on` takes
88
+ `ZENERA_GYM_EMBEDDING`, then `zen gym model --embedding <ref>`, then the first
89
+ provider with a key that offers one. Without the flag those settings do nothing.
55
90
 
56
91
  ## Serving
57
92
 
58
- Binds the loopback address by default. On start it prints a table per document:
59
- paths, methods, and how many operations have a response schema and therefore get
60
- a generator.
93
+ Binds the loopback address by default. On start it prints a table per document,
94
+ then the model, story, docs (and how they are searched) and the world file.
61
95
 
62
- | Endpoint | Answers |
63
- | --------------- | ------------------------- |
64
- | `/__gym/routes` | Every route it will serve |
65
- | `/__gym/health` | Whether it is up |
96
+ | Endpoint | Answers |
97
+ | --------------- | -------------------------------------------- |
98
+ | `/` | Contents page, with a Run form per operation |
99
+ | `/__gym/routes` | Every route it will serve |
100
+ | `/__gym/health` | Whether it is up |
66
101
 
67
102
  Response headers:
68
103
 
69
104
  | Header | Meaning |
70
105
  | ----------------- | ----------------------------------------------------- |
71
106
  | `x-gym-operation` | The `operationId` that answered |
72
- | `x-gym-cache` | `hit` or `miss` - whether this call cost a model turn |
107
+ | `x-gym-cache` | `hit`, `miss` or `regenerated` - the handler's origin |
73
108
 
74
109
  Gym provides simulation, not task scoring, rewards, or a training loop.
75
110
 
76
111
  Incoming headers are filtered: `authorization`, `cookie` and anything matching
77
- `key|token|secret|password|credential` never reach a generator.
78
-
79
- `--seed` makes each request's seed a hash of the seed, the operation and the
80
- parameters, so the same request answers identically across restarts - which is
81
- what makes a mock usable in a test.
112
+ `key|token|secret|password|credential` never reach a handler.
82
113
 
83
114
  ## What "correct" means here
84
115
 
85
- A generator is judged on two synthetic probes: the body validates against the
116
+ A handler is judged by `test_handler` on synthetic probes, in a throwaway copy
117
+ of the world with schema-sampled content: the body validates against the
86
118
  response schema, **and** it obeys the **echo rule** - a value given in the path
87
- comes back in the answer. `GET /users/12324` must return `user_id: 12324`. A body
88
- can validate perfectly and still be about the wrong entity, which is exactly the
89
- mock that wastes an afternoon.
119
+ comes back in the answer (`GET /users/12324` must return `user_id: 12324`).
120
+ Paged operations are walked: the cursor must advance and end. And every record
121
+ type the handler touches must live where earlier handlers put it.
90
122
 
91
- Query parameters are deliberately not enforced: `?source=realtime`, `?page_size`
92
- and `?cursor` are controls, and their names collide with unrelated response
93
- fields.
123
+ ## Bindings: where each type lives
94
124
 
95
- Probes are synthetic on purpose - real request bodies never reach a prompt.
125
+ Handlers name records by schema type (`ctx.lookup('Message', id)`). The first
126
+ handler to use a type binds it to a collection and id field; later handlers are
127
+ told the binding and held to it, so every operation on a resource reads the same
128
+ records. Bindings are add-only and machine-wide, keyed by the documents' types;
129
+ `cache clear` forgets them.
96
130
 
97
- ## The cache
131
+ ## The cache, the world, the reports
98
132
 
99
- Generators live in the machine's shared cache, `~/.zenera/neo/cache/gym-generator/`,
100
- keyed by the operation's shape - so the same spec served from two directories is
101
- written once, and a spec edit produces a new key rather than a stale answer. A
102
- generator that a model gave up on is remembered for the life of the process, so
103
- a hopeless operation is not re-asked on every request; a _transient_ failure - a
104
- 429, a dropped socket - is not, because it is about this minute rather than this
105
- operation.
133
+ Handlers live in the machine's shared cache, `~/.zenera/neo/cache/gym-handler/`,
134
+ keyed by the operation's shape (descriptions and examples excluded) - not by the
135
+ story, since a handler holds no content. A cached handler whose bindings no
136
+ longer hold is rebuilt. Two processes needing the same handler build it once.
106
137
 
107
- `~/.zenera/neo/gym/` is the container's workspace, and scratch: a cache hit is
108
- copied into it, because the container can only run what is under its mount.
138
+ Worlds live in `<cache>/worlds/`. With a story and no `--world`, the world is
139
+ named after the story's content, so editing the story starts a new world (gym
140
+ says so). `cache clear` never touches worlds; `world rm` and `serve --reset` do.
109
141
 
110
- `zen gym cache ls` lists what has been generated. `zen gym cache clear`
111
- removes the generators, the workspace and the container together. They have to
112
- go together: the container's name is a hash of its configuration, so deleting
113
- the workspace alone would leave a stopped container bind-mounted onto a
114
- directory that no longer exists, and every generator would fail with
115
- `python3: can't open file '/workspace/generators/…/gen.py'`.
142
+ The docs index lives in `<cache>/indexes/`, keyed by the docs' content and the
143
+ embedding model; a restart reuses it.
116
144
 
117
- `zen cache ls --kind gym-generator` reaches the same entries from the other
118
- side, along with everything else this machine has cached.
145
+ Every agent run leaves an HTML report in `<cache>/reports/`; failed builds
146
+ leave a markdown report in `<cache>/builds/`.
119
147
 
120
148
  ## Documents it accepts
121
149
 
122
150
  Swagger 2 and OpenAPI 3.0/3.1, JSON or YAML, `$ref`s resolved. Several documents
123
- can be served at once. OpenAPI 3.0 constructs are translated to JSON Schema
124
- 2020-12 on the way in (`nullable`, boolean `exclusiveMinimum`, Draft-4 array
125
- `items`), and a `pattern` written as a JavaScript regex literal (`/^[a-z]+$/`)
126
- is unwrapped rather than being treated as an unsatisfiable string.
151
+ can be served at once, as long as no two define the same route (two versions of
152
+ one API: serve them from two processes with the same `--world`). OpenAPI 3.0
153
+ constructs are translated to JSON Schema 2020-12 on the way in (`nullable`,
154
+ boolean `exclusiveMinimum`, Draft-4 array `items`), and a `pattern` written as a
155
+ JavaScript regex literal (`/^[a-z]+$/`) is unwrapped.
@@ -32,6 +32,16 @@ dereference: having seen the shape and spotted the loop, you open the three
32
32
  nodes that explain it, whole and untruncated. The index is cheap and you only
33
33
  pay for what you open.
34
34
 
35
+ For a whole-run audit, follow **zen-analyze-run**: reuse the graph, begin with
36
+ the outcome, batch selected evidence nodes, and expand backwards only for a
37
+ specific unresolved criterion or anomaly. Labels locate evidence; exact
38
+ arguments, returned facts and success claims require the relevant payload.
39
+ Stop when the evidence is sufficient, not after opening every node.
40
+ Start with supporting or contradicting results; select decision nodes only
41
+ after identifying a remaining evidence gap or material attribution question.
42
+ Keep each retrieved node part and its output location, and search that copy
43
+ for all quotations rather than fetching it once per phrase.
44
+
35
45
  `ask` is the last resort, not the first move: it spends a model call to ask the
36
46
  run's own model why it did what it did. Open the node first - most questions are
37
47
  answered by reading what it was given.
@@ -278,6 +288,11 @@ zen inspect node n11 --part thinking --part text --dir <run dir>
278
288
  zen inspect node n11 --full --dir <run dir>
279
289
  ```
280
290
 
291
+ Those are explicit deep-inspection options, not whole-run audit defaults.
292
+ Prefer `--part call` for LLM tool arguments and `--part text` for its public
293
+ answer. Open `thinking` only when unresolved attribution would change a
294
+ recommendation; self-explanations do not prove causation.
295
+
281
296
  An `llm_call` carries two more parts read out of its request, held back the
282
297
  same way: `tools`, the tool names that call was offered, one per line, and
283
298
  `messages`, the conversation it saw, one clipped line per message with its
@@ -26,6 +26,12 @@ zen inspect ask <llm-node-id> --question-file <question file> --dir <run-dir>
26
26
  Each non-interactive call is a **fresh replay**. It does not remember your
27
27
  previous question. A follow-up must restate what it builds on.
28
28
 
29
+ For a whole-run audit, **zen-analyze-run** owns the replay budget: default
30
+ zero, at most two invocations including retries and second opinions. Its
31
+ budget and uncertainty gate take precedence over the retry suggestions below.
32
+ Do not replay a healthy run or ask about a cause already established by
33
+ recorded evidence.
34
+
29
35
  ## 1. Rule out the cheap causes first
30
36
 
31
37
  A "why didn't you" question is only about instructions if the model could have
@@ -242,18 +248,21 @@ only a finding once the sentence is confirmed.
242
248
  ```sh
243
249
  zen inspect node n9 --part request --dir <run-dir> | grep -F 'Do not fork a sequence'
244
250
  ```
251
+ Reuse a request already retrieved; fetch it once and check all quotes
252
+ against that copy. A match in a project file alone does not prove delivery.
245
253
  A quote that is not there is invented - discard the answer, not just the
246
- quote. Ask once more; if it invents again, ask another model (step 4).
254
+ quote. Retry only within the caller's budget; otherwise report that
255
+ attribution remains unresolved.
247
256
  2. **Find every copy.** The blocker often exists twice - once in a house rule,
248
257
  once in a skill with a softer tail. Grep the whole request for a distinctive
249
258
  phrase of it, then grep the project's `agents/` tree for the file to edit.
250
259
  3. **Check it is the project's file.** `fork-instructions.md`,
251
260
  `memory-instructions.md`, `tools-instructions.md` are zen's own copies; load
252
261
  **zen-instructions** before changing where that rule lives.
253
- 4. **Second opinion when the self-report is thin.** The model that made the
254
- call rationalises; another model reading the same replay often names the
255
- conflict more plainly: `--model <ref>`. Ask the identical question: the same
256
- question file.
262
+ 4. **Second opinion only when justified.** A thin answer or `no instruction -
263
+ my own default` does not itself justify more replay. In a whole-run audit,
264
+ use a second opinion only after an invented quote, and within the two-call
265
+ total budget: `--model <ref>`, the identical question file.
257
266
  5. **Reproduce.** After the edit, rerun the case and check the graph: the
258
267
  `tools` header row shows `fork x1` or `memory_search x1` where it did not
259
268
  before. The answer predicted a fix; the graph confirms it.
@@ -36,8 +36,12 @@ NOISE='^(and/or|he/she|his/her|input/output|read/write|w/o|n/a|N/A|24/7|km/h)$|^
36
36
  # A url, stripped before tokenising rather than filtered after it — the token
37
37
  # regex reads `https://acme.dev/docs` as `//acme.dev` *and* `/docs`, and the
38
38
  # second half is indistinguishable from a real absolute path once it is alone.
39
+ #
40
+ # A meta agent command, `zen meta run /spec-edit`, goes the same way: its
41
+ # `/<name>` is a stored prompt, not a file the running agent is told to open.
39
42
  strip_urls() {
40
- sed -E 's#[a-zA-Z][a-zA-Z0-9+.-]*://[^][ )"'"'"'`>]*##g' "$1"
43
+ sed -E -e 's#[a-zA-Z][a-zA-Z0-9+.-]*://[^][ )"'"'"'`>]*##g' \
44
+ -e 's#(zen meta run( [A-Za-z0-9_.-]+)?) /[A-Za-z0-9_-]+#\1#g' "$1"
41
45
  }
42
46
 
43
47
  # The three trees §2.5 names, prose only: a skill's own script is code the
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: zen-spec-sync
3
- description: Running `/spec-sync-project` as an incremental pass - the committed `.spec-sync` baseline of what the last pass applied, how to scope a pass from the specification and feedback diffs and from what moved in the project itself, the five checks a narrow pass may never skip, which skills a pass must load before editing (`zen-instructions` for any house rule it touches), the iteration history format, and why the baseline is written last. Load before every `/spec-sync-project`, including the first one on a project that has no baseline yet.
3
+ description: Running `/spec-sync-project` as an incremental pass - the committed `.spec-sync` baseline of what the last pass applied, how to scope a pass from the specification and feedback diffs and from what moved in the project itself, which input wins when they disagree, the five checks a narrow pass may never skip, which skills a pass must load before editing (`zen-instructions` for any house rule it touches), the iteration history format, and why the baseline is written last. Load before every `/spec-sync-project`, including the first one on a project that has no baseline yet.
4
4
  ---
5
5
 
6
6
  # Syncing a project with its specification, one change at a time
@@ -103,9 +103,64 @@ editing anything, and report it in the chat as the pass's scope.
103
103
  covers it, and you say which line, or it does not, and it is an **extra**
104
104
  reported under `➕`.
105
105
 
106
+ ## When the inputs disagree
107
+
108
+ Two inputs can ask for different things - a ticked answer and a later edit to
109
+ the same specification line, say. Decide by this order, highest first, and do
110
+ not weigh them again:
111
+
112
+ 1. **The user's message that started this pass**, where it says more than the
113
+ command name. It is the newest and most direct statement of intent there is.
114
+ 2. **`SPECIFICATION.md` as it stands now.** An edit to the specification is
115
+ made on purpose and after the questions were written, so it outranks them.
116
+ 3. **An answer ticked in `SPECIFICATION-FEEDBACK.md`** and not yet folded in.
117
+ 4. **What the last pass left open.**
118
+
119
+ A ticked answer that the current specification text contradicts was
120
+ **superseded**, not ignored: do not fold its text back in over the newer line.
121
+ Strike the question with one line naming the specification line that replaced
122
+ it, and say in the chat that you did.
123
+
124
+ Facts outrank all four. `zen --version` decides the sandbox pin (below); a
125
+ specification line asking for something impossible is a question, not an order.
126
+ Where the order above does not decide, build what the higher-ranked input asks
127
+ for, write **one** question in `SPECIFICATION-FEEDBACK.md`, and carry on.
128
+
129
+ ### Do not reconstruct intent
130
+
131
+ The diffs say what changed. The order above says what wins. A feedback question
132
+ covers whatever is left. Do not use anything else to work out _why_ somebody
133
+ changed something: no session history or chat transcripts, no file timestamps,
134
+ no `git log` or `git blame`, no older history entries beyond the one `applied:`
135
+ names. If a pass catches itself guessing at what the human meant, that guess is
136
+ the text of a question, and the pass moves on.
137
+
138
+ ### The `zen` version in the specification
139
+
140
+ The `@zenera/cli` and `@zenera/rag` pin in `sandbox/Dockerfile` always follows
141
+ `zen --version` - `zen check` warns on any other number, older or newer. Nothing
142
+ outranks that, not a specification line and not the user's message: the image
143
+ cannot hold a `zen` other than the one building it. If a version was asked for
144
+ that is not the one in hand, say so in the chat - `zen` has to be upgraded on the
145
+ host first.
146
+
147
+ When `SPECIFICATION.md` names an exact version other than `zen --version`, pin
148
+ the Dockerfile to `zen --version` and keep **one** `✏️` question open for that
149
+ line. If one is already open, update it instead of adding another. Offer these
150
+ answers:
151
+
152
+ - State the pin without a number - "pinned to the `zen` version that builds the
153
+ image" - so the next upgrade does not raise the question again
154
+ _(recommended)_.
155
+ - Replace the number with the one `zen --version` reports.
156
+ - Keep the number, upgrade `zen` on the host to it, and run the pass again.
157
+
158
+ That is the whole of the work. A version mismatch is not a reason to look for
159
+ anything else.
160
+
106
161
  ## The five checks a narrow pass may never skip
107
162
 
108
- However small the diff:
163
+ However small the diff - with the one narrowing for a spec-only pass below:
109
164
 
110
165
  1. **`zen check` passes.** Run it before the first edit and again after the
111
166
  last.
@@ -131,6 +186,28 @@ However small the diff:
131
186
  it, the history entry claims it, and the baseline records it as applied.
132
187
  Specification-driven rules go in a topic file of the project's own beside it.
133
188
 
189
+ ### The spec-only pass
190
+
191
+ A pass qualifies when **all** of the following hold:
192
+
193
+ - the implementation diff (input 4) is empty
194
+ - the pass edits nothing except `SPECIFICATION.md`, `SPECIFICATION-FEEDBACK.md`
195
+ and the `@zenera/*` pin in `sandbox/Dockerfile`
196
+ - no changed specification hunk names an agent, tool, model, embedding, skill,
197
+ house rule, handoff, memory, index, asset or setup step
198
+
199
+ A pass like that changes nothing an agent reads, so it has no capability
200
+ obligation to re-check. Checks 4 and 5 drop out: load no capability skill and no
201
+ `zen-instructions`. `zen check` still runs before and after, and it still
202
+ reports `rules.stale`. Check 2 shrinks to `scripts/_setup.sh --check`, which
203
+ must report every step `skipped`. If it reports anything else, run
204
+ `scripts/_setup.sh` in full as written. Check 3 shrinks to the §9
205
+ **Specification** group and the groups covering any file the pass edited.
206
+
207
+ Decide this before loading anything, and say it in the chat - "spec-only pass:"
208
+ followed by the reason. If any edit turns out to reach further, the pass is no
209
+ longer spec-only: run all five checks.
210
+
134
211
  A narrow diff narrows reading and editing. It does not narrow verification.
135
212
 
136
213
  ## What else an incremental pass still owes
@@ -26,6 +26,20 @@ Search before starting work that costs more than one cheap read or call:
26
26
  Do not repeat the same search in different words. Search again only when the
27
27
  question has changed.
28
28
 
29
+ When a request involves several distinct subjects, search for all of them in
30
+ parallel: send one `memory_search` per subject in the same turn rather than one
31
+ after another. Likewise, load every node you need in the same turn. Parallel
32
+ searches must ask different questions, not rephrase one.
33
+
34
+ ### Call memory tools silently
35
+
36
+ You MUST NOT write any text before a `memory_*` call. Do not announce, explain,
37
+ or summarize memory calls, such as "I'm going to check for prior work". The
38
+ tool call is shown to the user on its own. This overrides the general rule to
39
+ say what you are about to do before tool calls: when a turn contains only
40
+ `memory_*` calls, write nothing; when it mixes them with other tools, describe
41
+ only the other calls.
42
+
29
43
  ### Choose the retrieval tool
30
44
 
31
45
  | Need | Tool |
@@ -17,3 +17,63 @@ Anything under `/assets` is reference material: read it, search it, and do not
17
17
  try to change it.
18
18
 
19
19
  Say what you changed.
20
+
21
+ <!-- ===== BEGIN: unconfigured-agent disclaimer (delete this block once the agent is configured) ===== -->
22
+
23
+ ## This agent is not configured yet
24
+
25
+ This agent has not been set up for any specific task yet. It only has the
26
+ generic defaults above, so it is not expected to do anything particularly
27
+ useful on its own.
28
+
29
+ When the user greets you ("hi", "hello"), asks what you can do, asks who you
30
+ are, or asks how to get started, tell them plainly:
31
+
32
+ - This agent is not configured yet to do anything useful.
33
+ - To teach it specific tasks, they should use the **Zenera Meta Agent**,
34
+ which can configure this agent's prompts, tools, knowledge and workflows.
35
+ It ships with the `zen` CLI:
36
+ - What it is and how it works:
37
+ https://github.com/zenera-ai/ZeneraNeo#what-is-the-meta-agent
38
+ - The CLI and its commands:
39
+ https://github.com/zenera-ai/ZeneraNeo/tree/main/packages/cli
40
+ - The project home: https://zenera.ai
41
+
42
+ Then give them these steps to get started. The commands run in a terminal on
43
+ their machine, from the project directory, not here:
44
+
45
+ 1. Pick the model the meta agent uses (once per machine):
46
+ `zen meta model --pick`
47
+ 2. Describe what this agent should do in `SPECIFICATION.md`: its purpose,
48
+ models, agents, tools, knowledge and memory. Edit the file by hand, or have
49
+ the meta agent write it from a plain request:
50
+ `zen meta run /spec-edit "<what to add, change or remove>"`
51
+ 3. Have the meta agent build the system from the specification:
52
+ `zen meta run /spec-sync-project`
53
+ 4. If the meta agent has questions, it writes them to
54
+ `SPECIFICATION-FEEDBACK.md`. Answer them there, then apply the answers:
55
+ `zen meta run /spec-apply-feedback`
56
+ 5. Validate the project and try it: `zen check`, then `zen run "<request>"`.
57
+ Review a run with `zen inspect`.
58
+
59
+ To find out more, `--help` works on every command and subcommand:
60
+
61
+ - `zen meta --help` lists everything the meta agent can do: `run`,
62
+ `prompts`, `resume`, `model`, `dataset` and `finetune`, with examples.
63
+ - `zen meta run --help` lists the options for a run and the stored prompts,
64
+ the `/<name>` commands used above.
65
+ `zen meta prompts` lists the stored prompts on their own.
66
+ - `zen meta dataset --help` and `zen meta finetune --help` cover building an
67
+ evaluation dataset and tuning the project against it.
68
+ - `zen meta run "<question>"` asks the meta agent anything about the project,
69
+ for example `zen meta run "what does this project do?"`.
70
+
71
+ For teams that need more, mention **ZeneraLab**, Zenera's enterprise-grade
72
+ platform (https://zenera.ai). It has all of this built into a UI, where users
73
+ can build enterprise-grade agentic solutions, integrate them with any legacy
74
+ system, and train, fine-tune, optimize, test and monitor their agents.
75
+
76
+ Keep that answer short and friendly. You can still help with simple requests
77
+ in the workspace if asked directly.
78
+
79
+ <!-- ===== END: unconfigured-agent disclaimer ===== -->