@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.
- package/README.md +40 -3
- package/dist/archive.d.ts +139 -0
- package/dist/archive.js +376 -0
- package/dist/banner.d.ts +33 -24
- package/dist/banner.js +25 -6
- package/dist/commands/check.js +1 -0
- package/dist/commands/export.d.ts +3 -0
- package/dist/commands/export.js +255 -0
- package/dist/commands/import.d.ts +3 -0
- package/dist/commands/import.js +173 -0
- package/dist/commands/index.d.ts +5 -1
- package/dist/commands/index.js +13 -1
- package/dist/commands/init.js +1 -0
- package/dist/commands/inspect.js +1 -0
- package/dist/commands/key.js +1 -0
- package/dist/commands/list.js +1 -0
- package/dist/commands/memory.js +118 -10
- package/dist/commands/open.js +1 -0
- package/dist/commands/run.js +3 -0
- package/dist/commands/sandbox.js +1 -0
- package/dist/commands/version.js +1 -0
- package/dist/lib.d.ts +2 -1
- package/dist/lib.js +2 -1
- package/dist/meta.d.ts +1 -1
- package/dist/meta.js +5 -28
- package/dist/resolve.js +19 -12
- package/dist/sandbox.js +1 -0
- package/dist/scaffold.d.ts +8 -0
- package/dist/scaffold.js +7 -2
- package/dist/term.d.ts +2 -0
- package/dist/term.js +2 -0
- package/dist/tui/markdown.d.ts +16 -0
- package/dist/tui/markdown.js +259 -0
- package/dist/tui/theme.js +1 -1
- package/dist/tui/wrap.d.ts +1 -1
- package/dist/validate.js +150 -4
- package/package.json +12 -6
- package/templates/editor/.github/copilot-instructions.md +62 -33
- package/templates/editor/.github/prompts/spec-sync-project.prompt.md +56 -3
- package/templates/editor/.github/skills/zen-cli/SKILL.md +21 -16
- package/templates/editor/.github/skills/zen-cli/references/check.md +6 -0
- package/templates/editor/.github/skills/zen-cli/references/export.md +107 -0
- package/templates/editor/.github/skills/zen-cli/references/memory.md +51 -13
- package/templates/editor/.github/skills/zen-cli/references/projects.md +1 -0
- package/templates/editor/.github/skills/zen-cli/references/rag.md +43 -3
- package/templates/editor/.github/skills/zen-cli/references/sandbox.md +30 -2
- package/templates/editor/.github/skills/zen-instructions/SKILL.md +232 -0
- package/templates/editor/.github/skills/zen-memory/SKILL.md +2 -1
- package/templates/editor/.github/skills/zen-memory-warmup/SKILL.md +684 -0
- package/templates/editor/.github/skills/zen-rag-docs/SKILL.md +56 -23
- package/templates/editor/.github/skills/zen-rag-schema/SKILL.md +55 -28
- package/templates/editor/.github/skills/zen-review/SKILL.md +17 -1
- package/templates/editor/.github/skills/zen-sandbox/SKILL.md +257 -0
- package/templates/editor/.github/skills/zen-spec-sync/SKILL.md +16 -3
- package/templates/editor/.vscode/agents.schema.json +8 -3
- package/templates/project/SPECIFICATION.md.tmpl +4 -1
- package/templates/project/agents/files-instructions.md +86 -0
- package/templates/project/agents/fork-instructions.md +17 -0
- package/templates/project/agents/memory-instructions.md +37 -0
- package/templates/project/agents.yaml.tmpl +3 -3
- package/templates/project/gitignore +12 -1
- 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
|
|
48
|
-
# them one by one to be narrower, or subtract: [
|
|
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
|
-
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
#
|
|
49
|
-
#
|
|
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
|
|
56
|
-
# mv .tmp/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
|
|
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
|
-
|
|
149
|
+
if [ "$CHECK" = 1 ]; then
|
|
150
|
+
echo "setup check:"
|
|
151
|
+
else
|
|
152
|
+
echo "setup:"
|
|
153
|
+
fi
|
|
100
154
|
printf '%s' "$summary"
|
|
101
|
-
|
|
155
|
+
if [ "$failed" = 1 ] || [ "$pending" = 1 ]; then
|
|
156
|
+
exit 1
|
|
157
|
+
fi
|
|
158
|
+
exit 0
|