@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
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: zen-code-python
3
+ description: Code an agent writes must be a reusable tool that can be remembered and re-run, never a one-off. Holds the coding rules (`references/code_python.md`) and decides where they go in the target project - a section of a dedicated code agent's system prompt, or a coding skill for generic agents that sometimes run code - how to adapt them, and what a prompt or skill for a code-writing agent must never say. Load before writing, editing or reviewing any agent prompt, skill or house rule for an agent that writes or runs code - any agent holding `sandbox:*` or `run_command` - and before shipping a script inside a skill.
4
+ ---
5
+
6
+ # Code an agent writes is a tool
7
+
8
+ A script an agent writes is worth more than the answer it printed. Written
9
+ generically - every changing value an argument, a name that says what it does -
10
+ it can be committed to memory as a `file` node and found again by the next
11
+ similar question, which runs it instead of writing it again. Written as a
12
+ one-off - this customer's id, this month, this path, as literals - it can only
13
+ ever answer the question that produced it, and memory fills up with near-copies
14
+ that never fold together.
15
+
16
+ Nothing in the runtime enforces this, and `zen check` does not report it. The
17
+ rules reach an agent only through what you write into the target project.
18
+
19
+ ## The reference
20
+
21
+ `references/code_python.md` is the rule set, in wording that has been tested on
22
+ models. It is a source to build from, not a file to copy. Start from its
23
+ sentences - copying and then editing them works; rewriting them from scratch in
24
+ your own words loses the mechanical phrasing that makes them obeyed.
25
+
26
+ **Keep in substance, and never soften:**
27
+
28
+ - every value that would change for the next similar question is a named
29
+ argument, never a literal
30
+ - the file is named for what it does, and describes itself through `--help`
31
+ - the result goes to stdout, a produced file to an `--output` path
32
+ - the script is written to a file and the file is run - no `python -c`, no
33
+ heredoc
34
+ - before using the output, the script is checked against a different question
35
+ of the same kind
36
+ - with memory: search before writing, commit the working script after
37
+
38
+ **Adapt to the project:**
39
+
40
+ - the interpreter and language, if the sandbox image runs something other than
41
+ Python
42
+ - where scripts are written - `/workspace/scripts/` unless the project already
43
+ has a place
44
+ - libraries the image carries and the agent should prefer, and the output
45
+ format the project expects (JSON, CSV, a table)
46
+ - an example invocation from this project's own domain, values passed as
47
+ arguments
48
+ - the memory steps: keep them when the agent holds `memory_search` /
49
+ `memory_commit`, drop them when it never will. In a skill several agents may
50
+ load, keep them gated on the tool, as the reference does
51
+
52
+ ## Decide where the rules go
53
+
54
+ List the agents that hold `sandbox:*` or `run_command`, and read each one's
55
+ prompt for what its job is. Then:
56
+
57
+ | The project has | Write |
58
+ | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
59
+ | A **dedicated code agent** - a runner, an executor, an analyst whose answers are scripts | A `## Writing code` section in that agent's `agents/prompts/<name>.md` |
60
+ | **No dedicated code agent** - generic agents that sometimes run code | A coding skill, `agents/skills/code_python/SKILL.md` |
61
+ | Both | The prompt section, and the generic agents hand the code work to that agent rather than writing it - see below |
62
+ | No agent that writes or runs code | Nothing |
63
+
64
+ **A dedicated code agent gets the rules in its system prompt.** It writes code
65
+ on nearly every turn, so the rules are part of its job description: a skill
66
+ would cost a load on every case, and preloading one is the same text in the
67
+ prefix with an extra file to keep in step. Put the section after the agent's
68
+ identity and procedure, before its prohibitions.
69
+
70
+ **Generic agents get a skill.** Most of their turns write no code, so the rules
71
+ should cost nothing until one does. The `description` is the routing key - name
72
+ the condition, not the topic:
73
+
74
+ ```yaml
75
+ description: Before writing, changing or running any Python script - how to write it as a reusable tool rather than a one-off.
76
+ ```
77
+
78
+ Leave it in the agent's index; do not preload it. If `allow` is used, add
79
+ `code_python` to it for every agent holding `sandbox:*`.
80
+
81
+ **With both, one copy.** Generic agents that can reach a code agent should
82
+ `fork:` to it for an answer, or hand off to it, rather than writing code
83
+ themselves - then the rules have one home and the scripts one author. Grant
84
+ them no `sandbox:*` for code work. If they must keep a shell of their own, they
85
+ need the skill too, and its rules are the same sentences as the prompt section:
86
+ a second wording is how one copy ends up softer than the other, and the softer
87
+ one is the one obeyed.
88
+
89
+ Run `zen check` after any change to `agents.yaml` or a skill.
90
+
91
+ ## Writing anything else around it
92
+
93
+ - **One home per agent.** Once an agent has the rules - in its prompt or in its
94
+ skill - no house rule, other skill or prompt line restates them. A prompt that
95
+ needs to point at the skill names it: _"Follow `code_python` for every
96
+ script."_
97
+ - **Never add an exemption.** _"Hard-coding is fine for a quick one-off check"_
98
+ is a permission: every probe is a one-off by construction, so the exception
99
+ admits exactly what the rule forbids. The same goes for `python -c`.
100
+ - **Never show a one-off as an example.** A prompt or skill that shows
101
+ `python -c "..."`, or a script with a literal id, date or path in its body,
102
+ teaches the shape the rule forbids. Every example invocation passes its values
103
+ as named arguments:
104
+ `python /workspace/scripts/list_overdue_invoices.py --customer-id 42`.
105
+ - **Scripts shipped inside a skill** (`agents/skills/<name>/scripts/`, §3.4.1 of
106
+ the copilot instructions) follow the same rules: named arguments, a `--help`,
107
+ the result on stdout, an `--output` path under `/workspace` for any file,
108
+ since `/skills` is read-only.
109
+ - **Memory is what makes the reuse happen.** A code-writing agent without
110
+ memory still writes reusable scripts, but cannot find them in a later session.
111
+ Say so if the project expects reuse and that agent has no `memory:`.
112
+
113
+ ## Review
114
+
115
+ - [ ] Every agent that writes or runs code has the rules - a prompt section for
116
+ a dedicated code agent, the `code_python` skill reachable for the others
117
+ - [ ] Every rule under _Keep in substance_ is there, none softened, and the
118
+ memory steps match whether the agent holds the memory tools
119
+ - [ ] Generic agents beside a dedicated code agent hand code work to it, or
120
+ carry the same wording - not a second paraphrase
121
+ - [ ] No other prompt, skill or house rule restates the rules, adds an
122
+ exemption, or shows `python -c` or a script with literal values
123
+ - [ ] Every script shipped in a skill takes its values as named arguments
@@ -0,0 +1,48 @@
1
+ # Writing Python scripts
2
+
3
+ Every script you write is a tool for the next question like this one, not an
4
+ answer to this one. Write it once, generically, so it can be remembered and run
5
+ again unchanged.
6
+
7
+ ## Before writing
8
+
9
+ If you hold `memory_search`, search for a script that already answers this kind
10
+ of question, and load the best match with `memory_load`. If it fits, run it with
11
+ this question's arguments and write nothing new. If it needs a change, change
12
+ it the way the rest of this skill says - usually by adding an argument - and
13
+ commit the new version as superseding the old one.
14
+
15
+ ## Writing
16
+
17
+ 1. **Solve the kind of question, not this one.** Anything that would differ the
18
+ next time - inputs, ids, names, paths, urls, dates and date ranges, filters,
19
+ thresholds, limits, the output path - is a named `argparse` argument such as
20
+ `--resource-id`, never a literal in the code. A default is allowed only for a
21
+ value that is the same for every question.
22
+ 2. **Name the file for what it does**, verb first: `list_overdue_invoices.py`,
23
+ `compare_quarterly_revenue.py`. Never `script.py`, `test.py`, `tmp.py` or a
24
+ name that only makes sense in this conversation.
25
+ 3. **Describe it.** Line one is a docstring saying what question it answers. The
26
+ same sentence is the `argparse` description, and every argument has a
27
+ `help=`, so `--help` is all a later reader needs.
28
+ 4. **Print the result to stdout** and anything else to stderr. Exit non-zero
29
+ with a message saying what failed when it cannot answer. A file it produces
30
+ goes to the path given by `--output`.
31
+ 5. **Take credentials from environment variables by name.** Never write a key,
32
+ token or password into the code or an argument default.
33
+ 6. **Use only what the sandbox image already has.** Do not `pip install` from
34
+ the script or before running it.
35
+ 7. **Write it to a file and run the file**:
36
+ `python /workspace/scripts/<name>.py --resource-id 42`. Never run Python
37
+ with `python -c` or a heredoc.
38
+
39
+ ## Before using its output
40
+
41
+ - Run it, and fix the script - not the output - when it fails or prints
42
+ something wrong.
43
+ - Read your own code against a different question of the same kind. If
44
+ answering it would mean editing the script rather than passing other
45
+ arguments, a value is still hard-coded: make it an argument and run again.
46
+ - If you hold `memory_commit`, commit the working script as a `file` node. Its
47
+ text says what kind of question it answers and names its arguments, so that a
48
+ later search for a similar question finds it.
@@ -0,0 +1,253 @@
1
+ ---
2
+ name: zen-dataset
3
+ description: Keep a project's evaluation dataset in `dataset/` with `zen meta dataset` - every case read from its sources with a class, a complexity, tags, a verbatim rubric and an anchor to the section it came from. Covers extracting a training set of any shape into a proposal, applying it as a revision, finding which cases their sources moved under (drift) and re-reading only those sections, settling gone and uncovered sections, overriding a field by hand, leaving notes and verdicts on a case, reading a case's history and the sessions that touched it, and drawing samples by criteria (class, complexity, tag, rubric, revision, verdict, note kind, source, text) stratified, weighted and seeded. Load before building or refreshing a dataset, before running /dataset, before choosing which cases to run, and before writing a note or verdict on a case.
4
+ ---
5
+
6
+ # The dataset
7
+
8
+ A dataset is the project's set of real queries, each with what it should be
9
+ judged by. It lives in `dataset/` at the project root, it is committed, and it
10
+ outlives any one tuning. **Only `zen meta dataset` writes to it.** A hand edit
11
+ skips the history, the revision, the session stamp and the lock, and the next
12
+ drift check will not see it.
13
+
14
+ Reading a source and deciding what is a case is your work. Everything after
15
+ that - what changed, which revision, which cases restart, what to run next - is
16
+ the command's.
17
+
18
+ ## What is stored
19
+
20
+ ```
21
+ dataset/
22
+ manifest.json revision, a hash per source file, the ignored sections
23
+ revisions.jsonl one line per revision: added, updated, retired, restarted
24
+ cases/<id>.json each case as it is now
25
+ log/<id>.jsonl each case's history: every change, every note, who made it
26
+ ```
27
+
28
+ A case:
29
+
30
+ ```json
31
+ {
32
+ "id": "planning-organize-day",
33
+ "rev": 3,
34
+ "status": "active",
35
+ "class": "planning",
36
+ "complexity": "complex",
37
+ "tags": ["calendar", "mail"],
38
+ "input": "organize my day",
39
+ "rubric": [
40
+ { "id": "r1", "text": "calls api /mail/list" },
41
+ { "id": "r2", "text": "proposes a schedule, does not just list both" }
42
+ ],
43
+ "expected": "A time-ordered plan naming the two conflicting meetings.",
44
+ "source": {
45
+ "file": "SPECIFICATION.md",
46
+ "anchor": { "heading": ["Examples", "Query: organize my day"] }
47
+ }
48
+ }
49
+ ```
50
+
51
+ - **`rev`** is the dataset revision that last changed the case. A run that
52
+ records `{id, rev}` can always be read back against the rubric it ran under:
53
+ `zen meta dataset show <id>@<rev>`.
54
+ - **Rubric ids** stay with their line. An unchanged line keeps its `r<n>`; a
55
+ new line gets a new one; a note that says `r2 failed` keeps meaning the same
56
+ line.
57
+ - **Nothing is deleted.** A removed case is `retired`: out of every sample,
58
+ still readable, its id never reused.
59
+
60
+ ## Extracting cases
61
+
62
+ Read the source yourself and write the structure out; do not write a parser.
63
+ Large sources are read in parts, and the count is checked against the source at
64
+ the end.
65
+
66
+ | In the source | In the case |
67
+ | ---------------------------------------------------------------- | -------------------------------------------------------------------- |
68
+ | A heading like `## Query:` and a quoted string | One case, `input` is the string |
69
+ | A bullet list under `### Rubric:` | `rubric` - **verbatim**, one entry per bullet |
70
+ | An embedded image, a `![](...)` link, an audio or PDF attachment | A media part in `input`, path relative to the proposal file |
71
+ | A paragraph of context before the query | `notes`, not `input` - unless the agent is meant to see it |
72
+ | The expected answer | `expected`, one string; it is context for grading, not a diff target |
73
+ | Nothing but a query | A case with no `rubric` |
74
+
75
+ - **The rubric is the source's words.** A paraphrased rubric grades the
76
+ paraphrase. A wrong rubric is fixed in the source and re-read; when the
77
+ source is not yours to edit, `update --rubric-edit ... --override` and say why.
78
+ - **Class** is a distinction the source already makes - a section, an agent,
79
+ an API, a task type. Do not invent a taxonomy.
80
+ - **Complexity** rates the trajectory the query demands, not the sentence:
81
+
82
+ | Level | What it means |
83
+ | --------- | --------------------------------------------------------------------------- |
84
+ | `simple` | One tool call or none; one agent; the answer is a lookup or a restatement |
85
+ | `medium` | Several calls that depend on each other, or one delegation, or one artefact |
86
+ | `complex` | Fan-out, multi-agent, ambiguity to resolve, or a plan that can go wrong |
87
+
88
+ - **Tags** are free words for what cuts across classes - `mail`, `pagination`,
89
+ `impossible`. Use the source's own words; a tag on one case is noise.
90
+ - **Ids** are letters, digits, dot, dash and underscore, `class-short-slug`,
91
+ and **stable**: a case read again from the same section keeps its id. A new
92
+ id for an old case restarts it and orphans its history.
93
+ - **`input` is exactly what `zen run batch` accepts**: a string, or a list of
94
+ parts - a string, `{ "text": "…" }`, or `{ "image" | "audio" | "video" | "file": "<path or url>" }`.
95
+
96
+ ### Anchors
97
+
98
+ Every case read from a file names the section it came from, so the command can
99
+ find that section again with no model involved:
100
+
101
+ | Source | Anchor | The section |
102
+ | ---------------------- | ---------------------------------------- | ------------------------------------------------- |
103
+ | Markdown | `{ "heading": "Examples > Query: one" }` | from the heading to the next one at its level |
104
+ | JSON or YAML | `{ "pointer": "/cases/3" }` | that value; key order and formatting do not count |
105
+ | Anything else, or none | no `anchor` | the whole file |
106
+
107
+ A heading path needs only its last name while that is unique in the file; add
108
+ a parent to tell two apart. Headings inside code fences are not headings. An
109
+ anchor that does not resolve to exactly one section is refused at apply.
110
+
111
+ ### The proposal
112
+
113
+ Write the cases to a scratch file - `.tmp/dataset/proposal.json` - as
114
+ `{ "cases": [ … ] }`. Media paths in it resolve against that file. Then:
115
+
116
+ ```sh
117
+ zen meta dataset apply .tmp/dataset/proposal.json --dry-run
118
+ zen meta dataset apply .tmp/dataset/proposal.json --why "first extraction of SPECIFICATION.md"
119
+ ```
120
+
121
+ A whole proposal **retires every active case it does not name**. A refresh of
122
+ a few sections is `--partial`: only the cases it names are touched. Read the
123
+ dry run before writing - an unexpected `retired` or an id you did not mean to
124
+ change is caught there and nowhere else.
125
+
126
+ The old `finetune/dataset.json` (`cases` or `samples`) applies as it stands.
127
+
128
+ ## When the sources move
129
+
130
+ ```sh
131
+ zen meta dataset drift
132
+ ```
133
+
134
+ A source file whose hash is unchanged is not opened. In a file that moved, each
135
+ case's own section is compared, so a typo three sections away restarts nothing.
136
+
137
+ | State | Means | Do |
138
+ | ----------- | ----------------------------------------------------- | --------------------------------------------------------------------- |
139
+ | `changed` | the case's section text differs | re-read that section; put the case in a `--partial` proposal |
140
+ | `gone` | its anchor no longer finds exactly one section | `retire` it, or `reanchor` it if the section was only renamed |
141
+ | `uncovered` | a section at the cases' level that no case comes from | new cases in the proposal, or `ignore <file> --heading "…" --why "…"` |
142
+ | `unsettled` | a file never recorded, because a section is uncovered | settle its uncovered sections |
143
+
144
+ Re-reading a `changed` section and proposing the same case is fine: if what it
145
+ asks, expects and is judged by did not change, nothing is revised - only its
146
+ stored hash moves.
147
+
148
+ **What restarts a case.** A change to `input`, `rubric` or `expected` - the
149
+ question or how it is judged - lists the case under `restarted` in that
150
+ revision; results from its earlier revision are about a different question. A
151
+ change to `class`, `complexity`, `tags`, `notes` or `source` revises the case
152
+ without restarting it.
153
+
154
+ ## By hand
155
+
156
+ ```sh
157
+ zen meta dataset update <id> --set class=search --set complexity=medium --why "…"
158
+ zen meta dataset update <id> --rubric-edit r2="proposes a schedule" --override --why "…"
159
+ zen meta dataset update <id> --rubric-add "says when it is impossible" --rubric-drop r3 --why "…"
160
+ zen meta dataset update <id> --tag-add impossible --why "…"
161
+ zen meta dataset retire <id>... --why "…" # restore <id>... to undo
162
+ zen meta dataset reanchor <id> --heading "Examples > Query: plan" --why "section renamed"
163
+ ```
164
+
165
+ `--set <field>=` with nothing after the `=` clears that field. `--override` keeps the
166
+ change through every later re-extraction; without it the next apply of that
167
+ section writes the source's version back.
168
+
169
+ ## Notes, verdicts, history
170
+
171
+ ```sh
172
+ zen meta dataset note <id>... -m "…" [--kind graded|analyze|difficult|rubric-suspect|observation] \
173
+ [--run <run>] [--verdict right|wrong|void] [--rubric r1=pass,r2=fail]
174
+ zen meta dataset log [id...]
175
+ ```
176
+
177
+ A note is about the case's **current** revision and is recorded with it; after
178
+ the case is revised, the note stays in its history but stops counting. A note
179
+ with a verdict defaults to `graded`. Leave a `rubric-suspect` note when a case
180
+ fails for a reason the rubric cannot be right about - the dataset prompt lists
181
+ them until someone fixes the source.
182
+
183
+ Every change and note records who made it: the `zen meta` session, the prompt
184
+ it ran (`/dataset`, `/analyze`, …) and the host. `log` prints
185
+ `resume: zen meta resume <project> <session>` for every session this machine
186
+ still holds.
187
+
188
+ ## Drawing a sample
189
+
190
+ ```sh
191
+ zen meta dataset sample [filters] [-n <count>] [--seed <n>] [--by <fields>] \
192
+ [--weight <stratum>=<w>] [--order <keys>] [--format ids|batch|cases|json] [-o <file>]
193
+ ```
194
+
195
+ **Filters** - all must hold; a repeated flag means any of its values:
196
+
197
+ | Flag | Keeps |
198
+ | ---------------------------------------- | ----------------------------------------------------------- |
199
+ | `--class`, `--complexity`, `--tag` | those values (`unclassified`, `unrated` for none) |
200
+ | `--status active\|retired\|all` | default `active` |
201
+ | `--rubric yes\|no`, `--expected yes\|no` | cases with or without one |
202
+ | `--id <glob>`, `--exclude <glob>` | ids matching, ids not matching |
203
+ | `--ids-from <file>` | ids listed - plain, or json with `ids`, `batch`, `cases` |
204
+ | `--changed-since <rev>` | revised after that revision |
205
+ | `--restarted` | restarted by the latest revision (or the `--at` one) |
206
+ | `--at <rev>` | the dataset as it stood then |
207
+ | `--verdict right\|wrong\|void` | the latest verdict on the current revision |
208
+ | `--never-graded` | no verdict on the current revision |
209
+ | `--note <kind>`, `--graded-in <run>` | has a note of that kind, or one from that run |
210
+ | `--source <glob>`, `--anchor <glob>` | read from that file, or that section |
211
+ | `--grep <text>` | input or rubric contains it (`--regex`, `--case-sensitive`) |
212
+
213
+ A value the dataset does not have - a misspelt class - is an error that lists
214
+ the real ones, never an empty sample.
215
+
216
+ **The draw.** Cases are grouped into strata by `--by` (default `class`; also
217
+ `complexity`, `tag`, `source`, `rubric`, `verdict`, several joined by commas,
218
+ or `none`). Inside a stratum they are ordered by `--order` (default
219
+ `rubric,complexity`: graded first, then complex, medium, simple; also
220
+ `verdict` - wrong first, `rev` - newest first, `id`), ties broken by `--seed`.
221
+ Strata take turns, `--weight alpha=2` giving one twice the turns. The whole
222
+ order is laid out before `-n` cuts it, so **a larger `-n` keeps every case a
223
+ smaller one chose**, and the same filters, seed and revision draw the same cases
224
+ on any machine.
225
+
226
+ **Output.** `ids` (default) one per line; `batch` - `{ "batch": [{ id, input }] }`
227
+ for `zen run batch`, **never a rubric**; `cases` - whole cases with rubrics, for
228
+ a grader; `json` - the ids with the criteria, seed, revision and per-stratum
229
+ counts, which is the record that reproduces the sample. Media paths are written
230
+ relative to the `-o` file. The per-stratum table goes to stderr.
231
+
232
+ ```sh
233
+ # a cross-section of 12 graded cases
234
+ zen meta dataset sample --rubric yes -n 12 --format batch -o runs/r1/cases.json
235
+ # everything the latest revision restarted
236
+ zen meta dataset sample --restarted --by none --format batch -o runs/r2/cases.json
237
+ # what is still wrong, worst classes first
238
+ zen meta dataset sample --verdict wrong --order complexity --weight search=2
239
+ # the whole dataset, rubrics included, for another machine
240
+ zen meta dataset export -o dataset.json
241
+ ```
242
+
243
+ `export [id...]` is the same filters with no strata, in id order, as `cases`
244
+ by default.
245
+
246
+ ## Rules
247
+
248
+ - Only `zen meta dataset` writes `dataset/`.
249
+ - Every write says `--why`, in terms of the source: what changed in it, or why
250
+ it is being overridden.
251
+ - Rubrics leave the dataset only through `--format cases` or `export`. Never
252
+ put one in a batch input, a prompt, a skill or the workspace an agent reads.
253
+ - Moving a rubric to match what an agent did is not a fix; it deletes the test.