@zenera/cli 1.1.16 → 1.1.17
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 +20 -12
- package/dist/catalog.js +19 -20
- package/dist/commands/check.js +5 -1
- package/dist/commands/init.js +41 -6
- package/dist/commands/run.js +4 -0
- package/dist/engine.js +6 -0
- package/dist/env.d.ts +20 -0
- package/dist/env.js +65 -0
- package/dist/keys.d.ts +2 -0
- package/dist/keys.js +2 -0
- package/dist/sandbox.d.ts +9 -0
- package/dist/sandbox.js +23 -3
- package/dist/scaffold.d.ts +6 -0
- package/dist/scaffold.js +56 -15
- package/dist/validate.js +57 -15
- package/package.json +2 -2
- package/templates/editor/.github/copilot-instructions.md +256 -91
- package/templates/editor/.github/prompts/review-project.prompt.md +53 -14
- package/templates/editor/.github/prompts/sync-with-spec.prompt.md +208 -21
- package/templates/editor/.github/prompts/update-spec-from-feedback.prompt.md +142 -0
- package/templates/editor/.github/skills/zen-cli/references/check.md +6 -3
- package/templates/editor/.github/skills/zen-cli/references/frame.md +5 -3
- package/templates/editor/.github/skills/zen-cli/references/projects.md +19 -2
- package/templates/editor/.github/skills/zen-cli/references/sandbox.md +6 -0
- package/templates/editor/.github/skills/zen-memory/SKILL.md +102 -30
- package/templates/editor/.github/skills/zen-memory/scripts/check-instructions.sh +115 -0
- package/templates/editor/.github/skills/zen-review/SKILL.md +123 -0
- package/templates/editor/.github/skills/zen-review/scripts/check-paths.sh +119 -0
- package/templates/editor/.github/skills/zen-review/scripts/review.sh +104 -0
- package/templates/editor/.github/skills/zen-spec-sync/SKILL.md +197 -0
- package/templates/editor/.github/skills/zen-spec-sync/scripts/snapshot.sh +200 -0
- package/templates/editor/.vscode/settings.json +44 -4
- package/templates/parts/memory-terms.yaml.tmpl +16 -0
- package/templates/parts/memory.yaml.tmpl +12 -0
- package/templates/project/SPECIFICATION.md.tmpl +7 -0
- package/templates/project/agents/memory-instructions.md +278 -0
- package/templates/project/agents.yaml.tmpl +9 -0
- package/templates/project/env +22 -0
- /package/templates/project/{INSTRUCTIONS.md → agents/instructions.md} +0 -0
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
>
|
|
8
8
|
> It describes the Zenera Neo runtime, not this particular project, and `zen`
|
|
9
9
|
> rewrites the whole tree on `init` and `open` - so put this project's own
|
|
10
|
-
> conventions in `
|
|
11
|
-
> reference is `docs/agents-yaml.md`, `docs/projects.md` and
|
|
12
|
-
> @zenera/neo repository - where they disagree with this
|
|
10
|
+
> conventions in `agents/instructions.md`, where they will survive. The
|
|
11
|
+
> runtime's own reference is `docs/agents-yaml.md`, `docs/projects.md` and
|
|
12
|
+
> `DESIGN.md` in the @zenera/neo repository - where they disagree with this
|
|
13
|
+
> file, they win.
|
|
13
14
|
|
|
14
15
|
---
|
|
15
16
|
|
|
@@ -34,13 +35,23 @@ programmed: what an agent knows, which model answers, and which of the tools
|
|
|
34
35
|
6. Every change must still load: `agents.yaml` is validated strictly at load,
|
|
35
36
|
and `zen check` says so before a model is ever called.
|
|
36
37
|
|
|
37
|
-
### 0.1 Copilot is the meta-agent:
|
|
38
|
+
### 0.1 Copilot is the meta-agent: load the skill for every capability in use
|
|
38
39
|
|
|
39
40
|
Copilot is always the meta-agent that creates and changes target projects. Load
|
|
40
41
|
the editor's `zen-cli` skill before deciding how a target project should run,
|
|
41
42
|
be validated, or use command-line capabilities. It is the command contract; do
|
|
42
43
|
not reconstruct `zen` arguments from memory or call `--help` to discover them.
|
|
43
44
|
|
|
45
|
+
**Every runtime capability a project turns on carries obligations that are not
|
|
46
|
+
visible in `agents.yaml` and that `zen check` does not report.** Before
|
|
47
|
+
reviewing or changing a project, list the capabilities it has turned on and load
|
|
48
|
+
the editor skill for each one - `zen-memory` for a `memory:` block, `zen-rag-
|
|
49
|
+
schema` or `zen-rag-docs` for an index, `zen-cli` always. A capability that is
|
|
50
|
+
already configured and already passing `zen check` is exactly the case that
|
|
51
|
+
looks finished and is not: the obligation lives in the skill, so a review that
|
|
52
|
+
never opens the skill cannot find what is missing. This applies whatever
|
|
53
|
+
prompted the change - a task scoped to `SPECIFICATION.md` does not narrow it.
|
|
54
|
+
|
|
44
55
|
First determine whether the target project uses RAG: a `zen rag` command in an
|
|
45
56
|
agent prompt or skill, RAG tools supplied by its host, or a documentation or
|
|
46
57
|
schema index it is expected to consult all count. When it does, also load the
|
|
@@ -68,6 +79,42 @@ target project. Grant the agents that need CLI RAG the necessary `sandbox:*`
|
|
|
68
79
|
tool access; give tool-based RAG users the configured RAG tools instead. Run
|
|
69
80
|
`zen check` after adding or changing the skill.
|
|
70
81
|
|
|
82
|
+
Memory has one such obligation and it is absolute: **a project with a `memory:`
|
|
83
|
+
block carries the `zen-memory` skill's `references/memory-instructions.md` in its
|
|
84
|
+
own `agents/memory-instructions.md`.** `zen init` writes both, since it scaffolds
|
|
85
|
+
memory on; what needs watching is a project that deleted the file, or one whose
|
|
86
|
+
copy has fallen behind the reference. Do not read the two files against each
|
|
87
|
+
other - they drift by trailing whitespace inside tables, which is invisible.
|
|
88
|
+
The skill ships the check:
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
.github/skills/zen-memory/scripts/check-instructions.sh # the verdict
|
|
92
|
+
.github/skills/zen-memory/scripts/check-instructions.sh fix # copy the reference over
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
It is a copy, never a transcription - the reference ships inside the project,
|
|
96
|
+
because `zen init` and `zen open` write this whole `.github/` tree, so `fix` is
|
|
97
|
+
just `cp` from one to the other.
|
|
98
|
+
|
|
99
|
+
Nothing else tells a running agent how the store works, so without it nothing
|
|
100
|
+
forbids an agent from pointing `grep` or `cat` at `/memory` - a read that
|
|
101
|
+
bypasses the audience mask and serves superseded nodes as current. Keep the copy
|
|
102
|
+
byte-identical and put this project's own memory policy in a second topic file,
|
|
103
|
+
`agents/memory-policy-instructions.md`, which is read straight after it: then the
|
|
104
|
+
copy can be re-run after any `zen init` or `zen open` refreshes the reference,
|
|
105
|
+
without losing anything. Never paraphrase the reference into prose of your own.
|
|
106
|
+
See §5.3.
|
|
107
|
+
|
|
108
|
+
A project with a `SPECIFICATION.md` carries one more: **`.spec-sync/` records
|
|
109
|
+
what the last `/sync-with-spec` pass applied**, and the `zen-spec-sync` skill is
|
|
110
|
+
loaded before running that prompt, whether or not a baseline exists yet. The
|
|
111
|
+
state is committed, because a record only the last machine has is not a record.
|
|
112
|
+
Two things to watch for, neither of which `zen check` reports: a baseline that
|
|
113
|
+
moved without a history entry to match it, which is a pass claiming work it did
|
|
114
|
+
not do, and a `.spec-sync/baseline/` whose `manifest.txt` no longer matches its
|
|
115
|
+
files. Both are reported, not quietly repaired - rewriting the manifest asserts
|
|
116
|
+
a pass that never happened.
|
|
117
|
+
|
|
71
118
|
---
|
|
72
119
|
|
|
73
120
|
## 1. Mental model
|
|
@@ -76,12 +123,12 @@ tool access; give tool-based RAG users the configured RAG tools instead. Run
|
|
|
76
123
|
|
|
77
124
|
An agent is four things and nothing more:
|
|
78
125
|
|
|
79
|
-
| Part | Where it lives
|
|
80
|
-
| --------------- |
|
|
81
|
-
| **Instruction** | `
|
|
82
|
-
| **Model** | `agents.yaml` → `model:`
|
|
83
|
-
| **Tools** | `agents.yaml` → `tools:`
|
|
84
|
-
| **Knowledge** | `agents/skills/*` + memory
|
|
126
|
+
| Part | Where it lives | What it decides |
|
|
127
|
+
| --------------- | ------------------------------------------------------ | ----------------------------- |
|
|
128
|
+
| **Instruction** | `agents/*instructions.md` + `agents/prompts/<name>.md` | How it behaves |
|
|
129
|
+
| **Model** | `agents.yaml` → `model:` | How well and how expensively |
|
|
130
|
+
| **Tools** | `agents.yaml` → `tools:` | What it can _do_ |
|
|
131
|
+
| **Knowledge** | `agents/skills/*` + memory | What it can _know_, on demand |
|
|
85
132
|
|
|
86
133
|
Plus two relations: **handoffs** - which other agents it may transfer control to
|
|
87
134
|
|
|
@@ -116,7 +163,7 @@ is deciding **what is in that sequence and in what order**.
|
|
|
116
163
|
```
|
|
117
164
|
┌─────────────────────────────────────────────┐
|
|
118
165
|
│ tool schemas fixed at load │ ← stable, cacheable
|
|
119
|
-
│
|
|
166
|
+
│ agents/*instructions shared by all agents │ ← stable, cacheable
|
|
120
167
|
│ agent prompt this agent's brief │ ← stable per agent
|
|
121
168
|
│ skill index names + descriptions │ ← stable per agent
|
|
122
169
|
│ preloaded skills activated turn 0 │ ← stable, in the cached prefix
|
|
@@ -159,10 +206,12 @@ my-project/
|
|
|
159
206
|
│ ├── copilot-instructions.md this file
|
|
160
207
|
│ ├── prompts/*.prompt.md tasks you invoke by name
|
|
161
208
|
│ └── skills/*/SKILL.md reference the editor loads on demand
|
|
162
|
-
├── .env
|
|
163
|
-
├──
|
|
209
|
+
├── .env this project's environment - NEVER committed
|
|
210
|
+
├── .spec-sync/ what the last /sync-with-spec applied - §0.1
|
|
164
211
|
├── agents.yaml who exists, what they may reach for
|
|
165
212
|
├── agents/
|
|
213
|
+
│ ├── instructions.md house rules, prepended to every agent
|
|
214
|
+
│ ├── memory-instructions.md more of them - any `<topic>-instructions.md`
|
|
166
215
|
│ ├── prompts/
|
|
167
216
|
│ │ ├── intake.md one agent's own brief
|
|
168
217
|
│ │ └── adjuster.md
|
|
@@ -185,13 +234,18 @@ Only `agents.yaml` is required, and only `agents:` is required inside it.
|
|
|
185
234
|
The config is found by name, in order: `agents.yaml`, `agents.yml`,
|
|
186
235
|
`agents/agents.yaml`, `agents/agents.yml`.
|
|
187
236
|
|
|
237
|
+
The house rules are `agents/instructions.md` plus every
|
|
238
|
+
`agents/<topic>-instructions.md`, read in filename order and prepended to every
|
|
239
|
+
agent (§3.2). A project written before the move keeps its `INSTRUCTIONS.md` in
|
|
240
|
+
the root; that still loads, and `zen check` says to move it.
|
|
241
|
+
|
|
188
242
|
### 2.2 Variants
|
|
189
243
|
|
|
190
244
|
**Single agent, knowledge-heavy** - the most under-used shape. One agent, one
|
|
191
245
|
prompt, a large skill catalog. Prefer this until routing is genuinely needed.
|
|
192
246
|
|
|
193
247
|
```
|
|
194
|
-
|
|
248
|
+
agents.yaml · agents/instructions.md · agents/prompts/assistant.md · agents/skills/** (20 skills)
|
|
195
249
|
```
|
|
196
250
|
|
|
197
251
|
**Router + specialists** - a cheap intake agent that classifies and hands off.
|
|
@@ -236,10 +290,10 @@ dots.
|
|
|
236
290
|
There are two sets of instructions in this repository and they are not for the
|
|
237
291
|
same reader. Keeping them apart is the single easiest thing to get wrong.
|
|
238
292
|
|
|
239
|
-
| Tree
|
|
240
|
-
|
|
|
241
|
-
| `
|
|
242
|
-
| `.github/`
|
|
293
|
+
| Tree | Read by | About |
|
|
294
|
+
| ------------------------ | ------------------------------------------ | ----------------------------------- |
|
|
295
|
+
| `agents.yaml`, `agents/` | the **project's** agents, at run time | the domain this system works in |
|
|
296
|
+
| `.github/` | the **editor's** assistant, while you edit | how a project of this kind is built |
|
|
243
297
|
|
|
244
298
|
The `.github/` tree follows the same progressive-disclosure discipline the
|
|
245
299
|
agents do, for the same reason - it is a prefix somebody pays for:
|
|
@@ -258,7 +312,8 @@ agents do, for the same reason - it is a prefix somebody pays for:
|
|
|
258
312
|
|
|
259
313
|
`zen init` and `zen open` rewrite this whole tree from the version of `zen` in
|
|
260
314
|
hand, so **edits inside `.github/` do not survive**. Project-specific conventions
|
|
261
|
-
belong in `
|
|
315
|
+
belong in `agents/instructions.md` and the agent prompts, which are never
|
|
316
|
+
overwritten.
|
|
262
317
|
|
|
263
318
|
### 2.5 What a running agent can actually see
|
|
264
319
|
|
|
@@ -276,10 +331,10 @@ Commands run inside the container `sandbox:` describes (§3.7): the same
|
|
|
276
331
|
`/workspace`, and whatever the image ships.
|
|
277
332
|
|
|
278
333
|
Everything else in the project directory is **invisible at run time** -
|
|
279
|
-
`agents.yaml`, `
|
|
280
|
-
name, `sandbox/Dockerfile`, `.env`, `.github/`, `sessions/`, and the
|
|
281
|
-
root itself. `zen` reads them to build the run; they are never a path an
|
|
282
|
-
can open.
|
|
334
|
+
`agents.yaml`, `agents/instructions.md`, `agents/prompts/`, `agents/skills/`
|
|
335
|
+
under that name, `sandbox/Dockerfile`, `.env`, `.github/`, `sessions/`, and the
|
|
336
|
+
project root itself. `zen` reads them to build the run; they are never a path an
|
|
337
|
+
agent can open.
|
|
283
338
|
|
|
284
339
|
Two consequences:
|
|
285
340
|
|
|
@@ -298,13 +353,13 @@ prose**, in the prompt - never sent to read the file that configured it.
|
|
|
298
353
|
|
|
299
354
|
#### Checklist - no path an agent cannot open
|
|
300
355
|
|
|
301
|
-
Run this over `
|
|
302
|
-
`agents/skills/*/SKILL.md` after editing any of them. Every path-shaped
|
|
303
|
-
those files is read by a model as an instruction to open something:
|
|
356
|
+
Run this over every `agents/*instructions.md`, every `agents/prompts/*.md` and
|
|
357
|
+
every `agents/skills/*/SKILL.md` after editing any of them. Every path-shaped
|
|
358
|
+
token in those files is read by a model as an instruction to open something:
|
|
304
359
|
|
|
305
360
|
- [ ] Every absolute path begins `/workspace`, `/assets`, `/skills` or
|
|
306
361
|
`/memory`. Nothing else exists.
|
|
307
|
-
- [ ] No project file is named: `agents.yaml`, `
|
|
362
|
+
- [ ] No project file is named: `agents.yaml`, `agents/instructions.md`,
|
|
308
363
|
`agents/prompts/…`, `agents/skills/…`, `sandbox/Dockerfile`, `.env`,
|
|
309
364
|
`.github/…`, `sessions/…`, `SPECIFICATION.md`, `README.md`, `docs/…`.
|
|
310
365
|
- [ ] Nothing escapes a mount: no `../`, no `~`, no host path (`/Users/…`,
|
|
@@ -327,13 +382,17 @@ Finding the candidates, from the project root - every path-shaped token in the
|
|
|
327
382
|
three trees, minus the ones under a mount:
|
|
328
383
|
|
|
329
384
|
```sh
|
|
330
|
-
|
|
331
|
-
INSTRUCTIONS.md agents/prompts agents/skills \
|
|
332
|
-
| sort -u | grep -Ev '^/(workspace|assets|skills|memory)(/|$)'
|
|
385
|
+
.github/skills/zen-review/scripts/check-paths.sh
|
|
333
386
|
```
|
|
334
387
|
|
|
335
|
-
|
|
336
|
-
|
|
388
|
+
It prints each candidate with the file and line it is on, and exits non-zero
|
|
389
|
+
while any remain. Everything it prints is either a path the agent cannot open or
|
|
390
|
+
noise the script has not learned yet - a url, a `path/to` in a sentence, an
|
|
391
|
+
`and/or` - and there is no third case. It strips the noise it does know about,
|
|
392
|
+
so a candidate that survives is one to explain or fix rather than one to skim
|
|
393
|
+
past. `check-paths.sh raw` is the sweep with nothing filtered, for when the
|
|
394
|
+
filter itself is the suspect. The `zen-review` skill says what it covers and
|
|
395
|
+
what it cannot.
|
|
337
396
|
|
|
338
397
|
---
|
|
339
398
|
|
|
@@ -410,7 +469,7 @@ provider with a missing key does not fail loading.
|
|
|
410
469
|
- `agents[].handoffs` naming an unknown agent, or the agent itself
|
|
411
470
|
- `agents[].skills.provider` / `.allow` / `.preload` naming something absent
|
|
412
471
|
- a `preload:` entry missing from `allow:`
|
|
413
|
-
- `agents[].fork.agents` naming an unknown agent, or being empty; `maxBranches` below
|
|
472
|
+
- `agents[].fork.agents` naming an unknown agent, or being empty; `maxBranches` below 1
|
|
414
473
|
- `system:` pointing at a missing file, or outside the project root
|
|
415
474
|
|
|
416
475
|
**Not caught at load** - a model id whose prefix is missing and so resolves to the
|
|
@@ -499,14 +558,26 @@ hide that. `maxBatch` therefore defaults to `1`; raise it only for a
|
|
|
499
558
|
`zen check` reports every declared embedding beside the models, with the
|
|
500
559
|
credential each one would need.
|
|
501
560
|
|
|
502
|
-
### 3.2 `
|
|
561
|
+
### 3.2 `agents/instructions.md` and friends
|
|
503
562
|
|
|
504
|
-
House rules, read **once** and prepended to every agent's system prompt.
|
|
505
|
-
the stable head of the cached prefix, so
|
|
563
|
+
House rules, read **once** and prepended to every agent's system prompt. They are
|
|
564
|
+
the stable head of the cached prefix, so they should change rarely. The name is
|
|
506
565
|
deliberately not `AGENTS.md` - that one belongs to the coding assistant reading
|
|
507
566
|
this file, and these rules address the project's own agents.
|
|
508
567
|
|
|
509
|
-
|
|
568
|
+
There may be more than one. `agents/instructions.md` is the base; every
|
|
569
|
+
`agents/<topic>-instructions.md` is read after it, in filename order, and every
|
|
570
|
+
agent gets all of them. Each arrives as its own block tagged with the file it
|
|
571
|
+
came from - `<house_rules src="agents/memory-instructions.md">` - so the model
|
|
572
|
+
can tell one document from the next.
|
|
573
|
+
|
|
574
|
+
Split a topic out when it is true for every agent but belongs to **one
|
|
575
|
+
capability**: the memory usage rules (§5.3) are the standard case - they arrive
|
|
576
|
+
when `memory:` is turned on and are deleted when it is turned off, which is a
|
|
577
|
+
whole file rather than a section somebody has to find. Do not split by author,
|
|
578
|
+
by date, or to keep a file short; that is what a skill is for.
|
|
579
|
+
|
|
580
|
+
Put in them only what is true for **every** agent:
|
|
510
581
|
|
|
511
582
|
- identity and domain ("You work the property claims desk")
|
|
512
583
|
- non-negotiable prohibitions (regulatory, legal, safety)
|
|
@@ -533,13 +604,13 @@ follow. So:
|
|
|
533
604
|
- Anything only one agent needs goes in that agent's prompt instead. If you find
|
|
534
605
|
yourself writing "if you are the router…", you are in the wrong file.
|
|
535
606
|
|
|
536
|
-
Target 20–60 lines. If
|
|
607
|
+
Target 20–60 lines each. If one exceeds ~100, split the stable half out into a
|
|
537
608
|
preloaded skill.
|
|
538
609
|
|
|
539
610
|
### 3.3 `agents/prompts/<name>.md`
|
|
540
611
|
|
|
541
612
|
Plain Markdown, no frontmatter. This is the agent's _job description_, appended
|
|
542
|
-
after
|
|
613
|
+
after the house rules.
|
|
543
614
|
|
|
544
615
|
Structure that works:
|
|
545
616
|
|
|
@@ -574,8 +645,8 @@ literally; it states the boundary ("you do not have them") with the _reason_; it
|
|
|
574
645
|
forbids the specific failure that agent actually exhibits.
|
|
575
646
|
|
|
576
647
|
Write it as a prompt, under the rules in §4.2 - **instructive and concise**. It
|
|
577
|
-
tells one agent what to do; it never explains the system (
|
|
578
|
-
already did, §3.2), never repeats
|
|
648
|
+
tells one agent what to do; it never explains the system (the house rules
|
|
649
|
+
already did, §3.2), never repeats one of them, and never describes the runtime.
|
|
579
650
|
Every line should be an instruction the model can act on or a boundary it can
|
|
580
651
|
check itself against.
|
|
581
652
|
|
|
@@ -808,23 +879,34 @@ sandbox:
|
|
|
808
879
|
env: [HTTPS_PROXY, NO_PROXY] # host variables to forward, by NAME
|
|
809
880
|
```
|
|
810
881
|
|
|
811
|
-
| Field | Default | Meaning
|
|
812
|
-
| --------- | --------------------------------------------- |
|
|
813
|
-
| `image` | `docker.io/library/python:3.14-slim-bookworm` | The base image commands run in
|
|
814
|
-
| `build` | none | A Dockerfile to build instead
|
|
815
|
-
| `cpus` | the host's | Fractional cores
|
|
816
|
-
| `memory` | the host's | MiB
|
|
817
|
-
| `network` | `bridge` | `bridge` / `none` / `host`
|
|
818
|
-
| `workdir` | `/workspace` | Mount point and default cwd
|
|
819
|
-
| `timeout` | `120` | Seconds per command
|
|
820
|
-
| `user` | the image's | uid, name, or `uid:gid`
|
|
821
|
-
| `persist` | `false` - **set it to `true`** | Keep the container between runs of a session
|
|
822
|
-
| `env` | none | Host variables to forward, **names**
|
|
882
|
+
| Field | Default | Meaning |
|
|
883
|
+
| --------- | --------------------------------------------- | --------------------------------------------- |
|
|
884
|
+
| `image` | `docker.io/library/python:3.14-slim-bookworm` | The base image commands run in |
|
|
885
|
+
| `build` | none | A Dockerfile to build instead |
|
|
886
|
+
| `cpus` | the host's | Fractional cores |
|
|
887
|
+
| `memory` | the host's | MiB |
|
|
888
|
+
| `network` | `bridge` | `bridge` / `none` / `host` |
|
|
889
|
+
| `workdir` | `/workspace` | Mount point and default cwd |
|
|
890
|
+
| `timeout` | `120` | Seconds per command |
|
|
891
|
+
| `user` | the image's | uid, name, or `uid:gid` |
|
|
892
|
+
| `persist` | `false` - **set it to `true`** | Keep the container between runs of a session |
|
|
893
|
+
| `env` | none | Host variables to forward, **names** |
|
|
894
|
+
| `keys` | `true` | Whether model credentials reach the container |
|
|
823
895
|
|
|
824
896
|
`env:` takes **names, never values** - a value here would be a secret in the
|
|
825
897
|
repository - and anything credential-shaped (`KEY`, `TOKEN`, `SECRET`,
|
|
826
898
|
`PASSWORD`, `CREDENTIAL`) is refused at load.
|
|
827
899
|
|
|
900
|
+
**Model credentials are already inside the container** (`keys:`, default
|
|
901
|
+
`true`). Every provider key the run holds is forwarded by name, and a Vertex
|
|
902
|
+
service-account file is bind-mounted read-only at `/run/zenera/keys` with
|
|
903
|
+
`GOOGLE_APPLICATION_CREDENTIALS` rewritten to point there - wherever it sits on
|
|
904
|
+
the host, keyring included. So a `zen` command that embeds (`zen rag … search`)
|
|
905
|
+
works in the sandbox: do not assume otherwise, do not route around it, and
|
|
906
|
+
never copy a key file into the project to "reach" the container. Only
|
|
907
|
+
`keys: false` / `zen run --no-keys` withholds them, and `network: none` is what
|
|
908
|
+
stops the call going out.
|
|
909
|
+
|
|
828
910
|
**`build:`, when no published image fits.** A project that needs two runtimes,
|
|
829
911
|
or a pinned toolchain, names a Dockerfile instead of an image - `zen init`
|
|
830
912
|
writes one at `sandbox/Dockerfile` with Python and Node in it:
|
|
@@ -1041,13 +1123,14 @@ is a different project, not a different key.
|
|
|
1041
1123
|
### 4.1 Composition order
|
|
1042
1124
|
|
|
1043
1125
|
```
|
|
1044
|
-
1.
|
|
1045
|
-
2. agents
|
|
1046
|
-
3.
|
|
1047
|
-
4.
|
|
1126
|
+
1. agents/instructions.md (shared, once, all agents)
|
|
1127
|
+
2. agents/*-instructions.md (shared too, filename order)
|
|
1128
|
+
3. agents/prompts/<n>.md (this agent)
|
|
1129
|
+
4. skill index (rendered by the runtime - do not hand-write it)
|
|
1130
|
+
5. preloaded skills (activated before the first call)
|
|
1048
1131
|
```
|
|
1049
1132
|
|
|
1050
|
-
Never duplicate
|
|
1133
|
+
Never duplicate house-rules content into an agent prompt; never hand-render
|
|
1051
1134
|
a list of skills into a prompt (the runtime does it, and a hand-written one goes
|
|
1052
1135
|
stale silently).
|
|
1053
1136
|
|
|
@@ -1089,8 +1172,8 @@ When behaviour is wrong, in this order:
|
|
|
1089
1172
|
|
|
1090
1173
|
1. **Read the actual assembled prompt**, not the file. Use the inspect report.
|
|
1091
1174
|
2. Is the instruction _present_? (Missed skill load, wrong agent, compaction.)
|
|
1092
|
-
3. Is it _contradicted_ by
|
|
1093
|
-
win over distant ones; later text usually wins over earlier.
|
|
1175
|
+
3. Is it _contradicted_ by a house-rules file or a skill? Adjacent
|
|
1176
|
+
contradictions win over distant ones; later text usually wins over earlier.
|
|
1094
1177
|
4. Is it _specific enough to be checkable_? Rewrite as a testable assertion.
|
|
1095
1178
|
5. Only then consider a stronger model.
|
|
1096
1179
|
|
|
@@ -1105,15 +1188,15 @@ it forever.
|
|
|
1105
1188
|
|
|
1106
1189
|
The decision for every piece of knowledge:
|
|
1107
1190
|
|
|
1108
|
-
| Where
|
|
1109
|
-
|
|
|
1110
|
-
| `
|
|
1111
|
-
| agent prompt
|
|
1112
|
-
| **preloaded skill**
|
|
1113
|
-
| **indexed skill**
|
|
1114
|
-
| **searched skill**
|
|
1115
|
-
| **tool**
|
|
1116
|
-
| **memory**
|
|
1191
|
+
| Where | Cost | Use when |
|
|
1192
|
+
| ------------------------- | ----------------------- | ----------------------------------------------------- |
|
|
1193
|
+
| `agents/*instructions.md` | every call, every agent | true always, for everyone |
|
|
1194
|
+
| agent prompt | every call, one agent | true always, for this job |
|
|
1195
|
+
| **preloaded skill** | every call, one agent | always needed, but versioned/shared separately |
|
|
1196
|
+
| **indexed skill** | one line until loaded | needed _sometimes_, model can tell when from one line |
|
|
1197
|
+
| **searched skill** | nothing until searched | catalog too large to index (>~30 entries) |
|
|
1198
|
+
| **tool** | schema only | needs live data, exact arithmetic, or a side effect |
|
|
1199
|
+
| **memory** | recall block when hit | learned across runs, not authored |
|
|
1117
1200
|
|
|
1118
1201
|
### 5.2 Skill bindings
|
|
1119
1202
|
|
|
@@ -1166,6 +1249,39 @@ Every node carries an **audience**, and an agent's `sees` is the set it reads:
|
|
|
1166
1249
|
one graph, masked per agent, never one graph each. The four `memory_*` tools are
|
|
1167
1250
|
derived from `access` and are never listed in `tools:`.
|
|
1168
1251
|
|
|
1252
|
+
**Memory comes on.** `zen init` writes the block above, `memory: true` on the
|
|
1253
|
+
default agent, and the half nobody would guess was part of it:
|
|
1254
|
+
`agents/memory-instructions.md`, a copy of the `zen-memory` skill's
|
|
1255
|
+
`references/memory-instructions.md`, which the project already holds. Adding
|
|
1256
|
+
memory to a project that has none is both of those edits, and a copy that was
|
|
1257
|
+
lost or went stale is one command:
|
|
1258
|
+
|
|
1259
|
+
```sh
|
|
1260
|
+
.github/skills/zen-memory/scripts/check-instructions.sh fix
|
|
1261
|
+
```
|
|
1262
|
+
|
|
1263
|
+
It is what tells the agent that the store is reached only through the tools, that
|
|
1264
|
+
`memory_search` clips a node's text and `memory_load` reads it whole, that a
|
|
1265
|
+
remembered file's path comes from `memory_load` and not from listing `/memory`,
|
|
1266
|
+
what a node must carry to be worth having, and that a correction is a
|
|
1267
|
+
`SUPERSEDES` edge rather than an edit. It is its own file rather than a section of
|
|
1268
|
+
`agents/instructions.md` because it arrives with the `memory:` block and leaves
|
|
1269
|
+
with it.
|
|
1270
|
+
|
|
1271
|
+
**Leave that file as a pure copy.** Anything this project decides for itself -
|
|
1272
|
+
which audience holds what, what must never be written down, what an agent is
|
|
1273
|
+
expected to commit at the end of a job - goes in
|
|
1274
|
+
`agents/memory-policy-instructions.md`. Topic files are read in filename order,
|
|
1275
|
+
so the policy lands directly after the rules it qualifies, and the copy stays
|
|
1276
|
+
re-runnable: the reference is rewritten by every `zen init` and `zen open`, and
|
|
1277
|
+
keeping up with it is then the same one-line command rather than a hand-patch.
|
|
1278
|
+
|
|
1279
|
+
`zen check` validates the `memory:` block and says nothing about the rules'
|
|
1280
|
+
absence, so this is checked every time, by
|
|
1281
|
+
`.github/skills/zen-memory/scripts/check-instructions.sh` and never by reading
|
|
1282
|
+
the two files against each other: they drift by trailing whitespace inside a
|
|
1283
|
+
table, and the script is what can see that.
|
|
1284
|
+
|
|
1169
1285
|
Do not treat memory as a database. It is for things learned that should
|
|
1170
1286
|
persist. Anything authoritative - a rate, a policy clause, a procedure - belongs
|
|
1171
1287
|
in a skill, where it is versioned and reviewable.
|
|
@@ -1179,12 +1295,12 @@ in front of a `zen rag` index - is in the `zen-memory` skill.
|
|
|
1179
1295
|
Rules that follow directly from "stable prefix = cache hit":
|
|
1180
1296
|
|
|
1181
1297
|
- Do not reorder `agents.yaml` for cosmetic reasons - tool order is prompt order.
|
|
1182
|
-
- Do not put timestamps, run ids, or "today is …" in
|
|
1298
|
+
- Do not put timestamps, run ids, or "today is …" in a house-rules file or a
|
|
1183
1299
|
prompt. A changing prefix is a permanent cache miss. Put volatile facts in a
|
|
1184
1300
|
tool result.
|
|
1185
1301
|
- Prefer `preload` over an instruction telling the model to load a skill first.
|
|
1186
1302
|
- Keep the volatile half of an instruction in the agent prompt and the stable
|
|
1187
|
-
half in
|
|
1303
|
+
half in the house rules, not the reverse.
|
|
1188
1304
|
|
|
1189
1305
|
---
|
|
1190
1306
|
|
|
@@ -1269,7 +1385,8 @@ interchangeable:
|
|
|
1269
1385
|
- The other agent should **own the conversation from here** → `handoffs:`, and
|
|
1270
1386
|
something on the far side has to lead back.
|
|
1271
1387
|
- This agent needs **an answer and then carries on** → `fork:`. Never a handoff:
|
|
1272
|
-
a handoff spends the conversation to get the answer.
|
|
1388
|
+
a handoff spends the conversation to get the answer. One branch is enough -
|
|
1389
|
+
a fork of one is exactly "ask the specialist and continue".
|
|
1273
1390
|
|
|
1274
1391
|
But the return is **condensed**: `A → fork → B` rejoins as one tool result
|
|
1275
1392
|
holding B's answer, so A never sees the steps B took - no tool calls, no files
|
|
@@ -1297,7 +1414,7 @@ agents:
|
|
|
1297
1414
|
| Field | Default | Meaning |
|
|
1298
1415
|
| ------------- | -------------------- | ------------------------------------- |
|
|
1299
1416
|
| `agents` | every declared agent | Which agents a branch may run |
|
|
1300
|
-
| `maxBranches` | unlimited | Cap on branches per call; minimum `
|
|
1417
|
+
| `maxBranches` | unlimited | Cap on branches per call; minimum `1` |
|
|
1301
1418
|
|
|
1302
1419
|
The **model** decides the split: it names N branches, each with self-contained
|
|
1303
1420
|
instructions. They run truly concurrently and rejoin as **one tool call and one
|
|
@@ -1310,8 +1427,10 @@ Rules worth knowing before you write the key:
|
|
|
1310
1427
|
is not an error, and one role fanned out over ten items is the common shape.
|
|
1311
1428
|
The list reaches the model as an `enum`, so a name outside it cannot even be
|
|
1312
1429
|
decoded.
|
|
1313
|
-
- A fork
|
|
1314
|
-
|
|
1430
|
+
- A fork of **one** branch is delegation, and it is valid: one assignment run
|
|
1431
|
+
elsewhere, its conclusion returned, its transcript left out of this
|
|
1432
|
+
conversation. Use it when another agent suits the job better, or when the job
|
|
1433
|
+
would fill the caller's context with material it has no use for afterwards.
|
|
1315
1434
|
- **Branches cannot talk to each other.** If branch B needs branch A's answer,
|
|
1316
1435
|
it is a sequence, not a fork - keep it in one conversation.
|
|
1317
1436
|
- Nesting is capped by the run's `maxForkDepth` (2 by default), so a branch may
|
|
@@ -1330,10 +1449,12 @@ agent's prompt which one this work wants:
|
|
|
1330
1449
|
- `none` - system prompt plus instructions only. Cheapest; for independent
|
|
1331
1450
|
lookups.
|
|
1332
1451
|
|
|
1333
|
-
Declaring `fork:` only makes the tool available.
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1452
|
+
Declaring `fork:` only makes the tool available. What a fork costs and what
|
|
1453
|
+
survives the join is explained to the model by the runtime, in the system prompt
|
|
1454
|
+
of every agent holding the key. What is left to you is _when_, in the terms of
|
|
1455
|
+
this domain - _"When the request covers more than one region, fork one branch
|
|
1456
|
+
per region and merge their findings"_ - or a weaker model will work through the
|
|
1457
|
+
list serially and never call it.
|
|
1337
1458
|
|
|
1338
1459
|
### 6.5 Termination
|
|
1339
1460
|
|
|
@@ -1736,6 +1857,16 @@ ok, `1` failed, `2` usage, `3` invalid project, `4` no usable credential.
|
|
|
1736
1857
|
|
|
1737
1858
|
## 9. Review checklist
|
|
1738
1859
|
|
|
1860
|
+
Four of these are decidable, and are one command - `zen check`, the path sweep,
|
|
1861
|
+
the memory copy, the spec-sync record, in that order:
|
|
1862
|
+
|
|
1863
|
+
```sh
|
|
1864
|
+
.github/skills/zen-review/scripts/review.sh
|
|
1865
|
+
```
|
|
1866
|
+
|
|
1867
|
+
Run it first and read what it says. Everything else below is judgement, which is
|
|
1868
|
+
why it is still a list. The `zen-review` skill has the detail.
|
|
1869
|
+
|
|
1739
1870
|
Before finishing any change here:
|
|
1740
1871
|
|
|
1741
1872
|
**Structure**
|
|
@@ -1750,16 +1881,24 @@ Before finishing any change here:
|
|
|
1750
1881
|
|
|
1751
1882
|
**Prompts**
|
|
1752
1883
|
|
|
1753
|
-
- [ ] `
|
|
1754
|
-
-
|
|
1884
|
+
- [ ] `agents/instructions.md` carries the shared architecture and nothing
|
|
1885
|
+
agent-specific
|
|
1886
|
+
- [ ] Nothing duplicated between a house-rules file and an agent prompt
|
|
1887
|
+
- [ ] Each `agents/<topic>-instructions.md` is about one capability, and is true
|
|
1888
|
+
of every agent
|
|
1755
1889
|
- [ ] Every tool and agent referenced by its exact name
|
|
1756
1890
|
- [ ] Failure paths stated for every instruction that can fail
|
|
1757
1891
|
- [ ] No facts, rates or figures embedded in a prompt
|
|
1758
1892
|
- [ ] No hedging, no meta-talk about the runtime
|
|
1893
|
+
- [ ] If any agent has `memory:`,
|
|
1894
|
+
`.github/skills/zen-memory/scripts/check-instructions.sh` exits zero -
|
|
1895
|
+
`agents/memory-instructions.md` is the reference byte for byte - and
|
|
1896
|
+
anything project-specific is in `agents/memory-policy-instructions.md` - §5.3
|
|
1759
1897
|
|
|
1760
|
-
**Paths (§2.5 -
|
|
1898
|
+
**Paths (§2.5 - `.github/skills/zen-review/scripts/check-paths.sh` finds the
|
|
1899
|
+
candidates; these are the judgements to make about each one)**
|
|
1761
1900
|
|
|
1762
|
-
- [ ] Every absolute path in `
|
|
1901
|
+
- [ ] Every absolute path in `agents/*instructions.md`, `agents/prompts/*.md` and
|
|
1763
1902
|
`agents/skills/*/SKILL.md` is under `/workspace`, `/assets`, `/skills` or
|
|
1764
1903
|
`/memory`
|
|
1765
1904
|
- [ ] No prompt or skill names a project file - `agents.yaml`, a prompt path, a
|
|
@@ -1807,14 +1946,29 @@ Before finishing any change here:
|
|
|
1807
1946
|
- [ ] No key literal in YAML, prompt, skill or log - `${VAR}` only
|
|
1808
1947
|
- [ ] `.env` is git-ignored
|
|
1809
1948
|
|
|
1949
|
+
**Specification** (only where the project has a `SPECIFICATION.md`)
|
|
1950
|
+
|
|
1951
|
+
- [ ] `.github/skills/zen-spec-sync/scripts/snapshot.sh status` does not say
|
|
1952
|
+
`tampered` - the baseline matches its own `manifest.txt`
|
|
1953
|
+
- [ ] `.spec-sync/baseline/applied.txt` names the newest file in
|
|
1954
|
+
`.spec-sync/history/`; a baseline ahead of the history is a pass that
|
|
1955
|
+
claimed work it did not finish
|
|
1956
|
+
- [ ] The newest history entry's `Still open` is what the next pass will trust,
|
|
1957
|
+
and says so honestly - an unchanged specification line is not evidence
|
|
1958
|
+
that anything implements it
|
|
1959
|
+
- [ ] No question in `SPECIFICATION-FEEDBACK.md` has a box marked `[x]`, or
|
|
1960
|
+
exactly one answer left under it, without a matching `✅ Answered` entry -
|
|
1961
|
+
that is an answer given and never folded into the specification
|
|
1962
|
+
- [ ] `.spec-sync/` is committed and `.tmp/` is not
|
|
1963
|
+
|
|
1810
1964
|
---
|
|
1811
1965
|
|
|
1812
1966
|
## 10. Where to change what
|
|
1813
1967
|
|
|
1814
1968
|
| Symptom | Change this |
|
|
1815
1969
|
| --------------------------------------------- | ------------------------------------------------------------------- |
|
|
1816
|
-
| Wrong tone, wrong format, wrong length |
|
|
1817
|
-
| Says something forbidden |
|
|
1970
|
+
| Wrong tone, wrong format, wrong length | The house rules (all agents) or the agent prompt |
|
|
1971
|
+
| Says something forbidden | A house-rules prohibition, stated specifically |
|
|
1818
1972
|
| Ignores a rule that only applies sometimes | Move the rule into a skill with a sharp description |
|
|
1819
1973
|
| Never loads the skill it should | The skill's `description`; or `preload` it |
|
|
1820
1974
|
| Loads too much, answers slowly | `allow:`, `maxIndexEntries:`, or `discovery: search` |
|
|
@@ -1841,6 +1995,8 @@ Before finishing any change here:
|
|
|
1841
1995
|
| Fails only on genuinely hard cases | Promote that agent's tier, or split the hard path out |
|
|
1842
1996
|
| Shows no reasoning while it works | Turn summaries on for that model - §7.6 |
|
|
1843
1997
|
| Forgets across conversations | Continue the session rather than starting a new one |
|
|
1998
|
+
| Greps `/memory` or reads `graph.json` | `agents/memory-instructions.md` is missing the block - §5.3 |
|
|
1999
|
+
| Recalls a note it cannot check or continue | Same block: it is what requires provenance on every node - §5.3 |
|
|
1844
2000
|
| Breaks at load with a named path | Read the message - it names the exact key |
|
|
1845
2001
|
|
|
1846
2002
|
---
|
|
@@ -1850,16 +2006,23 @@ Before finishing any change here:
|
|
|
1850
2006
|
- **The mega-prompt.** 300 lines covering twelve scenarios. Split into skills.
|
|
1851
2007
|
- **Agent sprawl.** Eight agents that share one model, one tool set and one
|
|
1852
2008
|
prompt style. Collapse into one with a catalog.
|
|
1853
|
-
- **Facts in prompts.** A fee schedule inside `
|
|
1854
|
-
versioned, cannot be shared, and is paid for on every call.
|
|
2009
|
+
- **Facts in prompts.** A fee schedule inside `agents/instructions.md`. It cannot
|
|
2010
|
+
be versioned, cannot be shared, and is paid for on every call.
|
|
1855
2011
|
- **The bare skill file.** `agents/skills/<name>.md` instead of a folder. It can
|
|
1856
2012
|
never grow the table or script the next revision of the rule will want - §3.4.
|
|
1857
2013
|
- **Pointing an agent at the project.** A prompt or skill naming `agents.yaml`,
|
|
1858
|
-
`
|
|
1859
|
-
them are on any path the agent can open, so the instruction fails on
|
|
1860
|
-
that follows it - §2.5.
|
|
2014
|
+
`agents/instructions.md`, `agents/skills/<name>/…` or `sandbox/Dockerfile`.
|
|
2015
|
+
None of them are on any path the agent can open, so the instruction fails on
|
|
2016
|
+
the turn that follows it - §2.5.
|
|
1861
2017
|
- **Arithmetic in prose.** A skill that walks the model through a calculation it
|
|
1862
2018
|
will get wrong, in a folder that could have held the script - §3.4.1.
|
|
2019
|
+
- **The unguarded store.** `memory:` turned on and the skill's
|
|
2020
|
+
`references/memory-instructions.md` never copied to
|
|
2021
|
+
`agents/memory-instructions.md`, so nothing tells the agent the store is
|
|
2022
|
+
reached only through the tools - and `zen check` passes throughout - §5.3.
|
|
2023
|
+
- **Reviewing a capability without its skill.** A project whose memory, index or
|
|
2024
|
+
sandbox was configured by an earlier pass looks finished because it loads. The
|
|
2025
|
+
obligations are in the editor skill, not in `agents.yaml` - §0.1.
|
|
1863
2026
|
- **Politeness padding.** "Please try your best to be helpful." Costs tokens,
|
|
1864
2027
|
changes nothing.
|
|
1865
2028
|
- **Commented implementation notes.** `agents.yaml` explaining how skill
|
|
@@ -1875,7 +2038,7 @@ Before finishing any change here:
|
|
|
1875
2038
|
branch needs the first branch's answer is a sequence wearing a fork's clothes.
|
|
1876
2039
|
- **Installing the toolchain every run.** A prompt that begins with `apt-get
|
|
1877
2040
|
install` is an `image:` that was never set - §3.7.
|
|
1878
|
-
- **Volatile prefix.** "Current date: …" in
|
|
2041
|
+
- **Volatile prefix.** "Current date: …" in the house rules. Permanent cache
|
|
1879
2042
|
miss.
|
|
1880
2043
|
|
|
1881
2044
|
---
|
|
@@ -1894,6 +2057,8 @@ Update it when:
|
|
|
1894
2057
|
- a vendor trap is discovered - add it to §7.7
|
|
1895
2058
|
- a recurring review comment appears twice - turn it into a checklist line in §9
|
|
1896
2059
|
- a runtime capability is added - describe it here, or it will not be used
|
|
2060
|
+
- an editor skill starts requiring a block in the target project - name the
|
|
2061
|
+
requirement in §0.1 and the check for it in §9, or it will be missed
|
|
1897
2062
|
|
|
1898
2063
|
Do not let it grow without pruning. When a section is only true of one agent, it
|
|
1899
2064
|
belongs in that agent's prompt, not here.
|