@zenera/cli 1.1.9 → 1.1.11

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.
Files changed (45) hide show
  1. package/README.md +49 -15
  2. package/dist/cache.d.ts +98 -0
  3. package/dist/cache.js +301 -0
  4. package/dist/catalog.d.ts +3 -0
  5. package/dist/catalog.js +35 -11
  6. package/dist/commands/cache.d.ts +7 -0
  7. package/dist/commands/cache.js +245 -0
  8. package/dist/commands/check.js +6 -3
  9. package/dist/commands/index.js +3 -1
  10. package/dist/commands/key.js +68 -14
  11. package/dist/commands/models.js +17 -1
  12. package/dist/commands/run.js +11 -3
  13. package/dist/commands/sandbox.js +70 -23
  14. package/dist/history.d.ts +18 -0
  15. package/dist/history.js +93 -0
  16. package/dist/home.d.ts +2 -2
  17. package/dist/home.js +2 -2
  18. package/dist/keys.d.ts +22 -0
  19. package/dist/keys.js +105 -2
  20. package/dist/lib.d.ts +1 -0
  21. package/dist/lib.js +1 -0
  22. package/dist/liveness.js +11 -0
  23. package/dist/resolve.d.ts +4 -0
  24. package/dist/resolve.js +43 -17
  25. package/dist/term.d.ts +25 -2
  26. package/dist/term.js +224 -10
  27. package/dist/tui/app.d.ts +10 -0
  28. package/dist/tui/app.js +542 -58
  29. package/dist/tui/theme.d.ts +6 -2
  30. package/dist/tui/theme.js +14 -8
  31. package/dist/tui/wrap.d.ts +92 -0
  32. package/dist/tui/wrap.js +147 -2
  33. package/dist/validate.d.ts +2 -0
  34. package/dist/validate.js +87 -2
  35. package/package.json +2 -2
  36. package/templates/editor/.github/copilot-instructions.md +50 -13
  37. package/templates/editor/.github/prompts/new-agent.prompt.md +5 -2
  38. package/templates/editor/.github/prompts/sync-with-spec.prompt.md +202 -0
  39. package/templates/editor/.github/skills/zen-cli/SKILL.md +2 -1
  40. package/templates/editor/.github/skills/zen-cli/references/faker.md +18 -8
  41. package/templates/editor/.github/skills/zen-cli/references/keys.md +7 -7
  42. package/templates/editor/.github/skills/zen-cli/references/rag.md +104 -0
  43. package/templates/editor/.github/skills/zen-rag-docs/SKILL.md +575 -0
  44. package/templates/editor/.github/skills/{api-schema-index → zen-rag-schema}/SKILL.md +28 -20
  45. package/templates/editor/.vscode/settings.json +1 -1
@@ -0,0 +1,202 @@
1
+ ---
2
+ description: Bring the project into compliance with SPECIFICATION.md, and record every open question in SPECIFICATION-FEEDBACK.md.
3
+ ---
4
+
5
+ Make this project match `SPECIFICATION.md`. The specification is the intent;
6
+ the files are the implementation. Where they disagree, the specification wins —
7
+ except where it is ambiguous, contradictory or impossible, which is what
8
+ `SPECIFICATION-FEEDBACK.md` is for.
9
+
10
+ ## 1. Read before changing anything
11
+
12
+ Read, in this order, and do not edit until all of it is read:
13
+
14
+ 1. `SPECIFICATION.md` — what the system is meant to be.
15
+ 2. `agents.yaml` — providers, models, embeddings, agents, tools, handoffs,
16
+ skills, sandbox.
17
+ 3. `INSTRUCTIONS.md` and every file under `agents/prompts/`.
18
+ 4. Every `agents/skills/*/SKILL.md`, plus what each skill folder ships.
19
+ 5. `assets/`, `sandbox/Dockerfile` and every script under `scripts/`, starting
20
+ with `scripts/_setup.sh`.
21
+ 6. `SPECIFICATION-FEEDBACK.md`, if it exists — do not re-raise something already
22
+ open there.
23
+
24
+ Run `zen check` first and record what it said. A project that does not load is
25
+ the first thing to fix.
26
+
27
+ ## 2. Build the difference
28
+
29
+ Produce a difference list before touching a file. For every item in the
30
+ specification, decide which of these it is:
31
+
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
+
38
+ Check at least: the model and embedding ids and which agent uses which; that
39
+ every agent named in the specification exists with that job and no second job;
40
+ handoff edges and fork permissions; the tools each agent holds; every skill the
41
+ specification implies; and every setup step, index or asset it depends on.
42
+
43
+ Then build the difference the other way, because the list above can only find
44
+ what the specification asked for and nothing implements. Read `INSTRUCTIONS.md`,
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** —
47
+ the category covers a single sentence in a prompt, not only a whole file. Three
48
+ things to look for while reading, none of which the forward pass can see:
49
+
50
+ - **A line that contradicts another file.** One prompt against another, a prompt
51
+ against `INSTRUCTIONS.md`, or a prompt against `agents.yaml` — an instruction
52
+ to use a tool the agent does not hold, to hand to an agent that is not in its
53
+ `handoffs:`, or to load a skill outside its `allow:`.
54
+ - **A line that asks for something the system already supplies.** A question put
55
+ to the user about a value that arrives from the environment, a file or an
56
+ earlier step is unanswerable, and the answer would be discarded.
57
+ - **A line the agent cannot carry out** — naming a path it cannot reach, a tool
58
+ it was not granted, or an agent it cannot transfer to.
59
+
60
+ These are bugs whatever the specification says: fix them in place and report each
61
+ one. An extra that is merely unspecified is reported under `➕`, not removed.
62
+
63
+ ## 3. Change the smallest thing that closes the gap
64
+
65
+ Apply the fixes in the order the copilot instructions prefer: a prompt or skill
66
+ edit over a new skill, a new skill over a new agent, a tool grant over asking
67
+ the model to compute or remember. Specifically:
68
+
69
+ - A behaviour gap is a prompt or skill edit, not a new agent.
70
+ - A fact, rate, threshold or command surface goes in a skill, never in a prompt.
71
+ - Arithmetic or a fixed transformation goes in a script under the skill folder,
72
+ called by its absolute `/skills/<name>/…` path.
73
+ - A capability gap is a `tools:` grant plus the prompt line that says when to
74
+ use it. A granted tool no prompt mentions is not implemented.
75
+ - A toolchain the work always needs goes in `sandbox/Dockerfile`, not in a
76
+ prompt that installs it every run.
77
+ - If the project has a `sandbox/Dockerfile`, pin `@zenera/cli` and `@zenera/rag`
78
+ in it to the version of `zen` in hand. Read that version with `zen --version`
79
+ and write it into the `npm install -g` line, so the CLI an agent runs inside
80
+ the container is the same one that built it. An unpinned name drifts away from
81
+ the host on the next image build; a stale pin is a mismatch nothing reports.
82
+
83
+ Never delete an **extra** without saying so. Report it, say why the
84
+ specification does not cover it, and leave it unless I tell you to remove it.
85
+
86
+ Do not invent a value the specification does not state — a model id, a limit, a
87
+ retry count, a file path. That is an entry in `SPECIFICATION-FEEDBACK.md`, not a
88
+ guess.
89
+
90
+ ## 4. Every setup step is a script
91
+
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
+ not a paragraph of instructions for a human.
95
+
96
+ - One step per file, under `scripts/`, named after the step:
97
+ `scripts/build-schema-index.sh`, `scripts/fetch-api-docs.sh`.
98
+ - `scripts/_setup.sh` is the **only** entry point — the leading underscore is
99
+ what separates the runner from the steps it runs. It runs the steps in the
100
+ order they depend on each other and is the single command that initialises the
101
+ project. Consolidate any setup script that lives elsewhere into this shape,
102
+ including one left at the project root.
103
+ - Every script starts `set -eu`, works from any working directory
104
+ (`cd "$(dirname "$0")/.."` first), needs no arguments, and exits non-zero on
105
+ failure so `scripts/_setup.sh` stops rather than continuing on a broken step.
106
+ - **Re-entrancy is required.** Running `scripts/_setup.sh` a second time must be
107
+ safe. A step whose output is present and newer than its inputs prints that it
108
+ is up to date and returns 0; otherwise it redoes the work idempotently, writing
109
+ to a temporary path and moving it into place so an interrupted run never leaves
110
+ a half-built artefact behind. `scripts/_setup.sh --force` redoes everything.
111
+ - **It must be watchable.** `scripts/_setup.sh` tees each step's output to
112
+ `.tmp/logs/setup-<step>.log`, prints a heartbeat line while a long step runs,
113
+ and finishes with one line per step: `ok`, `skipped`, or `failed`.
114
+ - **Everything transient goes under `.tmp/`** — logs, scratch files, downloads,
115
+ test output, and the temporary path a step writes to before moving its
116
+ artefact into place. Nothing else in the tree is a scratch directory, and
117
+ `.tmp/` is git-ignored: add it to `.gitignore` if it is not there already.
118
+ Deleting `.tmp/` must leave the project runnable and `scripts/_setup.sh`
119
+ re-runnable.
120
+ - Steps that need credentials run on the host, not in the sandbox. Read keys
121
+ from the environment or `.env`; never inline one into a script.
122
+ - Anything the sandbox always needs belongs in `sandbox/Dockerfile`, not in a
123
+ setup script that installs it again on every run.
124
+
125
+ ## 5. Write `SPECIFICATION-FEEDBACK.md`
126
+
127
+ Create or update `SPECIFICATION-FEEDBACK.md` at the project root whenever
128
+ anything in the
129
+ specification is unclear, contradictory, impossible, or wrong. If there is
130
+ nothing to raise, say so in the chat and do not create the file.
131
+
132
+ Group entries under these headings, and omit a heading that has no entries.
133
+ The file is scanned before it is read, so keep the emoji on every heading:
134
+
135
+ ```markdown
136
+ # Feedback on SPECIFICATION.md
137
+
138
+ ## 🛑 Blocking — cannot implement without an answer
139
+
140
+ ## ❓ Ambiguous — implemented one way, confirm the choice
141
+
142
+ ## ⚡ Contradictions
143
+
144
+ ## ✏️ Errors and typos
145
+
146
+ ## ➕ Out of scope — implemented but unspecified
147
+ ```
148
+
149
+ Each entry is one bullet, opening with the emoji of the heading it sits under,
150
+ then four parts in this order:
151
+
152
+ - **What the specification says**, quoted, with the section it is in.
153
+ - **Why it cannot be implemented as written** — the specific gap, not "unclear".
154
+ - **What was done in the meantime**, or "nothing — blocked".
155
+ - **The question**, phrased so a one-line answer unblocks it.
156
+
157
+ Use no other emoji anywhere in the file — one per entry is what makes them
158
+ scannable. Keep entries factual and short. Do not editorialise about the
159
+ specification's quality, do not restate the runtime, and do not copy the whole
160
+ section in.
161
+ Append to the existing file rather than rewriting it; strike an entry only when
162
+ this pass has actually resolved it, and say in the chat which ones you closed.
163
+
164
+ ## 6. Run `scripts/_setup.sh` and watch it finish
165
+
166
+ After `zen check` passes, run `scripts/_setup.sh` yourself. A pass is not done
167
+ until it has run to completion in this session.
168
+
169
+ It is slow — an embedding index is minutes, not seconds — so start it in the
170
+ background and follow the logs instead of waiting blind:
171
+
172
+ - Tail `.tmp/logs/setup-*.log` and check the output artefact is still growing.
173
+ - **Wait in a loop, never in one long sleep.** Sleep at most 30 seconds at a
174
+ time, then check the log and say what it shows, and repeat until the step
175
+ finishes. A single long block makes the run unwatchable and hides a failure
176
+ that happened in the first ten seconds.
177
+ - Report progress as you go: which step is running, how long it has been going,
178
+ what the last log line said.
179
+ - Do not kill a quiet step. Confirm the process is dead or the log and the
180
+ output have both stopped growing before calling it stuck.
181
+ - On failure, read that step's log, fix the cause, and run `scripts/_setup.sh`
182
+ again — re-running is the fix path, not a reset. If the same step fails twice
183
+ for the same reason, stop and raise it in `SPECIFICATION-FEEDBACK.md`.
184
+ - Prove re-entrancy: once it has succeeded, run `scripts/_setup.sh` once more and
185
+ check that every step reports `skipped` rather than rebuilding.
186
+
187
+ ## 7. Verify and report
188
+
189
+ Run `zen check` again and fix whatever it names rather than working around it.
190
+ It validates structure and says nothing about the prose, so work §9 of the
191
+ copilot instructions as a checklist afterwards and report each group pass or
192
+ fail. Then report in the chat:
193
+
194
+ - what changed, file by file, and which specification item each change closes
195
+ - every prompt or skill line that served no specification item, and what became
196
+ of it — corrected, or reported and left alone
197
+ - the outcome of every `scripts/_setup.sh` step, and what each one produced
198
+ - what is still open, with a pointer to its `SPECIFICATION-FEEDBACK.md` entry
199
+ - anything you found that the specification does not cover at all
200
+
201
+ Do not report a specification item as done unless the file that implements it
202
+ exists, `zen check` passes, and `scripts/_setup.sh` completed every step it owns.
@@ -29,6 +29,7 @@ zen version
29
29
 
30
30
  zen faker <serve|build|cache> [spec...]
31
31
  zen rag schema <index|search|list|grep|trace|show|stats> [spec...]
32
+ zen rag docs <index|search|list|grep|show|stats> [path...]
32
33
  ```
33
34
 
34
35
  ## Read the reference before answering
@@ -48,7 +49,7 @@ guess a flag, and do not read them all.
48
49
  | The container shell commands run in, images, `persist` | [sandbox.md](./references/sandbox.md) |
49
50
  | Run reports, trajectories, what a session directory holds | [inspect.md](./references/inspect.md) |
50
51
  | `zen faker` — a mock API from an OpenAPI/Swagger document | [faker.md](./references/faker.md) |
51
- | `zen rag` — searching an OpenAPI/Swagger document as a graph | [rag.md](./references/rag.md) |
52
+ | `zen rag` — searching an API description, or a pile of markdown | [rag.md](./references/rag.md) |
52
53
 
53
54
  ## The short version
54
55
 
@@ -91,17 +91,27 @@ Probes are synthetic on purpose — real request bodies never reach a prompt.
91
91
 
92
92
  ## The cache
93
93
 
94
- Under `~/.zenera/neo/faker/generators/<key>/`, one directory per operation. A
95
- generator that a model gave up on is remembered, so a hopeless operation is not
96
- re-asked on every request; a _transient_ failure a 429, a dropped socket — is
97
- not, because it is about this minute rather than this operation.
98
-
99
- `zen faker cache clear` removes the generators and the container together. They
100
- have to go together: the container's name is a hash of its configuration, so
101
- deleting the directory alone would leave a stopped container bind-mounted onto a
94
+ Generators live in the machine's shared cache, `~/.zenera/neo/cache/faker-generator/`,
95
+ keyed by the operation's shape so the same spec served from two directories is
96
+ written once, and a spec edit produces a new key rather than a stale answer. A
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 — a
99
+ 429, a dropped socket is not, because it is about this minute rather than this
100
+ operation.
101
+
102
+ `~/.zenera/neo/faker/` is the container's workspace, and scratch: a cache hit is
103
+ copied into it, because the container can only run what is under its mount.
104
+
105
+ `zen faker cache ls` lists what has been generated. `zen faker cache clear`
106
+ removes the generators, the workspace and the container together. They have to
107
+ go together: the container's name is a hash of its configuration, so deleting
108
+ the workspace alone would leave a stopped container bind-mounted onto a
102
109
  directory that no longer exists, and every generator would fail with
103
110
  `python3: can't open file '/workspace/generators/…/gen.py'`.
104
111
 
112
+ `zen cache ls --kind faker-generator` reaches the same entries from the other
113
+ side, along with everything else this machine has cached.
114
+
105
115
  ## Documents it accepts
106
116
 
107
117
  Swagger 2 and OpenAPI 3.0/3.1, JSON or YAML, `$ref`s resolved. Several documents
@@ -25,8 +25,8 @@ keys; one of them is active.
25
25
  | `zen key show <ref> [--reveal]` | Masked by default |
26
26
  | `zen key env [provider …]` | Shell exports, for other tools |
27
27
 
28
- `zen key add` also takes `--project` and `--location`, for a Vertex service
29
- account.
28
+ `zen key add` also takes `--gcp-project` and `--gcp-location`, for a Vertex
29
+ service account.
30
30
 
31
31
  ```
32
32
  zen key add openai # prompts, echo off
@@ -56,18 +56,18 @@ echo-off prompt and from nowhere else.
56
56
 
57
57
  A **service-account file** is absorbed into `~/.zenera/neo/keys/` and
58
58
  `GOOGLE_APPLICATION_CREDENTIALS` points at it. It wants a project too, from
59
- `--project`, or `GOOGLE_CLOUD_PROJECT`, or the `project_id` inside the file, and
60
- a region from `--location` (`global` otherwise). Application Default
59
+ `--gcp-project`, or `GOOGLE_CLOUD_PROJECT`, or the `project_id` inside the file,
60
+ and a region from `--gcp-location` (`global` otherwise). Application Default
61
61
  Credentials from `gcloud auth application-default login` work with no entry at
62
62
  all.
63
63
 
64
64
  An **express-mode key** is an ordinary secret under `VERTEX_API_KEY`, and
65
65
  addresses no project: a key and a project are alternatives, and sending both
66
- gets a `403` that mentions neither. `--project` and `--location` are therefore
67
- refused alongside a key.
66
+ gets a `403` that mentions neither. `--gcp-project` and `--gcp-location` are
67
+ therefore refused alongside a key.
68
68
 
69
69
  ```
70
- zen key add vertex --project acme-prod --location europe-west4
70
+ zen key add vertex --gcp-project acme-prod --gcp-location europe-west4
71
71
  # paste a path → the file shape
72
72
  # paste a key → the express shape
73
73
  ```
@@ -327,3 +327,107 @@ found and the endpoint to call is what is actually wanted.
327
327
 
328
328
  They share the group `schema`, so an agent takes them with `schema:*` in its
329
329
  `tools:`.
330
+
331
+ # Document search — `zen rag docs`
332
+
333
+ ```
334
+ zen rag docs <index|search|list|grep|show|stats> [args...]
335
+ ```
336
+
337
+ The second subject of the same command. Where `schema` reads an API description
338
+ as a graph, `docs` reads a pile of **markdown and plain text** and answers with
339
+ the documents themselves: the passages that matched, quoted verbatim with their
340
+ line numbers, and a marker wherever something between two of them was skipped.
341
+
342
+ ## `index`
343
+
344
+ ```
345
+ zen rag docs index <path...> [--embedding <ref>] [-o <dir>] [--chunk-tokens <n>]
346
+ ```
347
+
348
+ | Flag | Default | Meaning |
349
+ | -------------------- | ----------- | ------------------------------------------------------------ |
350
+ | `--embedding <ref>` | — | Which embedder makes the vectors. Omit it to see the choices |
351
+ | `-o`, `--out <dir>` | `./docs-db` | Where the index goes; `$ZEN_DOCS_DB` if set |
352
+ | `--batch <n>` | `96` | Texts per embedding request |
353
+ | `--chunk-tokens <n>` | `384` | Target chunk size |
354
+ | `--quiet` | — | No narration |
355
+
356
+ Paths may be files, directories or globs. `.md`, `.markdown`, `.txt` and
357
+ `.text` are read; hidden directories and `node_modules` are not.
358
+
359
+ Every document is **copied into the index**, and every quoted line is read back
360
+ out of that copy — so the index is one portable thing and what it quotes is the
361
+ document rather than a reconstruction of it. Each document is named by its path
362
+ relative to the common root of everything indexed, which is what keeps
363
+ `nsx_4.1.0/api/routing.md` and `nsx_4.2.0/api/routing.md` apart.
364
+
365
+ ```
366
+ docs-db/
367
+ manifest.json written last; its presence means the index is complete
368
+ outline.json every heading and table, with the lines they cover
369
+ sources/ the documents, verbatim
370
+ lance/ one row per chunk: two texts, one vector, the filter columns
371
+ ```
372
+
373
+ ## `search`
374
+
375
+ ```
376
+ zen rag docs search [text...] [-f <pattern>] [-s <section>] [--kind <k>]
377
+ ```
378
+
379
+ | Flag | Default | Meaning |
380
+ | ------------------------ | -------- | ---------------------------------------------------- |
381
+ | `-f`, `--file <pattern>` | — | Only documents whose name matches. Repeatable |
382
+ | `--exclude-file <p>` | — | Drop documents whose name matches |
383
+ | `-s`, `--section <name>` | — | Only under this heading, and what nests in it |
384
+ | `--kind <k>` | — | `paragraph`, `list`, `table`, `table_row`, `code`, … |
385
+ | `--mode <m>` | `hybrid` | `hybrid`, `vector` or `text` for exact wording |
386
+ | `--limit <n>` | `8` | Passages kept |
387
+ | `-B`, `-A <n>` | `0` | Extra lines quoted before and after each passage |
388
+ | `--max-lines <n>` | `400` | A ceiling on the whole answer |
389
+ | `--exclude-id <id>` | — | Drop a passage already seen. Repeatable |
390
+ | `--hits` | — | One line per passage instead of the text |
391
+ | `--interactive` | — | Prompt, search, narrow, search again |
392
+
393
+ **Narrowing is the interface.** Nobody finds the right paragraph on the first
394
+ ask; the second call is the same question inside one part of the tree.
395
+
396
+ ```
397
+ zen rag docs search "how are rate limits counted"
398
+ zen rag docs search --file "nsx_4.2.*/api/**" "rate limit for the users route"
399
+ zen rag docs search --section "Rate limits" --kind table "requests per minute"
400
+ zen rag docs search --mode text "X-RateLimit-Remaining"
401
+ ```
402
+
403
+ A `--file` pattern with `*` or `?` is a glob over the whole document name and
404
+ a substring otherwise.
405
+
406
+ ## `list`, `grep`, `show` — no embedder, no credential
407
+
408
+ ```
409
+ zen rag docs list <files|sections|tables> [-f <pattern>] [-s <section>]
410
+ zen rag docs grep <pattern> [-f <pattern>] [--regex] [--case-sensitive]
411
+ zen rag docs show <file> [--section <name>] [--lines <from-to>]
412
+ ```
413
+
414
+ `list sections` gives every heading with the lines it spans, which is how a
415
+ section is named before it is searched. `grep` reports `found` as the true
416
+ total even when `--limit` cuts the rows, so unlike a search it can answer
417
+ whether a string appears at all. `show` prints a document, a named section, or
418
+ a line range, verbatim.
419
+
420
+ ## Giving it to an agent
421
+
422
+ `@zenera/rag/docs/tools` exports four tools in the group `docs`:
423
+
424
+ | Tool | For |
425
+ | ------------- | --------------------------------------------------------------- |
426
+ | `search_docs` | The search above, with the same narrowing parameters |
427
+ | `list_docs` | The documents, their headings, or their tables — no ranking |
428
+ | `grep_docs` | Every matching line, counted in full — the way to prove absence |
429
+ | `read_docs` | A section or a line range, verbatim and complete |
430
+
431
+ Only `search_docs` ranks. Every answer carries line numbers and `read_docs`
432
+ takes them, which is the loop the subject exists for: find the passage, read
433
+ around it, then edit the file it came from.