@zenera/cli 1.1.21 → 1.1.23

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 (62) hide show
  1. package/README.md +40 -3
  2. package/dist/archive.d.ts +139 -0
  3. package/dist/archive.js +376 -0
  4. package/dist/banner.d.ts +33 -24
  5. package/dist/banner.js +25 -6
  6. package/dist/commands/check.js +1 -0
  7. package/dist/commands/export.d.ts +3 -0
  8. package/dist/commands/export.js +255 -0
  9. package/dist/commands/import.d.ts +3 -0
  10. package/dist/commands/import.js +173 -0
  11. package/dist/commands/index.d.ts +5 -1
  12. package/dist/commands/index.js +13 -1
  13. package/dist/commands/init.js +1 -0
  14. package/dist/commands/inspect.js +1 -0
  15. package/dist/commands/key.js +1 -0
  16. package/dist/commands/list.js +1 -0
  17. package/dist/commands/memory.js +118 -10
  18. package/dist/commands/open.js +1 -0
  19. package/dist/commands/run.js +3 -0
  20. package/dist/commands/sandbox.js +1 -0
  21. package/dist/commands/version.js +1 -0
  22. package/dist/lib.d.ts +2 -1
  23. package/dist/lib.js +2 -1
  24. package/dist/meta.d.ts +1 -1
  25. package/dist/meta.js +5 -28
  26. package/dist/resolve.js +19 -12
  27. package/dist/sandbox.js +1 -0
  28. package/dist/scaffold.d.ts +8 -0
  29. package/dist/scaffold.js +7 -2
  30. package/dist/term.d.ts +2 -0
  31. package/dist/term.js +2 -0
  32. package/dist/tui/markdown.d.ts +16 -0
  33. package/dist/tui/markdown.js +259 -0
  34. package/dist/tui/theme.js +1 -1
  35. package/dist/tui/wrap.d.ts +1 -1
  36. package/dist/validate.js +150 -4
  37. package/package.json +12 -6
  38. package/templates/editor/.github/copilot-instructions.md +62 -33
  39. package/templates/editor/.github/prompts/spec-sync-project.prompt.md +56 -3
  40. package/templates/editor/.github/skills/zen-cli/SKILL.md +21 -16
  41. package/templates/editor/.github/skills/zen-cli/references/check.md +6 -0
  42. package/templates/editor/.github/skills/zen-cli/references/export.md +107 -0
  43. package/templates/editor/.github/skills/zen-cli/references/memory.md +51 -13
  44. package/templates/editor/.github/skills/zen-cli/references/projects.md +1 -0
  45. package/templates/editor/.github/skills/zen-cli/references/rag.md +43 -3
  46. package/templates/editor/.github/skills/zen-cli/references/sandbox.md +30 -2
  47. package/templates/editor/.github/skills/zen-instructions/SKILL.md +232 -0
  48. package/templates/editor/.github/skills/zen-memory/SKILL.md +2 -1
  49. package/templates/editor/.github/skills/zen-memory-warmup/SKILL.md +684 -0
  50. package/templates/editor/.github/skills/zen-rag-docs/SKILL.md +56 -23
  51. package/templates/editor/.github/skills/zen-rag-schema/SKILL.md +55 -28
  52. package/templates/editor/.github/skills/zen-review/SKILL.md +17 -1
  53. package/templates/editor/.github/skills/zen-sandbox/SKILL.md +257 -0
  54. package/templates/editor/.github/skills/zen-spec-sync/SKILL.md +16 -3
  55. package/templates/editor/.vscode/agents.schema.json +8 -3
  56. package/templates/project/SPECIFICATION.md.tmpl +4 -1
  57. package/templates/project/agents/files-instructions.md +86 -0
  58. package/templates/project/agents/fork-instructions.md +17 -0
  59. package/templates/project/agents/memory-instructions.md +37 -0
  60. package/templates/project/agents.yaml.tmpl +3 -3
  61. package/templates/project/gitignore +12 -1
  62. package/templates/project/scripts/_setup.sh +68 -11
@@ -0,0 +1,86 @@
1
+ ---
2
+ requires: [files]
3
+ ---
4
+
5
+ # Working with files
6
+
7
+ These rules govern how files are discovered, inspected, and modified. If file tools
8
+ are not among your tools, you cannot read or change files directly.
9
+
10
+ ## Access modes
11
+
12
+ Check which tools you actually have:
13
+
14
+ - If `write_file` or `apply_patch` is not among your tools, your access is **read-only**.
15
+ Inspect files, search directories, and report conclusions, but attempt no edits.
16
+ - If `write_file` and `apply_patch` are available, you may create and edit files
17
+ under `/workspace`.
18
+
19
+ ## Discovery before assumption
20
+
21
+ Never guess a file's name, location, or contents.
22
+
23
+ - Use `list_dir` to see directory contents and formats before opening files.
24
+ - Use `find_files` to locate files by substring when the layout is unfamiliar.
25
+ - Check whether a target file already exists before writing to it.
26
+
27
+ ## Reading files
28
+
29
+ - Use `read_file` to read text files.
30
+ - For files longer than a few dozen lines, pass `start_line` and `end_line` (1-based, inclusive)
31
+ to read only the relevant section.
32
+ - When `read_file` returns `truncated: true`, the read hit the size limit or range boundary.
33
+ Resume reading from `end_line + 1` if you need the remainder.
34
+ - Non-text files (images, binaries, archives) cannot be read as text; `list_dir` reports
35
+ their format.
36
+
37
+ ## Modifying files
38
+
39
+ ### Modifying existing files: `apply_patch`
40
+
41
+ Always use `apply_patch` to edit existing files. It makes surgical, verifiable changes
42
+ and validates the entire patch before writing any file to disk.
43
+
44
+ 1. **Read before patching**: Read the target file first to obtain exact context lines.
45
+ An outdated or imagined context line fails the patch.
46
+ 2. **Provide context**: Include at least 3 unchanged context lines (prefixed with a space)
47
+ before and after each change.
48
+ 3. **No line numbers**: Patches match on context text, never on line numbers.
49
+ 4. **Always close the patch**: Every patch must begin with `*** Begin Patch` and end
50
+ with `*** End Patch`. Omitting `*** End Patch` is an error.
51
+
52
+ Example patch:
53
+
54
+ ```
55
+ *** Begin Patch
56
+ *** Update File: /workspace/src/config.ts
57
+ @@ port configuration
58
+ export interface Config {
59
+ host: string;
60
+ - port: 80;
61
+ + port: 8080;
62
+ timeoutMs: number;
63
+ }
64
+ *** End Patch
65
+ ```
66
+
67
+ ### Creating new files: `write_file`
68
+
69
+ Use `write_file` only to create a **new** file or to overwrite a small file completely.
70
+ Never use `write_file` to update an existing file when only a few lines need to change.
71
+
72
+ ### Moving and deleting
73
+
74
+ - Use `move_file` to rename or relocate a file or directory. It creates parent directories
75
+ as needed. Set `overwrite: true` only when intentionally replacing an existing destination.
76
+ - Use `delete_file` to remove a file. Removing a directory requires `recursive: true`.
77
+
78
+ ## Mounts and containment
79
+
80
+ All file operations are confined to mounted trees:
81
+
82
+ - `/workspace`: The primary writable directory for the project. Paths inside the workspace
83
+ (such as `/workspace/src/main.ts`) are where project files reside.
84
+ - `/assets`, `/skills`, `/memory`: Read-only mounts. You may read, list, and search them,
85
+ but you cannot write, move, or delete files inside them.
86
+ - Any attempt to reach outside these mounts fails with an containment error.
@@ -28,6 +28,23 @@ exploration down a path that may go nowhere. **Several branches are a fan-out**:
28
28
  independent parts of one task, worked at the same time, merged by you. It is the
29
29
  same call either way; the number of branches is the only difference.
30
30
 
31
+ Every `fork` call takes an array under `branches`, even for a single branch:
32
+
33
+ ```json
34
+ {
35
+ "branches": [
36
+ {
37
+ "name": "audit-auth",
38
+ "agent": "security",
39
+ "instructions": "Audit /workspace/src/auth/** for bypasses. Return the count and worst finding."
40
+ }
41
+ ]
42
+ }
43
+ ```
44
+
45
+ Never pass branch fields (`name`, `instructions`, `agent`) at the top level of
46
+ the tool call.
47
+
31
48
  Do not fork a sequence. Branches run at once and can exchange nothing, so a step
32
49
  that needs the step before it has to stay in this conversation.
33
50
 
@@ -248,6 +248,23 @@ for it, or a fact with nothing that acts on it, is a memory nobody can use. Refs
248
248
  resolve only within a single `memory_commit`, so a subgraph split across calls
249
249
  arrives without its links.
250
250
 
251
+ **Use `ref` (not `id`) for new nodes.** A new node uses `ref` as its local name
252
+ (for example, `"ask"`, `"script"`), and edges connect them using those refs:
253
+
254
+ ```json
255
+ {
256
+ "nodes": [
257
+ { "ref": "ask", "kind": "task", "text": "audit firewall rules for risky ports" },
258
+ { "ref": "script", "kind": "file", "text": "risk report generator", "file": "report.py" }
259
+ ],
260
+ "edges": [{ "from": "ask", "to": "script", "relation": "PRODUCED" }]
261
+ }
262
+ ```
263
+
264
+ Use `id` only when updating an existing node that is already in memory from a
265
+ previous search or load. Never pass `id` when creating a new node, and do not
266
+ pass both `ref` and `id` on the same node.
267
+
251
268
  **Do not re-commit what a search already returned.** A node that says what one
252
269
  already in memory says is folded into it, and its existing id comes back under
253
270
  your ref - so the links you asked for still land, on the memory that was already
@@ -285,6 +302,26 @@ costs nothing until a `memory_load` asks for it, and comes back at
285
302
  `/memory/<id>.<ext>` to be read or run. Commit a node with no file only when the
286
303
  whole of what you know is one line long.
287
304
 
305
+ **The file must exist in the workspace first.** `memory_commit` copies an
306
+ existing file from the workspace; it is not an upload channel and does not
307
+ write file contents from raw arguments. Write the file to the workspace first
308
+ (using `write_file`, `apply_patch`, or a command saving under `/workspace`),
309
+ then pass its workspace path (e.g. `"file": "report.py"` or
310
+ `"file": "/workspace/report.py"`).
311
+
312
+ | Which files to commit | What belongs in them |
313
+ | ---------------------- | -------------------------------------------------------------------------- |
314
+ | Working scripts | A script, query or invocation that can be re-run directly |
315
+ | Configurations & specs | Self-contained config files, schemas or request templates |
316
+ | Rendered findings | A table of findings or structured report produced by an investigation |
317
+ | Pinned reference text | Verbatim passages from released specs or versioned docs that cannot change |
318
+ | Assembled answers | Synthesised conclusions from multiple sources with a provenance header |
319
+ | Specimen responses | An API response shape to reproduce against (never raw secrets) |
320
+
321
+ Do not commit files from the living codebase (use a pointer with file and line
322
+ ranges instead - copies go stale silently), raw ephemeral command logs, or
323
+ anything outside the workspace.
324
+
288
325
  **Name the sources inside the file as well as in the text.** The two halves
289
326
  arrive separately - a recollection shows the text, and only a later
290
327
  `memory_load` opens the file - so a file read on its own is an assertion with
@@ -44,14 +44,14 @@ agents:
44
44
  # store at all.
45
45
  memory: true
46
46
  #
47
- # workspace:* is every file tool at once, sandbox:* is the shell. Name
48
- # them one by one to be narrower, or subtract: [workspace:*, -delete_file]
47
+ # files:* (alias: workspace:*) is every file tool at once, sandbox:* is
48
+ # the shell. Name them one by one to be narrower, or subtract: [files:*, -delete_file]
49
49
  #
50
50
  # sandbox:* runs commands in a container, not on this machine, so it
51
51
  # needs podman — `zen run` installs and starts what it can on its own,
52
52
  # and `zen sandbox status` says where that got to. Drop the line if you
53
53
  # would rather this agent never reached a shell.
54
54
  tools:
55
- - workspace:*
55
+ - files:*
56
56
  - sandbox:*
57
57
  {{exa}}
@@ -12,4 +12,15 @@ memory/.lock
12
12
  .tmp/
13
13
 
14
14
  # Credentials.
15
- .env
15
+ .env
16
+
17
+ # A rag index commits everything except its vectors: they are binary, they are
18
+ # large, and `zen rag <subject> restore` rebuilds them from the copies of the
19
+ # documents the index already carries — which is why this is safe to ignore and
20
+ # `memory/` above is not. A clone therefore holds an index that looks built and
21
+ # cannot search until a setup step restores it. `zen rag <subject> ready` is the
22
+ # test for that; `[ -f manifest.json ]` is not, because the manifest is here.
23
+ assets/**/lance/
24
+
25
+ .DS_Store
26
+ **/.DS_Store
@@ -4,6 +4,7 @@
4
4
  #
5
5
  # scripts/_setup.sh do whatever is not done yet
6
6
  # scripts/_setup.sh --force do all of it again
7
+ # scripts/_setup.sh --check say what is not done, and do none of it
7
8
  #
8
9
  # Anything that has to be in place before a run — an index built, a document
9
10
  # fetched, a file generated — is a script in this directory rather than a
@@ -17,9 +18,25 @@
17
18
  # - takes no arguments, and reads $FORCE to know whether to redo finished work
18
19
  # - exits 0 when it did the work, 3 when there was nothing to do, non-zero
19
20
  # when it failed
21
+ # - under $CHECK, does none of the work: it runs the same "already done" test,
22
+ # exits 3 when the answer is yes, and otherwise says what is missing and
23
+ # exits 4. A check must not assume an earlier step has run — a missing
24
+ # prerequisite is a 4 of its own, not a hard failure, or one unbuilt thing
25
+ # hides the rest of the list
20
26
  # - writes under .tmp/ and moves the result into place, so an interrupted run
21
27
  # never leaves half an artefact behind
22
28
  #
29
+ # A step decides it has nothing to do by testing for something that SURVIVES A
30
+ # CLONE. Files that are git-ignored do not: a vector index commits its manifest
31
+ # and ignores `lance/`, so `[ -f .../manifest.json ]` is true on a fresh
32
+ # checkout that cannot search at all, and every step reports `skipped` until the
33
+ # first search fails for a reason nobody connects to setup. Ask the tool instead
34
+ # of guessing at files — `zen rag docs ready` answers exactly that question.
35
+ #
36
+ # That test is the whole of `--check`, which is why this is one script and not
37
+ # two: the steps already know what "done" means, and a second script asking the
38
+ # same question would be a second answer to keep in step with this one.
39
+ #
23
40
  # Running this twice has to be safe, and the second run is what proves it: every
24
41
  # step should report `skipped`.
25
42
 
@@ -27,10 +44,17 @@ set -eu
27
44
  cd "$(dirname "$0")/.."
28
45
 
29
46
  FORCE=0
30
- if [ "${1:-}" = "--force" ]; then
31
- FORCE=1
32
- fi
33
- export FORCE
47
+ CHECK=0
48
+ case "${1:-}" in
49
+ '') ;;
50
+ --force) FORCE=1 ;;
51
+ --check) CHECK=1 ;;
52
+ *)
53
+ echo "usage: scripts/_setup.sh [--force|--check]" >&2
54
+ exit 2
55
+ ;;
56
+ esac
57
+ export FORCE CHECK
34
58
 
35
59
  LOGS=.tmp/logs
36
60
 
@@ -45,15 +69,29 @@ LOGS=.tmp/logs
45
69
  #
46
70
  # set -eu
47
71
  # cd "$(dirname "$0")/.."
48
- # if [ "${FORCE:-0}" = 0 ] && [ -f assets/docs-db/manifest.json ]; then
49
- # echo "assets/docs-db is already built"
72
+ # OUT=assets/docs-db
73
+ #
74
+ # if [ "${FORCE:-0}" = 0 ] && zen rag docs ready --dir "$OUT" --quiet; then
75
+ # echo "$OUT is already built"
50
76
  # exit 3
51
77
  # fi
78
+ # if [ "${CHECK:-0}" = 1 ]; then
79
+ # # Without --quiet it names what is missing and the command that fixes
80
+ # # it; `|| true` because not-ready is the exit code we came for.
81
+ # zen rag docs ready --dir "$OUT" || true
82
+ # exit 4
83
+ # fi
84
+ # # Committed index, git-ignored vectors: re-embed from the copies the index
85
+ # # already holds rather than indexing the documents over again.
86
+ # if [ "${FORCE:-0}" = 0 ] && [ -f "$OUT/manifest.json" ]; then
87
+ # zen rag docs restore --dir "$OUT"
88
+ # exit 0
89
+ # fi
52
90
  # rm -rf .tmp/docs-db
53
91
  # zen rag docs index assets/docs \
54
92
  # --embedding openai:text-embedding-3-small --out .tmp/docs-db
55
- # rm -rf assets/docs-db
56
- # mv .tmp/docs-db assets/docs-db
93
+ # rm -rf "$OUT"
94
+ # mv .tmp/docs-db "$OUT"
57
95
  #
58
96
  STEPS=""
59
97
 
@@ -65,9 +103,16 @@ fi
65
103
  mkdir -p "$LOGS"
66
104
  summary=""
67
105
  failed=0
106
+ pending=0
68
107
 
69
108
  for name in $STEPS; do
70
- log="$LOGS/setup-$name.log"
109
+ # A dry run keeps its own log: overwriting the build's would lose the
110
+ # record of the build to a question about it.
111
+ if [ "$CHECK" = 1 ]; then
112
+ log="$LOGS/check-$name.log"
113
+ else
114
+ log="$LOGS/setup-$name.log"
115
+ fi
71
116
  echo
72
117
  echo "-- $name $(date '+%H:%M:%S') ($log)"
73
118
 
@@ -81,6 +126,10 @@ for name in $STEPS; do
81
126
  case "$code" in
82
127
  0) word=ok ;;
83
128
  3) word=skipped ;;
129
+ 4)
130
+ word="needs setup"
131
+ pending=1
132
+ ;;
84
133
  *)
85
134
  word="failed ($code)"
86
135
  failed=1
@@ -90,12 +139,20 @@ for name in $STEPS; do
90
139
  "
91
140
  # Later steps depend on earlier ones, so a failure stops rather than
92
141
  # producing a second failure that is only a consequence of the first.
142
+ # `needs setup` does not stop it: the point of asking is the whole list.
93
143
  if [ "$failed" = 1 ]; then
94
144
  break
95
145
  fi
96
146
  done
97
147
 
98
148
  echo
99
- echo "setup:"
149
+ if [ "$CHECK" = 1 ]; then
150
+ echo "setup check:"
151
+ else
152
+ echo "setup:"
153
+ fi
100
154
  printf '%s' "$summary"
101
- exit "$failed"
155
+ if [ "$failed" = 1 ] || [ "$pending" = 1 ]; then
156
+ exit 1
157
+ fi
158
+ exit 0