@zenera/cli 1.1.24 → 1.1.26

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 (199) hide show
  1. package/README.md +65 -0
  2. package/dist/ask.js +28 -5
  3. package/dist/banner.js +2 -2
  4. package/dist/batch.d.ts +6 -0
  5. package/dist/batch.js +76 -1
  6. package/dist/catalog.d.ts +31 -1
  7. package/dist/catalog.js +140 -7
  8. package/dist/commands/index.js +2 -0
  9. package/dist/commands/inspect.d.ts +52 -2
  10. package/dist/commands/inspect.js +220 -31
  11. package/dist/commands/memory.js +156 -32
  12. package/dist/commands/meta.js +333 -24
  13. package/dist/commands/models.js +97 -12
  14. package/dist/commands/open.js +4 -4
  15. package/dist/commands/run.js +38 -4
  16. package/dist/commands/sandbox.js +148 -16
  17. package/dist/commands/view.d.ts +8 -0
  18. package/dist/commands/view.js +114 -0
  19. package/dist/engine.d.ts +8 -1
  20. package/dist/engine.js +7 -0
  21. package/dist/eventlog.d.ts +64 -0
  22. package/dist/eventlog.js +170 -0
  23. package/dist/liveness.d.ts +7 -0
  24. package/dist/liveness.js +35 -3
  25. package/dist/main.js +0 -0
  26. package/dist/meta/editor.d.ts +9 -0
  27. package/dist/meta/editor.js +43 -0
  28. package/dist/meta/finetune/analyze-brief.d.ts +26 -0
  29. package/dist/meta/finetune/analyze-brief.js +131 -0
  30. package/dist/meta/finetune/apply-brief.d.ts +23 -0
  31. package/dist/meta/finetune/apply-brief.js +247 -0
  32. package/dist/meta/finetune/brief.d.ts +45 -0
  33. package/dist/meta/finetune/brief.js +158 -0
  34. package/dist/meta/finetune/children.d.ts +8 -0
  35. package/dist/meta/finetune/children.js +76 -0
  36. package/dist/meta/finetune/command.d.ts +30 -0
  37. package/dist/meta/finetune/command.js +516 -0
  38. package/dist/meta/finetune/cost.d.ts +46 -0
  39. package/dist/meta/finetune/cost.js +105 -0
  40. package/dist/meta/finetune/dataset/anchors.d.ts +41 -0
  41. package/dist/meta/finetune/dataset/anchors.js +239 -0
  42. package/dist/meta/finetune/dataset/changes.d.ts +36 -0
  43. package/dist/meta/finetune/dataset/changes.js +319 -0
  44. package/dist/meta/finetune/dataset/command.d.ts +17 -0
  45. package/dist/meta/finetune/dataset/command.js +1011 -0
  46. package/dist/meta/finetune/dataset/drift.d.ts +33 -0
  47. package/dist/meta/finetune/dataset/drift.js +71 -0
  48. package/dist/meta/finetune/dataset/export.d.ts +26 -0
  49. package/dist/meta/finetune/dataset/export.js +51 -0
  50. package/dist/meta/finetune/dataset/index.d.ts +2 -0
  51. package/dist/meta/finetune/dataset/index.js +2 -0
  52. package/dist/meta/finetune/dataset/sample.d.ts +50 -0
  53. package/dist/meta/finetune/dataset/sample.js +197 -0
  54. package/dist/meta/finetune/dataset/schema.d.ts +33 -0
  55. package/dist/meta/finetune/dataset/schema.js +216 -0
  56. package/dist/meta/finetune/dataset/store.d.ts +35 -0
  57. package/dist/meta/finetune/dataset/store.js +177 -0
  58. package/dist/meta/finetune/dataset/types.d.ts +127 -0
  59. package/dist/meta/finetune/dataset/types.js +39 -0
  60. package/dist/meta/finetune/failure.d.ts +15 -0
  61. package/dist/meta/finetune/failure.js +26 -0
  62. package/dist/meta/finetune/feedback.d.ts +57 -0
  63. package/dist/meta/finetune/feedback.js +104 -0
  64. package/dist/meta/finetune/guard.d.ts +29 -0
  65. package/dist/meta/finetune/guard.js +104 -0
  66. package/dist/meta/finetune/improvements.d.ts +98 -0
  67. package/dist/meta/finetune/improvements.js +501 -0
  68. package/dist/meta/finetune/index.d.ts +2 -0
  69. package/dist/meta/finetune/index.js +2 -0
  70. package/dist/meta/finetune/journal.d.ts +35 -0
  71. package/dist/meta/finetune/journal.js +135 -0
  72. package/dist/meta/finetune/live.d.ts +84 -0
  73. package/dist/meta/finetune/live.js +272 -0
  74. package/dist/meta/finetune/loop.d.ts +3 -0
  75. package/dist/meta/finetune/loop.js +163 -0
  76. package/dist/meta/finetune/memories.d.ts +47 -0
  77. package/dist/meta/finetune/memories.js +154 -0
  78. package/dist/meta/finetune/recheck.d.ts +58 -0
  79. package/dist/meta/finetune/recheck.js +311 -0
  80. package/dist/meta/finetune/report.d.ts +40 -0
  81. package/dist/meta/finetune/report.js +1397 -0
  82. package/dist/meta/finetune/retry.d.ts +24 -0
  83. package/dist/meta/finetune/retry.js +96 -0
  84. package/dist/meta/finetune/sampler.d.ts +18 -0
  85. package/dist/meta/finetune/sampler.js +47 -0
  86. package/dist/meta/finetune/system.d.ts +27 -0
  87. package/dist/meta/finetune/system.js +132 -0
  88. package/dist/meta/finetune/train.d.ts +43 -0
  89. package/dist/meta/finetune/train.js +425 -0
  90. package/dist/meta/finetune/tui.d.ts +16 -0
  91. package/dist/meta/finetune/tui.js +316 -0
  92. package/dist/meta/finetune/tuning.d.ts +193 -0
  93. package/dist/meta/finetune/tuning.js +308 -0
  94. package/dist/meta/finetune/usage.d.ts +66 -0
  95. package/dist/meta/finetune/usage.js +260 -0
  96. package/dist/meta/finetune/view.d.ts +9 -0
  97. package/dist/meta/finetune/view.js +27 -0
  98. package/dist/meta/host.d.ts +15 -0
  99. package/dist/meta/host.js +21 -0
  100. package/dist/meta/index.d.ts +11 -0
  101. package/dist/meta/index.js +11 -0
  102. package/dist/meta/launch.d.ts +81 -0
  103. package/dist/meta/launch.js +286 -0
  104. package/dist/meta/model.d.ts +44 -0
  105. package/dist/meta/model.js +119 -0
  106. package/dist/meta/prompts.d.ts +18 -0
  107. package/dist/meta/prompts.js +61 -0
  108. package/dist/meta/relay.d.ts +20 -0
  109. package/dist/meta/relay.js +123 -0
  110. package/dist/meta/tokens.d.ts +52 -0
  111. package/dist/meta/tokens.js +226 -0
  112. package/dist/meta/window.d.ts +61 -0
  113. package/dist/meta/window.js +198 -0
  114. package/dist/meta/wire.d.ts +42 -0
  115. package/dist/meta/wire.js +129 -0
  116. package/dist/meta.d.ts +71 -1
  117. package/dist/meta.js +303 -6
  118. package/dist/modelref.d.ts +16 -0
  119. package/dist/modelref.js +41 -0
  120. package/dist/narrate.js +5 -2
  121. package/dist/podman.d.ts +26 -0
  122. package/dist/podman.js +83 -3
  123. package/dist/projects.d.ts +0 -5
  124. package/dist/projects.js +2 -15
  125. package/dist/resources.d.ts +215 -0
  126. package/dist/resources.js +856 -0
  127. package/dist/sandbox.d.ts +2 -0
  128. package/dist/sandbox.js +10 -3
  129. package/dist/scaffold.d.ts +15 -7
  130. package/dist/scaffold.js +24 -67
  131. package/dist/session.js +4 -29
  132. package/dist/term.d.ts +2 -0
  133. package/dist/term.js +11 -2
  134. package/dist/trace.d.ts +5 -0
  135. package/dist/trace.js +107 -7
  136. package/dist/tui/app.js +19 -5
  137. package/dist/tui/links.d.ts +27 -0
  138. package/dist/tui/links.js +142 -0
  139. package/dist/tui/models.d.ts +35 -0
  140. package/dist/tui/models.js +447 -0
  141. package/dist/tui/sandbox.d.ts +10 -0
  142. package/dist/tui/sandbox.js +131 -0
  143. package/dist/tui/wrap.d.ts +5 -0
  144. package/dist/tui/wrap.js +12 -0
  145. package/dist/usage.d.ts +78 -0
  146. package/dist/usage.js +51 -0
  147. package/package.json +4 -2
  148. package/templates/editor/.github/copilot-instructions.md +60 -145
  149. package/templates/editor/.github/prompts/analyze.prompt.md +33 -0
  150. package/templates/editor/.github/prompts/dataset.prompt.md +108 -0
  151. package/templates/editor/.github/prompts/finetune-apply.prompt.md +270 -0
  152. package/templates/editor/.github/prompts/finetune.prompt.md +691 -198
  153. package/templates/editor/.github/prompts/new-agent.prompt.md +3 -1
  154. package/templates/editor/.github/prompts/new-skill.prompt.md +2 -0
  155. package/templates/editor/.github/prompts/project-review.prompt.md +5 -4
  156. package/templates/editor/.github/skills/zen-analyze-run/SKILL.md +588 -0
  157. package/templates/editor/.github/skills/zen-cli/SKILL.md +9 -1
  158. package/templates/editor/.github/skills/zen-cli/references/dataset.md +34 -0
  159. package/templates/editor/.github/skills/zen-cli/references/finetune.md +137 -0
  160. package/templates/editor/.github/skills/zen-cli/references/inspect.md +63 -11
  161. package/templates/editor/.github/skills/zen-cli/references/memory.md +33 -10
  162. package/templates/editor/.github/skills/zen-cli/references/meta.md +61 -0
  163. package/templates/editor/.github/skills/zen-cli/references/models.md +5 -1
  164. package/templates/editor/.github/skills/zen-cli/references/projects.md +4 -6
  165. package/templates/editor/.github/skills/zen-cli/references/rag.md +24 -6
  166. package/templates/editor/.github/skills/zen-cli/references/sandbox.md +35 -14
  167. package/templates/editor/.github/skills/zen-code-python/SKILL.md +123 -0
  168. package/templates/editor/.github/skills/zen-code-python/references/code_python.md +48 -0
  169. package/templates/editor/.github/skills/zen-dataset/SKILL.md +253 -0
  170. package/templates/editor/.github/skills/zen-finetune/SKILL.md +1492 -660
  171. package/templates/editor/.github/skills/zen-finetune/references/readme-template.md +268 -0
  172. package/templates/editor/.github/skills/zen-finetune/scripts/batch.mjs +390 -0
  173. package/templates/editor/.github/skills/zen-finetune/scripts/difficult.mjs +243 -0
  174. package/templates/editor/.github/skills/zen-finetune/scripts/memory.mjs +280 -0
  175. package/templates/editor/.github/skills/zen-finetune/scripts/next.mjs +398 -0
  176. package/templates/editor/.github/skills/zen-finetune/scripts/report.mjs +797 -0
  177. package/templates/editor/.github/skills/zen-finetune/scripts/select.mjs +354 -0
  178. package/templates/editor/.github/skills/zen-finetune/scripts/usage.mjs +722 -0
  179. package/templates/editor/.github/skills/zen-inspect/SKILL.md +74 -26
  180. package/templates/editor/.github/skills/zen-inspect-ask/SKILL.md +271 -0
  181. package/templates/editor/.github/skills/zen-instructions/SKILL.md +4 -12
  182. package/templates/editor/.github/skills/zen-memory/SKILL.md +82 -53
  183. package/templates/editor/.github/skills/zen-rag-docs/SKILL.md +20 -8
  184. package/templates/editor/.github/skills/zen-review/SKILL.md +8 -31
  185. package/templates/editor/.github/skills/zen-review/scripts/check-paths.sh +5 -5
  186. package/templates/editor/.github/skills/zen-review/scripts/review.sh +3 -12
  187. package/templates/editor/.github/skills/zen-sandbox/SKILL.md +9 -4
  188. package/templates/editor/.github/skills/zen-sandbox-capacity/SKILL.md +2 -2
  189. package/templates/editor/.github/skills/zen-spec-sync/SKILL.md +2 -4
  190. package/templates/editor/.github/skills/zen-topology/SKILL.md +283 -0
  191. package/templates/editor/.vscode/settings.json +1 -0
  192. package/templates/project/agents/files-instructions.md +29 -20
  193. package/templates/project/agents/fork-instructions.md +78 -28
  194. package/templates/project/agents/memory-instructions.md +222 -494
  195. package/templates/project/agents/tools-instructions.md +14 -4
  196. package/templates/project/gitignore +2 -0
  197. package/templates/editor/.github/skills/zen-finetune/scripts/collect.sh +0 -432
  198. package/templates/editor/.github/skills/zen-finetune/scripts/sample.sh +0 -199
  199. package/templates/editor/.github/skills/zen-memory/scripts/check-instructions.sh +0 -116
@@ -1,20 +1,30 @@
1
1
  ---
2
2
  name: zen-inspect
3
- description: Diagnosing a run you did not watch - the `zen inspect graph` → read → `zen inspect node` loop, how to name the run (`--dir`, `--run`, `--session`, and why `node` takes ids only), how to read every part of the graph format (the `%%` header rows and what each count is evidence of, the anatomy of a node line, the label each node kind produces, shapes and colours, the `flow`/`branches`/`calls` edge blocks, branch subgraphs, and what `hidden by` and `ERROR` mean), how to open individual nodes by id or range and read the `===`/`--- part` framing, which payload parts and facts each kind carries, how `zen inspect ask` replays one `llm_call` to a model with a question when reading the node did not settle why it acted, and recipes for the usual faults - a loop, a failing tool, a prompt that was assembled differently from how it reads, a hand-off that fired early, a skill that never activated, a branch that failed, tokens spent where you did not expect. Load before reading any run trajectory, before answering "why did the agent do that", and whenever a run directory is all you have.
3
+ description: 'Use when an LLM agent must diagnose a recorded Zenera run non-interactively: read `zen inspect graph`, open selected nodes, replay an `llm_call` with `zen inspect ask`, identify loops, failed tools, wrong prompts, missed skills, early hand-offs, failed branches, compaction, latency, or token waste. Requires explicit run, node, and question arguments so commands remain deterministic and never prompt.'
4
4
  ---
5
5
 
6
- # Reading a run
6
+ # Diagnose a run non-interactively
7
7
 
8
8
  A run leaves behind everything it did, and that is the problem: a trajectory of
9
9
  a few hundred nodes is far too big to read and far too repetitive to need to.
10
10
  `zen inspect` answers it in two halves.
11
11
 
12
- | Command | For | Gives |
13
- | ----------------------- | ------- | ----------------------------------------------- |
14
- | `zen inspect report` | a human | `report.html` - every message, payload and cost |
15
- | `zen inspect graph` | you | the whole run as one Mermaid flowchart |
16
- | `zen inspect node <id>` | you | those nodes in full, payloads resolved |
17
- | `zen inspect ask <id>` | you | that call replayed to a model, with a question |
12
+ This skill is for an agent process without a TTY. Every invocation must be
13
+ fully specified. Never run bare `zen inspect` or `zen inspect node`: without a
14
+ run named they read whichever run is newest. Never run `zen inspect ask`
15
+ without a question: that is the interactive mode, for a person, and it fails
16
+ without a terminal. With a question it is one-shot - no banner, no prompt,
17
+ only the answer on stdout.
18
+
19
+ For a whole-run audit - health, memory, delegation, forking, tool use, and
20
+ what to change in the instructions - load **zen-analyze-run**, which drives
21
+ this skill end to end.
22
+
23
+ | Command | Gives |
24
+ | ---------------------------------------------------------- | --------------------------------------------- |
25
+ | `zen inspect graph --dir <run-dir>` | the whole run as one model-readable flowchart |
26
+ | `zen inspect node <id...> --dir <run-dir>` | selected nodes, payloads resolved |
27
+ | `zen inspect ask <id> --question-file <f> --dir <run-dir>` | one replay answer on stdout, then exit |
18
28
 
19
29
  **`graph` and `node` are the pair you use.** The graph is an index: one line per
20
30
  node, short sequential ids, the whole run in a few hundred lines. `node` is the
@@ -26,8 +36,26 @@ pay for what you open.
26
36
  run's own model why it did what it did. Open the node first - most questions are
27
37
  answered by reading what it was given.
28
38
 
29
- `report` is for a person with a browser. Print its path and hand it over; do not
30
- try to read the HTML.
39
+ To get one answer without prompts, pass all three inputs:
40
+
41
+ ```sh
42
+ zen inspect ask <llm-node-id> --question-file <question file> --dir <run-dir>
43
+ ```
44
+
45
+ - `<llm-node-id>` is an `nN` id from `zen inspect graph` whose label starts
46
+ with `llm`.
47
+ - `<question file>` holds the complete question, written with your
48
+ file-editing tool to `.tmp/ask/<run-id>/<node>-<topic>.md`. The shell never
49
+ parses it, so quotes, backticks and `$` arrive as written. Never pass the
50
+ question as a quoted argument, a heredoc or `$(cat ...)`, and never wrap
51
+ `zen` in a script.
52
+ - `--dir <run-dir>` identifies the run. Instead, a caller may use `--run
53
+ <run-id>` with `--session <session-id>` and, when outside the project,
54
+ `--project <name-or-dir>`.
55
+
56
+ Exactly one raw Markdown answer is written to stdout, then the command exits.
57
+ Omit `--model` to use the model that made the recorded call; pass `--model
58
+ <ref>` only for a second opinion.
31
59
 
32
60
  ## The loop
33
61
 
@@ -39,7 +67,8 @@ zen inspect graph --dir <run dir>
39
67
  zen inspect node n13 n17..n19 --dir <run dir>
40
68
 
41
69
  # 3. only if reading them did not settle it, ask the model itself
42
- zen inspect ask n17 "why run python -c when the skill says npm test?" --dir <run dir>
70
+ # (.tmp/ask/<run-id>/n17-tests.md: "Why run python -c when the skill says npm test?")
71
+ zen inspect ask n17 --question-file .tmp/ask/<run-id>/n17-tests.md --dir <run dir>
43
72
  ```
44
73
 
45
74
  That is the whole method. Never start by opening nodes - without the header
@@ -48,26 +77,26 @@ at a time is the failure the graph exists to prevent.
48
77
 
49
78
  ### Naming the run
50
79
 
51
- | You have | Use |
52
- | ----------------------- | ------------------------------------------------------ |
53
- | a run directory | `--dir <dir>` - the handle a program holds |
54
- | `zen run --json` output | `--dir "$(… \| jq -r .run.dir)"` |
55
- | a run id | `zen inspect graph <run-id>` or `--run <id>` |
56
- | nothing | omit everything: the newest run that actually recorded |
57
- | a session | `--session <id>`, listed by `zen list --sessions` |
80
+ | You have | Use |
81
+ | ----------------------- | ------------------------------------------------- |
82
+ | a run directory | `--dir <dir>` - the handle a program holds |
83
+ | `zen run --json` output | `--dir "$(… \| jq -r .run.dir)"` |
84
+ | a run id | `zen inspect graph <run-id>` or `--run <id>` |
85
+ | a session | `--session <id>`, listed by `zen list --sessions` |
86
+
87
+ Always identify the run. Prefer `--dir`, because `zen run --json` returns it
88
+ without requiring the caller to reconstruct project, session and run ids. If
89
+ the task supplies no run handle, obtain one before inspecting; do not rely on
90
+ the newest run implicitly.
58
91
 
59
92
  **`node` has no room for a run.** Every positional it takes is a node id, so
60
93
  name the run with `--dir`, `--run` or `--session`. `zen inspect node <run-id> n13`
61
- reads the run id as an id and fails. `ask` is the same: one node id, then the
62
- question.
94
+ reads the run id as an id and fails. Explicit `ask` arguments are the same: one
95
+ node id, then the question.
63
96
 
64
97
  For `graph` the positional is a run id unless it contains a `/`, in which case
65
98
  it is a directory - a run id is a stamp and never has a separator.
66
99
 
67
- With nothing to ask on - a script, `--json`, an agent - `zen inspect` takes the
68
- newest run of the newest session **that recorded one**. A session exists before
69
- its first run, so the literally newest session is routinely empty.
70
-
71
100
  ### Reading it cheaply
72
101
 
73
102
  `--no-style` drops the colour statements and `--no-timing` drops the clock;
@@ -121,6 +150,8 @@ diagram would make you count by eye.
121
150
  | `dir` | the run directory | paste into `--dir`, no reconstruction needed |
122
151
  | `workspace` | the files the run worked on | where to go and check what actually changed |
123
152
  | `memory` | the memory graph the run read | absent when the run read none |
153
+ | | recall · search · grep · load · commit, zeros kept | `commit 0` is nothing saved, whatever the answer says |
154
+ | | `nothing committed after N workspace file writes` | a script or file that worked and was not kept |
124
155
  | `agent` | the agent it ended on · the one it started as | two different names means a hand-off happened |
125
156
  | `phase` | `done`, or the phase and the error | an error here is the verdict; the graph is the story |
126
157
  | `nodes` | total · llm · tool calls · forks | the shape and the size of what follows |
@@ -247,9 +278,22 @@ zen inspect node n11 --part thinking --part text --dir <run dir>
247
278
  zen inspect node n11 --full --dir <run dir>
248
279
  ```
249
280
 
281
+ An `llm_call` carries two more parts read out of its request, held back the
282
+ same way: `tools`, the tool names that call was offered, one per line, and
283
+ `messages`, the conversation it saw, one clipped line per message with its
284
+ tool calls under it. They answer "was the tool offered" and "what had it seen"
285
+ without opening the request. For the request itself as JSON, `--raw` prints
286
+ one part of one node with no framing, ready for `jq`:
287
+
288
+ ```sh
289
+ zen inspect node n11 --part tools --dir <run dir>
290
+ zen inspect node n11 --part request --raw --dir <run dir> | jq '.messages'
291
+ ```
292
+
250
293
  `--part` is repeatable and matches a **prefix**, so `--part call` catches a part
251
294
  named `call run_command (toolu_01A…)` without your typing the id. A name that
252
- matches nothing is an error listing the parts the node does carry.
295
+ matches nothing is reported in a `#` line; when no name matches at all it is an
296
+ error listing the parts the nodes do carry.
253
297
 
254
298
  ```
255
299
  # zen inspect node · 1/41 nodes of run 20260825-143012-a7f3 · ids from `zen inspect graph`
@@ -304,7 +348,7 @@ bug in the node.
304
348
  ## Asking the model
305
349
 
306
350
  ```sh
307
- zen inspect ask n17 "which instruction made you avoid the test command?" --dir <run dir>
351
+ zen inspect ask n17 --question-file .tmp/ask/<run-id>/n17-tests.md --dir <run dir>
308
352
  ```
309
353
 
310
354
  One `llm_call`, replayed: its recorded system prompt, its messages and its tool
@@ -331,6 +375,10 @@ The questions it is good at are the ones about intent, where the node shows what
331
375
  happened but not why: which of two instructions won, why a skill that was
332
376
  loaded was not followed, why a tool was used the way it was.
333
377
 
378
+ Before writing the question, load skill **zen-inspect-ask**: which node to ask, what
379
+ to rule out first, and how to word a "why did you not..." question so the answer
380
+ quotes the instruction that blocked the better behaviour.
381
+
334
382
  ## Diagnosing
335
383
 
336
384
  Match the symptom to the row of the header, then open the two or three nodes
@@ -0,0 +1,271 @@
1
+ ---
2
+ name: zen-inspect-ask
3
+ description: 'Use when formulating a question for `zen inspect ask` about an `llm_call` node of a recorded Zenera run - especially a "why did you NOT do X" question (why no `memory_search` first, why no `fork` for independent research branches, why no skill, why no test run). Covers choosing the node, ruling out missing tools before asking, wording the counterfactual so the answer quotes the instruction that blocked the better behaviour, and verifying that quote against the recorded request.'
4
+ ---
5
+
6
+ # Asking a run why it did not do the better thing
7
+
8
+ `zen inspect ask` replays one recorded `llm_call` - its system prompt, messages
9
+ and tool schemas, byte for byte - with tool calling off and a preamble that
10
+ permits the model to quote its own instructions. Load **zen-inspect** for the
11
+ mechanics (graph, node, flags). This skill is about the one thing that decides
12
+ whether the call is worth its cost: **the question**.
13
+
14
+ The goal of every question here is the same: **find the sentence in the
15
+ assembled prompt that prevented the good behaviour**, or prove that no sentence
16
+ asked for it. That sentence is what you are about to edit. An answer that does
17
+ not name one is a wasted call.
18
+
19
+ Non-interactive rule, as in zen-inspect: always pass the node, the question and
20
+ the run. The question is always a file (section 3):
21
+
22
+ ```sh
23
+ zen inspect ask <llm-node-id> --question-file <question file> --dir <run-dir>
24
+ ```
25
+
26
+ Each non-interactive call is a **fresh replay**. It does not remember your
27
+ previous question. A follow-up must restate what it builds on.
28
+
29
+ ## 1. Rule out the cheap causes first
30
+
31
+ A "why didn't you" question is only about instructions if the model could have
32
+ done it. Check these from the graph and the node before spending a model call -
33
+ each one is a finding on its own, and asking the model about it produces an
34
+ invented rationale.
35
+
36
+ | Check | How | If it fails, the cause is |
37
+ | -------------------------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------- |
38
+ | The tool was offered on that call | `--part tools` of that call (below) | `agents.yaml` - tool not granted, or depth cap hit |
39
+ | The instruction file was in the prompt | the `system_prompt` label lists files: `fork-instructions.md`, `memory-instructions.md` | missing file, or its `requires:` not met |
40
+ | The skill was loaded | a `load_skills` node naming it, or the skill index in `request` | binding in `agents.yaml` (`skills:`) |
41
+ | Memory was already recalled for it | a `memory_recall` node before the call; `recall 0 nodes` | memory content, not behaviour |
42
+ | The context still held what it needed | no `compaction` before the node, or the item is not `hidden by` one | compaction, not instructions |
43
+
44
+ ```sh
45
+ zen inspect node n9 --part tools --dir <run-dir> | grep -xE 'fork|memory_search|memory_grep'
46
+ ```
47
+
48
+ Only when every row passes is the question "which instruction stopped you".
49
+
50
+ ## 2. Pick the node where the decision was made
51
+
52
+ The replay ends at the chosen node: the model sees everything up to and
53
+ including that call's own answer, and **nothing after it**. So ask the call that
54
+ made the choice, not the one where the consequence showed up.
55
+
56
+ | Missing behaviour | Ask the `llm_call` that... |
57
+ | ------------------------------- | ----------------------------------------------------------------------------------- |
58
+ | never searched memory | issued the first tool call of the task (usually the first `llm` after `user input`) |
59
+ | ran independent work in series | issued the **first** of the sequential calls - it already had the whole plan |
60
+ | never loaded / followed a skill | chose the substitute action (the `python -c`, the hand-rolled grep) |
61
+ | handed off too early | carries `calls transfer_to_<name>` |
62
+ | gave up / answered too early | the last `llm` before `final output` |
63
+ | repeated a failed call | the one right after the first `ERROR` result |
64
+
65
+ If the choice repeated (four serial searches), ask **once**, not per step. Ask
66
+ the first call when the question is why it started that way - it already had
67
+ the whole plan. Ask the last call of the sequence when the question is about
68
+ the sequence as a whole - its replay holds every step. Never ask a middle one:
69
+ that gets "I was continuing the pattern I had started", which names no
70
+ instruction.
71
+
72
+ ## 3. Formulate the question
73
+
74
+ ### What the replayed model can see
75
+
76
+ The model you are asking sees **only its own raw context** at that call: the
77
+ system prompt, the messages up to that point, the tool descriptions, and the
78
+ answer it gave - its text and its tool calls. That is all. So:
79
+
80
+ - **No node ids, no graph words.** `n7`, `llm_call`, `tool_result`, "branch
81
+ n12" are your index, not its world. Name what it did by its content: "you
82
+ ran `grep -rn invoice /workspace/src`", "your first tool call was
83
+ `read_file` on `src/export.ts`".
84
+ - **Refer to earlier steps by what they were**, as it saw them in its
85
+ messages: "after `memory_search` returned the export node", "after the
86
+ third `run_command` failed with exit code 1".
87
+ - **Describe anything after the call yourself, in plain words.** The replay
88
+ ends at that call; it cannot see what followed. "You then searched three
89
+ more topics one after another" is something it can only learn from you.
90
+
91
+ ### What the preamble already does
92
+
93
+ `ask` puts a preamble in front of the replayed system prompt, and it already
94
+ makes the model do the following:
95
+
96
+ - cite every reason as `[<kind>: <name> › <heading or parameter>] "<verbatim quote>"`,
97
+ where kind is system prompt, skill, tool description or message
98
+ - trace the decision: the options it could see, which one it took, and which
99
+ text tipped it
100
+ - say which instruction it followed, which it missed, which two conflicted, and
101
+ any exception it judged to apply
102
+ - write "no instruction — my own default" instead of making up a source
103
+ - use the answer format the question asks for
104
+
105
+ **Do not restate any of that in the question.** Asking again for verbatim
106
+ quotes or sources adds a second, differently worded copy of the rule, and the
107
+ model follows whichever it read last.
108
+
109
+ ### The three parts
110
+
111
+ The question supplies only what the preamble cannot know. Leave a part out and
112
+ the answer drifts to a generic apology.
113
+
114
+ 1. **What it did, by content.** The action as it appears in its own answer,
115
+ stated as a fact, not an accusation.
116
+ 2. **Why not the better action - asked directly.** "Why didn't you use
117
+ `memory_search` to look up the invoice export first?" Name the action
118
+ concretely - the tool as it appears in its tool list, and the arguments or
119
+ branches it could have used - and say it was available. Never ask "did you
120
+ consider...": its own answer already shows it did not take that path, and
121
+ the question invites a yes that explains nothing.
122
+ 3. **A fixed answer shape.** So answers can be compared across calls and
123
+ runs, and so an answer without a citation is visibly empty. The shape uses
124
+ the preamble's citation form.
125
+
126
+ Write the question to a file with your file-editing tool, then hand `zen` the
127
+ file. The shell never parses the question, so quotes, apostrophes, backticks and
128
+ `$` arrive as written. End the file with this shape, verbatim:
129
+
130
+ ```text
131
+ <the question>
132
+
133
+ Answer in this shape:
134
+ options: <what you could see at that point, and which one you took>
135
+ steered-by: [<kind>: <name> › <heading or parameter>] "<quote>" (one per line, or: no instruction — my own default)
136
+ should-have-applied: [<kind>: <name> › <heading or parameter>] "<quote>" (or: none found)
137
+ exception: [<kind>: <name> › <heading or parameter>] "<quote>" (or: none)
138
+ conflict: <the two citations that pulled in different directions, or: none>
139
+ missing: <the sentence that, added where, would have made you do it>
140
+ ```
141
+
142
+ ```sh
143
+ zen inspect ask n9 --question-file .tmp/ask/<run-id>/n9-memory.md --dir <run-dir>
144
+ ```
145
+
146
+ - One file per question, at `.tmp/ask/<run-id>/<node>-<topic>.md`. `.tmp/` is
147
+ the project's git-ignored scratch. A tuning loop's brief names its own `ask/`
148
+ folder instead: use that one.
149
+ - `--question-file` is the only way the question reaches `zen`. Never a quoted
150
+ argument, a heredoc, `$(cat ...)`, or a Python or Node script around `zen`.
151
+ - A retry (section 5, step 1) or a second opinion (step 4) reuses the same
152
+ file: add `--model <ref>` and change nothing else.
153
+
154
+ ### Wording rules
155
+
156
+ - **Ask why not, directly.** "Why didn't you fork the four lookups?" - not
157
+ "did you consider forking?", not "would forking have been better?".
158
+ - **Do not lead.** "Didn't fork-instructions tell you to parallelise?" gets
159
+ "yes, I should have" - agreement, not a cause. Name the action, never the
160
+ instruction you suspect.
161
+ - **Do not ask what it should have done.** That produces a lecture on best
162
+ practice written from general knowledge, not from its prompt.
163
+ - **One behaviour per question.** Memory and forking in one question get one
164
+ shallow answer each. Ask twice.
165
+ - **Name the alternative as an action, not a virtue.** "Why didn't you
166
+ `memory_search` for 'invoice export endpoint'?" - not "why weren't you more
167
+ efficient?".
168
+ - **Keep the exception line.** A rule with an escape hatch ("unless...", "only
169
+ when...", "for simple tasks...") is the most common blocker. The preamble asks
170
+ for exceptions, but a model will not volunteer that it granted itself one
171
+ unless an empty `exception:` line is waiting for it.
172
+
173
+ ## 4. Templates
174
+
175
+ The question bodies below replace `<the question>` in the file of section 3.
176
+ Replace every command, tool argument and topic with the run's own. None of them
177
+ mentions a node id: the id goes on the command line, never in the question.
178
+
179
+ ### Did not use memory
180
+
181
+ ```text
182
+ Your first step for this task was run_command `grep -rn 'export' /workspace/src`.
183
+ Why didn't you use memory_search or memory_grep to look up the invoice export
184
+ endpoint first? Both are in your tool list, and an earlier run may already have
185
+ worked it out. What in your instructions, or missing from them, made the
186
+ workspace the first place to look?
187
+ ```
188
+
189
+ ### Recalled memory, then redid the work
190
+
191
+ ```text
192
+ memory_search returned a node describing the invoice export endpoint and where
193
+ it is implemented. Your next step was to grep the workspace for the same
194
+ endpoint. Why didn't you use what memory returned, or memory_load that node to
195
+ read it whole? What made the recalled text not enough?
196
+ ```
197
+
198
+ ### Did not save what it learned
199
+
200
+ ```text
201
+ To answer this you read eleven files and ran four commands, and your answer
202
+ names facts a later run would need again. memory_commit is in your tool list.
203
+ Why didn't you commit what you worked out before answering?
204
+ ```
205
+
206
+ ### Did not fork independent research
207
+
208
+ ```text
209
+ From this point you researched four things one after another: (A) the auth
210
+ flow, (B) the billing schema, (C) the retry policy, (D) the webhook format.
211
+ None of the later lookups used an earlier result. Why didn't you call fork once
212
+ with a branch for each of A-D? fork is in your tool list.
213
+ ```
214
+
215
+ ### Did not follow a loaded skill
216
+
217
+ ```text
218
+ You called run_command with `python3 -c` to check the output. The skill
219
+ run-tests is in your context and says to run `npm test`. Why didn't you run
220
+ `npm test`? What made the inline script look acceptable here?
221
+ ```
222
+
223
+ ### Misused a tool
224
+
225
+ ```text
226
+ You called memory_commit three times with a `refs` array naming nodes from an
227
+ earlier commit, and each call failed. Why did you expect refs to reach nodes
228
+ committed earlier? Which words in the memory_commit description led you there,
229
+ or what was missing from it?
230
+ ```
231
+
232
+ The same skeleton covers any missing behaviour: **what it did, by content ->
233
+ why not the better action, available -> shape.** The preamble does the rest.
234
+
235
+ ## 5. Verify the answer
236
+
237
+ The answer is testimony. It is useful because it points at a sentence; it is
238
+ only a finding once the sentence is confirmed.
239
+
240
+ 1. **Grep each quote in the recorded request** - the text between the double
241
+ quotes of each `[...] "..."` citation.
242
+ ```sh
243
+ zen inspect node n9 --part request --dir <run-dir> | grep -F 'Do not fork a sequence'
244
+ ```
245
+ A quote that is not there is invented - discard the answer, not just the
246
+ quote. Ask once more; if it invents again, ask another model (step 4).
247
+ 2. **Find every copy.** The blocker often exists twice - once in a house rule,
248
+ once in a skill with a softer tail. Grep the whole request for a distinctive
249
+ phrase of it, then grep the project's `agents/` tree for the file to edit.
250
+ 3. **Check it is the project's file.** `fork-instructions.md`,
251
+ `memory-instructions.md`, `tools-instructions.md` are zen's own copies; load
252
+ **zen-instructions** before changing where that rule lives.
253
+ 4. **Second opinion when the self-report is thin.** The model that made the
254
+ call rationalises; another model reading the same replay often names the
255
+ conflict more plainly: `--model <ref>`. Ask the identical question: the same
256
+ question file.
257
+ 5. **Reproduce.** After the edit, rerun the case and check the graph: the
258
+ `tools` header row shows `fork x1` or `memory_search x1` where it did not
259
+ before. The answer predicted a fix; the graph confirms it.
260
+
261
+ ## 6. Reading the answer
262
+
263
+ | Answer says | Means | Fix |
264
+ | ---------------------------------------------------------- | ------------------------------------------- | ----------------------------------------------------------------- |
265
+ | `should-have-applied: none found` | nothing asked for it | add a mechanical rule at the point of decision |
266
+ | `steered-by: no instruction — my own default` | the model's habit filled a gap | add a mechanical rule at the point of decision |
267
+ | a rule quoted as `should-have-applied`, nothing against it | the rule is there but not reachable in time | move it earlier, or into the skill loaded for that task |
268
+ | a `steered-by` quote that argues against the better action | an instruction argued against it | narrow or remove the blocker, do not add a counter-rule beside it |
269
+ | `conflict:` names two rules | two instructions disagree | delete one; two copies of a rule is how drift starts |
270
+ | an exception is quoted as applying | a self-judged escape hatch | remove the hatch or make its condition checkable |
271
+ | no citation at all, general reasoning only | the question was too open, or led | rewrite with the three parts; do not act on it |
@@ -185,7 +185,7 @@ open something, and a running agent sees four: `/workspace`, `/assets`,
185
185
 
186
186
  It reads `agents/*instructions.md` and exits `1` on any candidate.
187
187
  `agents/memory-instructions.md` is exempt: it is worked examples by design, and
188
- `check-instructions.sh` is the check it actually needs.
188
+ `rules.stale` is the check it actually needs.
189
189
 
190
190
  ## What `zen check` reports
191
191
 
@@ -210,17 +210,9 @@ is quietly a project whose agents were never told how to call a tool. And
210
210
  `rules.unreached` deliberately never fires for ours, because they land in every
211
211
  project whether the capability is used or not.
212
212
 
213
- The memory copy has a check of its own, byte for byte, because the two files
214
- drift by trailing whitespace inside tables and that is invisible on screen:
215
-
216
- ```sh
217
- .github/skills/zen-memory/scripts/check-instructions.sh # the verdict
218
- .github/skills/zen-memory/scripts/check-instructions.sh diff # every differing line
219
- .github/skills/zen-memory/scripts/check-instructions.sh fix # copy the reference over
220
- ```
221
-
222
- Never read the two against each other by eye, and never paraphrase the reference
223
- into prose of your own.
213
+ `rules.stale` compares bytes, so it catches the usual drift - trailing
214
+ whitespace inside a table, invisible on screen. Never compare one of ours
215
+ against anything by eye, and never paraphrase one into prose of your own.
224
216
 
225
217
  ## Related
226
218