@zenera/cli 1.1.14 → 1.1.16
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 +563 -206
- package/dist/banner.d.ts +5 -1
- package/dist/banner.js +2 -2
- package/dist/command.d.ts +5 -0
- package/dist/commands/init.js +46 -2
- package/dist/main.js +10 -6
- package/dist/validate.js +1 -1
- package/package.json +2 -2
- package/templates/editor/.github/copilot-instructions.md +253 -218
- package/templates/editor/.github/prompts/new-agent.prompt.md +6 -6
- package/templates/editor/.github/prompts/new-skill.prompt.md +7 -7
- package/templates/editor/.github/prompts/review-project.prompt.md +1 -1
- package/templates/editor/.github/prompts/sync-with-spec.prompt.md +26 -26
- package/templates/editor/.github/skills/zen-cli/SKILL.md +62 -6
- package/templates/editor/.github/skills/zen-cli/references/check.md +3 -3
- package/templates/editor/.github/skills/zen-cli/references/faker.md +14 -14
- package/templates/editor/.github/skills/zen-cli/references/frame.md +6 -6
- package/templates/editor/.github/skills/zen-cli/references/inspect.md +3 -3
- package/templates/editor/.github/skills/zen-cli/references/keys.md +9 -9
- package/templates/editor/.github/skills/zen-cli/references/memory.md +11 -11
- package/templates/editor/.github/skills/zen-cli/references/models.md +8 -8
- package/templates/editor/.github/skills/zen-cli/references/projects.md +3 -3
- package/templates/editor/.github/skills/zen-cli/references/rag.md +191 -56
- package/templates/editor/.github/skills/zen-cli/references/run.md +3 -3
- package/templates/editor/.github/skills/zen-cli/references/sandbox.md +8 -8
- package/templates/editor/.github/skills/zen-memory/SKILL.md +50 -50
- package/templates/editor/.github/skills/zen-rag-docs/SKILL.md +71 -48
- package/templates/editor/.github/skills/zen-rag-schema/SKILL.md +67 -67
- package/templates/editor/.vscode/settings.json +5 -2
- package/templates/project/INSTRUCTIONS.md +1 -1
- package/templates/project/assets/README.md +1 -1
- package/templates/project/sandbox/Dockerfile.tmpl +3 -0
|
@@ -14,8 +14,8 @@ true, and you should say which:
|
|
|
14
14
|
- its instructions **contradict** an existing agent's rather than extend them
|
|
15
15
|
- it is a **parallel branch** target for a `fork:`
|
|
16
16
|
|
|
17
|
-
If none holds, propose the smaller change instead
|
|
18
|
-
tool grant
|
|
17
|
+
If none holds, propose the smaller change instead - a skill, a prompt line, a
|
|
18
|
+
tool grant - and stop. Adding an agent to solve a prompt problem is the failure
|
|
19
19
|
mode this project cares most about.
|
|
20
20
|
|
|
21
21
|
If it is warranted:
|
|
@@ -23,18 +23,18 @@ If it is warranted:
|
|
|
23
23
|
1. Pick a name matching `^[a-z0-9]+(?:[-_][a-z0-9]+)*$`. It reaches the model as
|
|
24
24
|
`transfer_to_<name>`, so the name is part of the routing surface.
|
|
25
25
|
2. Write `agents/prompts/<name>.md`: one sentence of identity, a short procedure
|
|
26
|
-
or three to five rules, then what it must **not** do
|
|
26
|
+
or three to five rules, then what it must **not** do - especially the
|
|
27
27
|
neighbouring agent's job. Second person, imperative, failure paths stated.
|
|
28
28
|
No frontmatter, no meta-talk about the runtime.
|
|
29
|
-
3. Add the `agents.yaml` entry. `description:` is written **for the model**
|
|
29
|
+
3. Add the `agents.yaml` entry. `description:` is written **for the model** - it
|
|
30
30
|
is the whole of what a sibling sees when deciding to hand off. Grant the
|
|
31
31
|
narrowest `tools:` the job needs.
|
|
32
32
|
4. Wire the return edge. A handoff does not come back on its own, so every
|
|
33
|
-
`A → B` needs a path from B back to A
|
|
33
|
+
`A → B` needs a path from B back to A - directly, or through another agent.
|
|
34
34
|
`zen check` warns on an edge that has none. If what this agent really wants
|
|
35
35
|
is an _answer_ rather than to give up the conversation, declare `fork:`
|
|
36
36
|
instead: a branch returns by itself.
|
|
37
|
-
5. Add a one-line comment above the entry saying why this agent exists
|
|
37
|
+
5. Add a one-line comment above the entry saying why this agent exists - its
|
|
38
38
|
job or its tier, not what the keys mean.
|
|
39
39
|
|
|
40
40
|
Then run `zen check` and report what it said. If it fails, fix the file it
|
|
@@ -3,29 +3,29 @@ mode: agent
|
|
|
3
3
|
description: Add a skill under agents/skills, with a description that routes.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Add a skill to this project. A skill is curated instruction content
|
|
7
|
-
optionally tools
|
|
6
|
+
Add a skill to this project. A skill is curated instruction content - and
|
|
7
|
+
optionally tools - loaded on demand instead of sitting in every system prompt.
|
|
8
8
|
Reach for one whenever a rule applies only sometimes, or holds a fact that will
|
|
9
9
|
change without the prompt changing.
|
|
10
10
|
|
|
11
11
|
Ask what the skill must say and when it applies, if I have not already said.
|
|
12
12
|
|
|
13
13
|
1. Create `agents/skills/<name>/SKILL.md`. That is the only skill layout there
|
|
14
|
-
is
|
|
14
|
+
is - a bare `agents/skills/<name>.md` fails `zen check` - and the folder is
|
|
15
15
|
what lets the skill carry companions later: a rate table, an example letter,
|
|
16
16
|
a schema, a script.
|
|
17
17
|
2. Write the `description`. This is the routing key and the only thing the model
|
|
18
18
|
sees before deciding to load the skill, so write it as **the condition under
|
|
19
19
|
which the skill is needed**, not as a title. `Water policy` is a title;
|
|
20
|
-
`Escape of water from plumbing and tanks
|
|
20
|
+
`Escape of water from plumbing and tanks - and the freezing exclusion` is a
|
|
21
21
|
condition. If two skills could both match a case, sharpen both until they
|
|
22
22
|
cannot.
|
|
23
23
|
3. Write the body as instructions the model can act on: thresholds, exact
|
|
24
24
|
wording, the boundaries of the rule, and what to do when the case falls
|
|
25
|
-
outside it. Put the facts here rather than in a prompt
|
|
25
|
+
outside it. Put the facts here rather than in a prompt - that is the point of
|
|
26
26
|
the file.
|
|
27
27
|
4. Put anything the rule computes or looks up in a file beside `SKILL.md` and
|
|
28
|
-
name it from the body by its absolute path
|
|
28
|
+
name it from the body by its absolute path - `python
|
|
29
29
|
/skills/<name>/scripts/calculate.py <id>`, not `scripts/calculate.py`. The
|
|
30
30
|
folder is mounted read-only at `/skills/<name>/`, so the script writes
|
|
31
31
|
nothing there; the agent needs `sandbox:*` to run it, and the interpreter has
|
|
@@ -37,7 +37,7 @@ Ask what the skill must say and when it applies, if I have not already said.
|
|
|
37
37
|
6. Leave `name` out unless it must differ from the folder name, and leave
|
|
38
38
|
`version`/`tags` out unless something uses them.
|
|
39
39
|
|
|
40
|
-
Do not `preload:` it unless every case genuinely needs it
|
|
40
|
+
Do not `preload:` it unless every case genuinely needs it - a preloaded skill is
|
|
41
41
|
a longer prompt, paid for on every call. Bind it under `agents[].skills.allow`
|
|
42
42
|
if the agent's catalog is restricted.
|
|
43
43
|
|
|
@@ -28,7 +28,7 @@ Work the checklist in §9 of the copilot instructions. In particular:
|
|
|
28
28
|
- **Routing.** Handoff targets have descriptions written for the model. No
|
|
29
29
|
ping-pong edges. No router that answers.
|
|
30
30
|
- **Models.** Each agent on the cheapest tier that is right, not the safest.
|
|
31
|
-
- **Cache.** Nothing volatile
|
|
31
|
+
- **Cache.** Nothing volatile - dates, ids, counts - in the stable prefix.
|
|
32
32
|
- **Secrets.** No key inlined anywhere; `.env` ignored, `sessions/` ignored.
|
|
33
33
|
|
|
34
34
|
Report as a list of findings, each naming the file and the line, ordered by how
|
|
@@ -3,7 +3,7 @@ description: Bring the project into compliance with SPECIFICATION.md, and record
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
Make this project match `SPECIFICATION.md`. The specification is the intent;
|
|
6
|
-
the files are the implementation. Where they disagree, the specification wins
|
|
6
|
+
the files are the implementation. Where they disagree, the specification wins -
|
|
7
7
|
except where it is ambiguous, contradictory or impossible, which is what
|
|
8
8
|
`SPECIFICATION-FEEDBACK.md` is for.
|
|
9
9
|
|
|
@@ -11,14 +11,14 @@ except where it is ambiguous, contradictory or impossible, which is what
|
|
|
11
11
|
|
|
12
12
|
Read, in this order, and do not edit until all of it is read:
|
|
13
13
|
|
|
14
|
-
1. `SPECIFICATION.md`
|
|
15
|
-
2. `agents.yaml`
|
|
14
|
+
1. `SPECIFICATION.md` - what the system is meant to be.
|
|
15
|
+
2. `agents.yaml` - providers, models, embeddings, agents, tools, handoffs,
|
|
16
16
|
skills, sandbox.
|
|
17
17
|
3. `INSTRUCTIONS.md` and every file under `agents/prompts/`.
|
|
18
18
|
4. Every `agents/skills/*/SKILL.md`, plus what each skill folder ships.
|
|
19
19
|
5. `assets/`, `sandbox/Dockerfile` and every script under `scripts/`, starting
|
|
20
20
|
with `scripts/_setup.sh`.
|
|
21
|
-
6. `SPECIFICATION-FEEDBACK.md`, if it exists
|
|
21
|
+
6. `SPECIFICATION-FEEDBACK.md`, if it exists - do not re-raise something already
|
|
22
22
|
open there.
|
|
23
23
|
|
|
24
24
|
Run `zen check` first and record what it said. A project that does not load is
|
|
@@ -29,11 +29,11 @@ the first thing to fix.
|
|
|
29
29
|
Produce a difference list before touching a file. For every item in the
|
|
30
30
|
specification, decide which of these it is:
|
|
31
31
|
|
|
32
|
-
- **present and correct**
|
|
33
|
-
- **missing**
|
|
34
|
-
- **divergent**
|
|
35
|
-
- **extra**
|
|
36
|
-
- **unclear**
|
|
32
|
+
- **present and correct** - leave it alone
|
|
33
|
+
- **missing** - the specification asks for it and nothing implements it
|
|
34
|
+
- **divergent** - implemented, but not as specified
|
|
35
|
+
- **extra** - implemented, and the specification does not ask for it
|
|
36
|
+
- **unclear** - the specification does not say enough to implement it
|
|
37
37
|
|
|
38
38
|
Check at least: the model and embedding ids and which agent uses which; that
|
|
39
39
|
every agent named in the specification exists with that job and no second job;
|
|
@@ -43,18 +43,18 @@ specification implies; and every setup step, index or asset it depends on.
|
|
|
43
43
|
Then build the difference the other way, because the list above can only find
|
|
44
44
|
what the specification asked for and nothing implements. Read `INSTRUCTIONS.md`,
|
|
45
45
|
each `agents/prompts/*.md` and each `SKILL.md` **line by line**, and for every
|
|
46
|
-
line name the specification item it serves. A line serving none is an **extra**
|
|
46
|
+
line name the specification item it serves. A line serving none is an **extra** -
|
|
47
47
|
the category covers a single sentence in a prompt, not only a whole file. Three
|
|
48
48
|
things to look for while reading, none of which the forward pass can see:
|
|
49
49
|
|
|
50
50
|
- **A line that contradicts another file.** One prompt against another, a prompt
|
|
51
|
-
against `INSTRUCTIONS.md`, or a prompt against `agents.yaml`
|
|
51
|
+
against `INSTRUCTIONS.md`, or a prompt against `agents.yaml` - an instruction
|
|
52
52
|
to use a tool the agent does not hold, to hand to an agent that is not in its
|
|
53
53
|
`handoffs:`, or to load a skill outside its `allow:`.
|
|
54
54
|
- **A line that asks for something the system already supplies.** A question put
|
|
55
55
|
to the user about a value that arrives from the environment, a file or an
|
|
56
56
|
earlier step is unanswerable, and the answer would be discarded.
|
|
57
|
-
- **A line the agent cannot carry out**
|
|
57
|
+
- **A line the agent cannot carry out** - naming a path it cannot reach, a tool
|
|
58
58
|
it was not granted, or an agent it cannot transfer to.
|
|
59
59
|
|
|
60
60
|
These are bugs whatever the specification says: fix them in place and report each
|
|
@@ -83,19 +83,19 @@ the model to compute or remember. Specifically:
|
|
|
83
83
|
Never delete an **extra** without saying so. Report it, say why the
|
|
84
84
|
specification does not cover it, and leave it unless I tell you to remove it.
|
|
85
85
|
|
|
86
|
-
Do not invent a value the specification does not state
|
|
86
|
+
Do not invent a value the specification does not state - a model id, a limit, a
|
|
87
87
|
retry count, a file path. That is an entry in `SPECIFICATION-FEEDBACK.md`, not a
|
|
88
88
|
guess.
|
|
89
89
|
|
|
90
90
|
## 4. Every setup step is a script
|
|
91
91
|
|
|
92
|
-
Anything the project needs done before it can run
|
|
93
|
-
a document, generating a file, warming the sandbox image
|
|
92
|
+
Anything the project needs done before it can run - building an index, fetching
|
|
93
|
+
a document, generating a file, warming the sandbox image - is a shell script,
|
|
94
94
|
not a paragraph of instructions for a human.
|
|
95
95
|
|
|
96
96
|
- One step per file, under `scripts/`, named after the step:
|
|
97
97
|
`scripts/build-schema-index.sh`, `scripts/fetch-api-docs.sh`.
|
|
98
|
-
- `scripts/_setup.sh` is the **only** entry point
|
|
98
|
+
- `scripts/_setup.sh` is the **only** entry point - the leading underscore is
|
|
99
99
|
what separates the runner from the steps it runs. It runs the steps in the
|
|
100
100
|
order they depend on each other and is the single command that initialises the
|
|
101
101
|
project. `zen init` writes it; adding a step is adding `scripts/<name>.sh` and
|
|
@@ -114,7 +114,7 @@ not a paragraph of instructions for a human.
|
|
|
114
114
|
- **It must be watchable.** `scripts/_setup.sh` tees each step's output to
|
|
115
115
|
`.tmp/logs/setup-<step>.log`, prints a heartbeat line while a long step runs,
|
|
116
116
|
and finishes with one line per step: `ok`, `skipped`, or `failed`.
|
|
117
|
-
- **Everything transient goes under `.tmp/`**
|
|
117
|
+
- **Everything transient goes under `.tmp/`** - logs, scratch files, downloads,
|
|
118
118
|
test output, and the temporary path a step writes to before moving its
|
|
119
119
|
artefact into place. Nothing else in the tree is a scratch directory, and
|
|
120
120
|
`.tmp/` is git-ignored: add it to `.gitignore` if it is not there already.
|
|
@@ -138,26 +138,26 @@ The file is scanned before it is read, so keep the emoji on every heading:
|
|
|
138
138
|
```markdown
|
|
139
139
|
# Feedback on SPECIFICATION.md
|
|
140
140
|
|
|
141
|
-
## 🛑 Blocking
|
|
141
|
+
## 🛑 Blocking - cannot implement without an answer
|
|
142
142
|
|
|
143
|
-
## ❓ Ambiguous
|
|
143
|
+
## ❓ Ambiguous - implemented one way, confirm the choice
|
|
144
144
|
|
|
145
145
|
## ⚡ Contradictions
|
|
146
146
|
|
|
147
147
|
## ✏️ Errors and typos
|
|
148
148
|
|
|
149
|
-
## ➕ Out of scope
|
|
149
|
+
## ➕ Out of scope - implemented but unspecified
|
|
150
150
|
```
|
|
151
151
|
|
|
152
152
|
Each entry is one bullet, opening with the emoji of the heading it sits under,
|
|
153
153
|
then four parts in this order:
|
|
154
154
|
|
|
155
155
|
- **What the specification says**, quoted, with the section it is in.
|
|
156
|
-
- **Why it cannot be implemented as written**
|
|
157
|
-
- **What was done in the meantime**, or "nothing
|
|
156
|
+
- **Why it cannot be implemented as written** - the specific gap, not "unclear".
|
|
157
|
+
- **What was done in the meantime**, or "nothing - blocked".
|
|
158
158
|
- **The question**, phrased so a one-line answer unblocks it.
|
|
159
159
|
|
|
160
|
-
Use no other emoji anywhere in the file
|
|
160
|
+
Use no other emoji anywhere in the file - one per entry is what makes them
|
|
161
161
|
scannable. Keep entries factual and short. Do not editorialise about the
|
|
162
162
|
specification's quality, do not restate the runtime, and do not copy the whole
|
|
163
163
|
section in.
|
|
@@ -169,7 +169,7 @@ this pass has actually resolved it, and say in the chat which ones you closed.
|
|
|
169
169
|
After `zen check` passes, run `scripts/_setup.sh` yourself. A pass is not done
|
|
170
170
|
until it has run to completion in this session.
|
|
171
171
|
|
|
172
|
-
It is slow
|
|
172
|
+
It is slow - an embedding index is minutes, not seconds - so start it in the
|
|
173
173
|
background and follow the logs instead of waiting blind:
|
|
174
174
|
|
|
175
175
|
- Tail `.tmp/logs/setup-*.log` and check the output artefact is still growing.
|
|
@@ -182,7 +182,7 @@ background and follow the logs instead of waiting blind:
|
|
|
182
182
|
- Do not kill a quiet step. Confirm the process is dead or the log and the
|
|
183
183
|
output have both stopped growing before calling it stuck.
|
|
184
184
|
- On failure, read that step's log, fix the cause, and run `scripts/_setup.sh`
|
|
185
|
-
again
|
|
185
|
+
again - re-running is the fix path, not a reset. If the same step fails twice
|
|
186
186
|
for the same reason, stop and raise it in `SPECIFICATION-FEEDBACK.md`.
|
|
187
187
|
- Prove re-entrancy: once it has succeeded, run `scripts/_setup.sh` once more and
|
|
188
188
|
check that every step reports `skipped` rather than rebuilding.
|
|
@@ -196,7 +196,7 @@ fail. Then report in the chat:
|
|
|
196
196
|
|
|
197
197
|
- what changed, file by file, and which specification item each change closes
|
|
198
198
|
- every prompt or skill line that served no specification item, and what became
|
|
199
|
-
of it
|
|
199
|
+
of it - corrected, or reported and left alone
|
|
200
200
|
- the outcome of every `scripts/_setup.sh` step, and what each one produced
|
|
201
201
|
- what is still open, with a pointer to its `SPECIFICATION-FEEDBACK.md` entry
|
|
202
202
|
- anything you found that the specification does not cover at all
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: zen-cli
|
|
3
|
-
description: How to drive this project from the terminal with `zen`
|
|
3
|
+
description: How to drive this project from the terminal with `zen` - running it, validating it, credentials, the sandbox, run reports, and the `faker` and `rag` modules.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# The `zen` command line
|
|
@@ -36,7 +36,7 @@ zen rag docs <index|search|list|grep|show|stats> [path...]
|
|
|
36
36
|
## Read the reference before answering
|
|
37
37
|
|
|
38
38
|
The full reference lives next to this file, one document per part of the command
|
|
39
|
-
line. **Read the one that covers the question before answering it**
|
|
39
|
+
line. **Read the one that covers the question before answering it** - do not
|
|
40
40
|
guess a flag, and do not read them all.
|
|
41
41
|
|
|
42
42
|
| The question is about | Read |
|
|
@@ -50,8 +50,8 @@ guess a flag, and do not read them all.
|
|
|
50
50
|
| The container shell commands run in, images, `persist` | [sandbox.md](./references/sandbox.md) |
|
|
51
51
|
| Run reports, trajectories, what a session directory holds | [inspect.md](./references/inspect.md) |
|
|
52
52
|
| What the agents remember, why something was recalled, forgetting | [memory.md](./references/memory.md) |
|
|
53
|
-
| `zen faker`
|
|
54
|
-
| `zen rag`
|
|
53
|
+
| `zen faker` - a mock API from an OpenAPI/Swagger document | [faker.md](./references/faker.md) |
|
|
54
|
+
| `zen rag` - searching an API description, or a pile of markdown | [rag.md](./references/rag.md) |
|
|
55
55
|
|
|
56
56
|
## The short version
|
|
57
57
|
|
|
@@ -67,6 +67,62 @@ zen models test <ref> whether one model actually answers
|
|
|
67
67
|
zen models pick --embedding the first embedder that does, on stdout
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
## Searching documents without help
|
|
71
|
+
|
|
72
|
+
Use `zen rag docs` for a directory of Markdown or text, and put the index path
|
|
73
|
+
in `-d <index-dir>` when it is not beside the working directory. These commands
|
|
74
|
+
are enough to discover the corpus and retrieve evidence; do not spend a turn on
|
|
75
|
+
`--help` first:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
zen rag docs list files -d <index-dir>
|
|
79
|
+
zen rag docs list sections -d <index-dir> --file "<path-pattern>"
|
|
80
|
+
zen rag docs search -d <index-dir> "<question in natural language>"
|
|
81
|
+
zen rag docs search -d <index-dir> --file "<path-pattern>" --section "<heading>" "<question>"
|
|
82
|
+
zen rag docs grep -d <index-dir> "<exact string>" --file "<path-pattern>"
|
|
83
|
+
zen rag docs show -d <index-dir> "<file>" --section "<heading>"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Start with one ordinary hybrid question. It is the best default for concepts and
|
|
87
|
+
open questions. Search returns candidates, not proof: read the quoted lines,
|
|
88
|
+
then use `show` or `grep` before claiming a fact is present or absent.
|
|
89
|
+
|
|
90
|
+
When the first answer is from the wrong product area, version, file, or heading,
|
|
91
|
+
ask the same question again with `--file` and then `--section`. A bare `--file`
|
|
92
|
+
value is a substring; `*` and `?` make it a glob. Use `--kind table` or
|
|
93
|
+
`--kind table_row` for limits and matrices, `--mode text` for a known exact
|
|
94
|
+
phrase, and `--exclude-id <id>` to continue past an already-read passage.
|
|
95
|
+
|
|
96
|
+
`--file` is the primary scope control: repeat it to admit several document
|
|
97
|
+
families, and use `--exclude-file` to remove a noisy family. Both are resolved
|
|
98
|
+
before ranking, so a result cannot come from an excluded document. `--section`
|
|
99
|
+
then keeps only a matching heading and its nested headings within those files.
|
|
100
|
+
For example, search two manual families but exclude archived releases:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
zen rag docs search -d <index-dir> --file "manual-*/**" --file "guide-*/**" \
|
|
104
|
+
--exclude-file "*-archive/**" --section "Operations" "<question>"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Hybrid is not a vector reranker. It retrieves a candidate list from full-text
|
|
108
|
+
search and another from vector similarity, then fuses their ranks. Full-text
|
|
109
|
+
finds literal terms; vector search finds passages with the same meaning even
|
|
110
|
+
when their wording differs. `--mode text` or `--mode vector` runs only one leg;
|
|
111
|
+
ordinary hybrid runs both and is normally the right choice.
|
|
112
|
+
|
|
113
|
+
Use `--text-query` with `--vector-query` only when one wording cannot serve both
|
|
114
|
+
retrievers: a distinctive corpus term or command for the text leg, and the full
|
|
115
|
+
question for the vector leg. For example:
|
|
116
|
+
|
|
117
|
+
```sh
|
|
118
|
+
zen rag docs search -d <index-dir> --text-query "exact identifier" \
|
|
119
|
+
--vector-query "what it means and how to use it"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This is not a general upgrade over hybrid search. Generic product names and
|
|
123
|
+
common nouns make weak text legs that can displace better semantic results. The
|
|
124
|
+
two flags replace positional text and `--mode`; give neither alongside them.
|
|
125
|
+
|
|
70
126
|
Run `zen check` after any edit to `agents.yaml`, a prompt or a skill: it reads
|
|
71
127
|
the project the way a run does, reports everything wrong at once, and calls no
|
|
72
128
|
model. It is the cheapest possible test.
|
|
@@ -75,7 +131,7 @@ When behaviour is wrong and the prompt looks right, open the run report. It
|
|
|
75
131
|
shows what the model was actually given, which is rarely what you assumed.
|
|
76
132
|
|
|
77
133
|
Flags always beat the file: the repository states intent, the invocation
|
|
78
|
-
overrides it. Failure messages name the offending key or file
|
|
79
|
-
names the exact path, as in `agents.yaml: agents[1].skills.discovery
|
|
134
|
+
overrides it. Failure messages name the offending key or file - a load error
|
|
135
|
+
names the exact path, as in `agents.yaml: agents[1].skills.discovery - …` - so
|
|
80
136
|
read it rather than guessing. The loader is strict on purpose, and an unknown
|
|
81
137
|
key is an error rather than a value quietly ignored.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Validating
|
|
1
|
+
# Validating - `zen check`
|
|
2
2
|
|
|
3
3
|
It reads the project without running it, and spends a few tokens asking each
|
|
4
4
|
model to answer once; `--no-models` gives an answer that costs nothing at all.
|
|
@@ -47,7 +47,7 @@ checked too. A word that is neither is a usage error (exit 2), not a report.
|
|
|
47
47
|
is a warning (`.unreachable`), because that is the network's problem and not
|
|
48
48
|
the project's.
|
|
49
49
|
- The sandbox: paths stay inside the project, the Dockerfile and its context
|
|
50
|
-
exist, and
|
|
50
|
+
exist, and - unless `--no-sandbox` - the image **builds** and one command runs
|
|
51
51
|
in it, against a temporary directory rather than your workspace. No container
|
|
52
52
|
engine at all is a warning, not an error.
|
|
53
53
|
|
|
@@ -71,7 +71,7 @@ embedding.refused embedding.unreachable embedding.unusable
|
|
|
71
71
|
credential.* service.credential
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
The report goes to **stdout**
|
|
74
|
+
The report goes to **stdout** - it is the answer. `--json` gives the same
|
|
75
75
|
findings as data.
|
|
76
76
|
|
|
77
77
|
Exit codes: `0` nothing wrong, `3` at least one error, or with `--strict` at
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Mock APIs
|
|
1
|
+
# Mock APIs - `zen faker`
|
|
2
2
|
|
|
3
3
|
```
|
|
4
4
|
zen faker <serve|build|cache> [spec...]
|
|
5
5
|
```
|
|
6
6
|
|
|
7
|
-
Alias: `zen mock`. Provided by `@zenera/faker`
|
|
7
|
+
Alias: `zen mock`. Provided by `@zenera/faker` - `npm i -g @zenera/faker` if
|
|
8
8
|
`zen faker` says it is not installed.
|
|
9
9
|
|
|
10
10
|
Serves a mock API from one or more OpenAPI/Swagger documents. For each
|
|
@@ -39,16 +39,16 @@ front and exits non-zero, with a table, if any could not be written.
|
|
|
39
39
|
| `--model <ref>` | project default | Which model writes the generators |
|
|
40
40
|
| `--image <ref>` | a baked image | Skip the baked image and use this one |
|
|
41
41
|
| `--cache <dir>` | `~/.zenera/neo/faker` | Where generators live |
|
|
42
|
-
| `--seed <n>` |
|
|
42
|
+
| `--seed <n>` | - | Answer the same request the same way every time |
|
|
43
43
|
| `--attempts <n>` | `3` | Tries per generator before giving up |
|
|
44
44
|
| `--concurrency <n>` | `4` | Generators written at once |
|
|
45
45
|
| `--timeout <s>` | `30` | Seconds one generator may take |
|
|
46
46
|
| `--max-body <n>` | 1 MB | Largest request body accepted, in bytes |
|
|
47
|
-
| `--rebuild` |
|
|
48
|
-
| `--no-cache` |
|
|
49
|
-
| `--quiet` |
|
|
47
|
+
| `--rebuild` | - | Ignore what is cached and write it again |
|
|
48
|
+
| `--no-cache` | - | Do not record what is written |
|
|
49
|
+
| `--quiet` | - | No narration |
|
|
50
50
|
|
|
51
|
-
Credentials come from the `zen` keyring
|
|
51
|
+
Credentials come from the `zen` keyring - see [keys.md](keys.md).
|
|
52
52
|
|
|
53
53
|
## Serving
|
|
54
54
|
|
|
@@ -66,19 +66,19 @@ Response headers:
|
|
|
66
66
|
| Header | Meaning |
|
|
67
67
|
| ------------------- | ----------------------------------------------------- |
|
|
68
68
|
| `x-faker-operation` | The `operationId` that answered |
|
|
69
|
-
| `x-faker-cache` | `hit` or `miss`
|
|
69
|
+
| `x-faker-cache` | `hit` or `miss` - whether this call cost a model turn |
|
|
70
70
|
|
|
71
71
|
Incoming headers are filtered: `authorization`, `cookie` and anything matching
|
|
72
72
|
`key|token|secret|password|credential` never reach a generator.
|
|
73
73
|
|
|
74
74
|
`--seed` makes each request's seed a hash of the seed, the operation and the
|
|
75
|
-
parameters, so the same request answers identically across restarts
|
|
75
|
+
parameters, so the same request answers identically across restarts - which is
|
|
76
76
|
what makes a mock usable in a test.
|
|
77
77
|
|
|
78
78
|
## What "correct" means here
|
|
79
79
|
|
|
80
80
|
A generator is judged on two synthetic probes: the body validates against the
|
|
81
|
-
response schema, **and** it obeys the **echo rule**
|
|
81
|
+
response schema, **and** it obeys the **echo rule** - a value given in the path
|
|
82
82
|
comes back in the answer. `GET /users/12324` must return `user_id: 12324`. A body
|
|
83
83
|
can validate perfectly and still be about the wrong entity, which is exactly the
|
|
84
84
|
mock that wastes an afternoon.
|
|
@@ -87,16 +87,16 @@ Query parameters are deliberately not enforced: `?source=realtime`, `?page_size`
|
|
|
87
87
|
and `?cursor` are controls, and their names collide with unrelated response
|
|
88
88
|
fields.
|
|
89
89
|
|
|
90
|
-
Probes are synthetic on purpose
|
|
90
|
+
Probes are synthetic on purpose - real request bodies never reach a prompt.
|
|
91
91
|
|
|
92
92
|
## The cache
|
|
93
93
|
|
|
94
94
|
Generators live in the machine's shared cache, `~/.zenera/neo/cache/faker-generator/`,
|
|
95
|
-
keyed by the operation's shape
|
|
95
|
+
keyed by the operation's shape - so the same spec served from two directories is
|
|
96
96
|
written once, and a spec edit produces a new key rather than a stale answer. A
|
|
97
97
|
generator that a model gave up on is remembered for the life of the process, so
|
|
98
|
-
a hopeless operation is not re-asked on every request; a _transient_ failure
|
|
99
|
-
429, a dropped socket
|
|
98
|
+
a hopeless operation is not re-asked on every request; a _transient_ failure - a
|
|
99
|
+
429, a dropped socket - is not, because it is about this minute rather than this
|
|
100
100
|
operation.
|
|
101
101
|
|
|
102
102
|
`~/.zenera/neo/faker/` is the container's workspace, and scratch: a cache hit is
|
|
@@ -48,7 +48,7 @@ Progress, banners, warnings and the spinner go to stderr. So
|
|
|
48
48
|
|
|
49
49
|
`--json` applies to every command and prints one machine-readable document on
|
|
50
50
|
stdout in place of the rendered form. Under `--json` nothing is asked
|
|
51
|
-
interactively
|
|
51
|
+
interactively - the questions a run would ask are taken as answered.
|
|
52
52
|
|
|
53
53
|
The banner is drawn only when stderr is a terminal, so a piped invocation never
|
|
54
54
|
sees it.
|
|
@@ -60,13 +60,13 @@ sees it.
|
|
|
60
60
|
| 0 | ok | It worked |
|
|
61
61
|
| 1 | failed | It ran and did not succeed |
|
|
62
62
|
| 2 | usage | The command line was wrong |
|
|
63
|
-
| 3 | invalid | The project is not valid
|
|
63
|
+
| 3 | invalid | The project is not valid - bad `agents.yaml`, missing file |
|
|
64
64
|
| 4 | credentials | No usable credential for what was asked |
|
|
65
65
|
| 5 | sandbox | No container engine, or the image could not be prepared |
|
|
66
66
|
|
|
67
67
|
A wrong invocation and a wrong answer are deliberately not the same code, which
|
|
68
68
|
is what a script needs. Failure messages name the offending key or file; a load
|
|
69
|
-
error names the exact path, as in `agents.yaml: agents[1].skills.discovery
|
|
69
|
+
error names the exact path, as in `agents.yaml: agents[1].skills.discovery - …`.
|
|
70
70
|
Read it rather than guessing: the loader is strict on purpose and an unknown key
|
|
71
71
|
is an error, not a value quietly ignored.
|
|
72
72
|
|
|
@@ -74,7 +74,7 @@ is an error, not a value quietly ignored.
|
|
|
74
74
|
|
|
75
75
|
Most commands operate on a project directory, resolved in this order:
|
|
76
76
|
|
|
77
|
-
1. `--project <name|dir>`
|
|
77
|
+
1. `--project <name|dir>` - a registry name or a path.
|
|
78
78
|
2. The working directory, if it is a project (or is inside one).
|
|
79
79
|
3. For `zen run`, a bare first word that names a registered project.
|
|
80
80
|
|
|
@@ -92,7 +92,7 @@ unregistered directory can still be validated.
|
|
|
92
92
|
| `ZENERA_DEBUG` | Print a stack trace when something unexpected escapes |
|
|
93
93
|
| `VISUAL`, `EDITOR` | Consulted by `zen open` after `ZENERA_EDITOR` |
|
|
94
94
|
| `COLORFGBG` | Read as a hint when the palette is being detected |
|
|
95
|
-
| Provider keys | `OPENAI_API_KEY` and friends
|
|
95
|
+
| Provider keys | `OPENAI_API_KEY` and friends - see [keys.md](keys.md) |
|
|
96
96
|
|
|
97
97
|
A real environment variable always beats the keyring.
|
|
98
98
|
|
|
@@ -112,7 +112,7 @@ A real environment variable always beats the keyring.
|
|
|
112
112
|
agents/prompts/ one .md per agent
|
|
113
113
|
agents/skills/ one directory per skill, each with SKILL.md
|
|
114
114
|
sandbox/Dockerfile the image commands run in, when the project builds one
|
|
115
|
-
sessions/ run state, memory, blobs, reports
|
|
115
|
+
sessions/ run state, memory, blobs, reports - never committed
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
Credential files are refused if anyone but the owner can read them, the way
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Reports
|
|
1
|
+
# Reports - `zen inspect`
|
|
2
2
|
|
|
3
3
|
```
|
|
4
4
|
zen inspect [run] [--session <id>] [--open] [--rebuild] [--serve [port]]
|
|
@@ -29,7 +29,7 @@ was assembled differently from how it looks in the repository: a skill that did
|
|
|
29
29
|
not activate, a hand-off that fired early, a tool that was withheld, an asset
|
|
30
30
|
that was not attached.
|
|
31
31
|
|
|
32
|
-
The report also draws the architecture
|
|
32
|
+
The report also draws the architecture - agents, their tools, their hand-offs -
|
|
33
33
|
and falls back to reconstructing the wiring from the trajectory when the run
|
|
34
34
|
did not record it.
|
|
35
35
|
|
|
@@ -52,7 +52,7 @@ resolves them back.
|
|
|
52
52
|
|
|
53
53
|
## What it prints
|
|
54
54
|
|
|
55
|
-
The path to `report.html` on stdout
|
|
55
|
+
The path to `report.html` on stdout - it is the answer, so it pipes. `--json`
|
|
56
56
|
gives `{ session, run, report }` instead. A report that is missing is built
|
|
57
57
|
before either; `--rebuild` builds one that already exists again, which is always
|
|
58
58
|
safe because the report is derived and `state.json` is the truth. That is also
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Credentials
|
|
1
|
+
# Credentials - `zen key`
|
|
2
2
|
|
|
3
3
|
```
|
|
4
4
|
zen key <ls|add|use|check|rm|show|env> [ref] [options]
|
|
@@ -85,7 +85,7 @@ behind, marked `~` and named for the variable rather than for a key:
|
|
|
85
85
|
~ vertex/adc …/application_default_credentials.json
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
These can be listed and checked, not chosen or forgotten
|
|
88
|
+
These can be listed and checked, not chosen or forgotten - there is nothing to
|
|
89
89
|
choose between, and nothing of ours to remove. Unset the variable, or
|
|
90
90
|
`gcloud auth application-default revoke`.
|
|
91
91
|
|
|
@@ -94,15 +94,15 @@ choose between, and nothing of ours to remove. Unset the variable, or
|
|
|
94
94
|
`zen key check` and `zen key ls --check` do one round trip per key and record
|
|
95
95
|
the verdict:
|
|
96
96
|
|
|
97
|
-
- **live**
|
|
97
|
+
- **live** - authenticated. A rate-limited answer counts as live, because it
|
|
98
98
|
proves the credential.
|
|
99
|
-
- **dead**
|
|
100
|
-
- **blocked**
|
|
99
|
+
- **dead** - the provider rejected it. A verdict.
|
|
100
|
+
- **blocked** - the credential was accepted and the **account** refused: an API
|
|
101
101
|
switched off in the project, an empty balance, a model this key was never
|
|
102
102
|
granted. Do not rotate the key; a new one is refused identically. The check
|
|
103
|
-
carries a `fix`
|
|
103
|
+
carries a `fix` - for a disabled Google API, the exact
|
|
104
104
|
`gcloud services enable <api> --project <id>`.
|
|
105
|
-
- **unknown**
|
|
105
|
+
- **unknown** - the provider could not be asked. Says nothing about the key;
|
|
106
106
|
usually the network.
|
|
107
107
|
|
|
108
108
|
`zen init` uses the same probe to pick which provider to scaffold with, so a
|
|
@@ -110,9 +110,9 @@ project is not built around a revoked key.
|
|
|
110
110
|
|
|
111
111
|
## When a run says there is no credential
|
|
112
112
|
|
|
113
|
-
The frame does **not** materialise the keyring for you
|
|
113
|
+
The frame does **not** materialise the keyring for you - each command that needs
|
|
114
114
|
a credential opens the store itself. If `zen key ls` shows a key as live and a
|
|
115
|
-
command still says `provider "openai": no api key
|
|
115
|
+
command still says `provider "openai": no api key - set OPENAI_API_KEY`, the
|
|
116
116
|
credential is fine and the command is at fault. Everything that runs a model
|
|
117
117
|
(`run`, `check`, `models`, `faker`, `rag`) already does this.
|
|
118
118
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Memory
|
|
1
|
+
# Memory - `zen memory`
|
|
2
2
|
|
|
3
3
|
```
|
|
4
4
|
zen memory [stats|ls|show|export|forget] [args] [options]
|
|
@@ -45,7 +45,7 @@ is masked, ranked and truncated as well, so what an agent gets is never the
|
|
|
45
45
|
whole picture.
|
|
46
46
|
|
|
47
47
|
This command ignores all of that. When the mask is the thing that is wrong, the
|
|
48
|
-
part that was hidden is exactly the part you need
|
|
48
|
+
part that was hidden is exactly the part you need - and this is a person at a
|
|
49
49
|
terminal in the project directory, not an agent inside a run.
|
|
50
50
|
|
|
51
51
|
It also contacts no model. The store is opened without an embedder, so
|
|
@@ -60,12 +60,12 @@ zen memory export --open
|
|
|
60
60
|
|
|
61
61
|
One self-contained HTML file, three panes:
|
|
62
62
|
|
|
63
|
-
- **left**
|
|
63
|
+
- **left** - every node, with a search box and filters for kind, audience,
|
|
64
64
|
files, superseded and unlinked
|
|
65
|
-
- **middle**
|
|
65
|
+
- **middle** - the graph as a Mermaid diagram, coloured by kind, with pan,
|
|
66
66
|
zoom, and a hop-focus selector for following one node's neighbourhood
|
|
67
|
-
- **right**
|
|
68
|
-
and **the remembered file's actual content**
|
|
67
|
+
- **right** - whatever you clicked, in full: the text, the metadata, the links,
|
|
68
|
+
and **the remembered file's actual content** - rendered as an image when it is
|
|
69
69
|
one, and as text otherwise
|
|
70
70
|
|
|
71
71
|
Clicking a node in either the list or the diagram selects it in both. Above 300
|
|
@@ -83,15 +83,15 @@ zen memory forget 01M1YPN0C8QRQS5BCZ03ABQ1G0
|
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
Asks first, unless `--yes`, and refuses outright when there is no terminal to
|
|
86
|
-
ask at. A node, its vector row and its remembered file bytes go together
|
|
86
|
+
ask at. A node, its vector row and its remembered file bytes go together -
|
|
87
87
|
there is one implementation of that, shared with the agent-facing tool, so the
|
|
88
88
|
three cannot drift apart.
|
|
89
89
|
|
|
90
90
|
**Forgetting is rarely the right correction.** The agents' own way to fix a
|
|
91
91
|
wrong memory is to commit the corrected node and supersede the old one, which
|
|
92
92
|
keeps the record of having been wrong. `zen memory ls --stale` lists what has
|
|
93
|
-
been superseded that way. Use `forget` for what should never have been stored
|
|
94
|
-
a secret, a mistake, a pile of noise
|
|
93
|
+
been superseded that way. Use `forget` for what should never have been stored -
|
|
94
|
+
a secret, a mistake, a pile of noise - not for what merely became untrue.
|
|
95
95
|
|
|
96
96
|
## Reading `stats`
|
|
97
97
|
|
|
@@ -100,8 +100,8 @@ nodes 7
|
|
|
100
100
|
edges 6
|
|
101
101
|
superseded 1
|
|
102
102
|
files 1 · 640 B
|
|
103
|
-
embedding none
|
|
104
|
-
vectors
|
|
103
|
+
embedding none - recall falls back to term overlap
|
|
104
|
+
vectors -
|
|
105
105
|
```
|
|
106
106
|
|
|
107
107
|
`embedding none` is worth noticing: without an embedder, recall matches on
|