@zenera/cli 1.1.25 → 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 (96) hide show
  1. package/README.md +13 -1
  2. package/dist/catalog.d.ts +20 -0
  3. package/dist/catalog.js +60 -0
  4. package/dist/commands/index.js +2 -0
  5. package/dist/commands/inspect.d.ts +5 -1
  6. package/dist/commands/inspect.js +54 -14
  7. package/dist/commands/memory.js +28 -3
  8. package/dist/commands/meta.js +24 -5
  9. package/dist/commands/models.js +2 -1
  10. package/dist/commands/sandbox.js +73 -3
  11. package/dist/commands/view.d.ts +8 -0
  12. package/dist/commands/view.js +114 -0
  13. package/dist/engine.d.ts +3 -1
  14. package/dist/engine.js +6 -0
  15. package/dist/eventlog.d.ts +5 -0
  16. package/dist/eventlog.js +25 -1
  17. package/dist/liveness.js +20 -2
  18. package/dist/main.js +0 -0
  19. package/dist/meta/editor.d.ts +1 -1
  20. package/dist/meta/editor.js +4 -21
  21. package/dist/meta/finetune/analyze-brief.d.ts +26 -0
  22. package/dist/meta/finetune/analyze-brief.js +131 -0
  23. package/dist/meta/finetune/apply-brief.d.ts +23 -0
  24. package/dist/meta/finetune/apply-brief.js +247 -0
  25. package/dist/meta/finetune/brief.d.ts +45 -0
  26. package/dist/meta/finetune/brief.js +158 -0
  27. package/dist/meta/finetune/command.d.ts +1 -1
  28. package/dist/meta/finetune/command.js +224 -46
  29. package/dist/meta/finetune/cost.d.ts +46 -0
  30. package/dist/meta/finetune/cost.js +105 -0
  31. package/dist/meta/finetune/dataset/types.d.ts +3 -1
  32. package/dist/meta/finetune/feedback.d.ts +14 -2
  33. package/dist/meta/finetune/feedback.js +22 -3
  34. package/dist/meta/finetune/guard.d.ts +29 -0
  35. package/dist/meta/finetune/guard.js +104 -0
  36. package/dist/meta/finetune/improvements.d.ts +50 -3
  37. package/dist/meta/finetune/improvements.js +290 -33
  38. package/dist/meta/finetune/live.d.ts +17 -7
  39. package/dist/meta/finetune/live.js +56 -10
  40. package/dist/meta/finetune/loop.js +59 -10
  41. package/dist/meta/finetune/recheck.d.ts +58 -0
  42. package/dist/meta/finetune/recheck.js +311 -0
  43. package/dist/meta/finetune/report.d.ts +9 -2
  44. package/dist/meta/finetune/report.js +551 -438
  45. package/dist/meta/finetune/sampler.js +8 -2
  46. package/dist/meta/finetune/train.d.ts +6 -2
  47. package/dist/meta/finetune/train.js +55 -21
  48. package/dist/meta/finetune/tui.d.ts +3 -3
  49. package/dist/meta/finetune/tui.js +37 -12
  50. package/dist/meta/finetune/tuning.d.ts +27 -1
  51. package/dist/meta/finetune/tuning.js +21 -2
  52. package/dist/meta/finetune/usage.d.ts +4 -0
  53. package/dist/meta/finetune/usage.js +35 -0
  54. package/dist/meta/finetune/view.d.ts +9 -0
  55. package/dist/meta/finetune/view.js +27 -0
  56. package/dist/meta/host.d.ts +2 -1
  57. package/dist/meta/host.js +2 -1
  58. package/dist/meta.d.ts +291 -0
  59. package/dist/meta.js +981 -0
  60. package/dist/resources.d.ts +215 -0
  61. package/dist/resources.js +856 -0
  62. package/dist/scaffold.d.ts +3 -4
  63. package/dist/scaffold.js +21 -9
  64. package/dist/trace.d.ts +5 -0
  65. package/dist/trace.js +54 -5
  66. package/dist/tui/app.js +19 -5
  67. package/dist/tui/links.d.ts +27 -0
  68. package/dist/tui/links.js +142 -0
  69. package/dist/tui/models.d.ts +3 -1
  70. package/dist/tui/models.js +65 -7
  71. package/dist/tui/sandbox.d.ts +10 -0
  72. package/dist/tui/sandbox.js +131 -0
  73. package/package.json +3 -2
  74. package/templates/editor/.github/copilot-instructions.md +29 -43
  75. package/templates/editor/.github/prompts/analyze.prompt.md +3 -1
  76. package/templates/editor/.github/prompts/finetune-apply.prompt.md +221 -42
  77. package/templates/editor/.github/prompts/project-review.prompt.md +1 -1
  78. package/templates/editor/.github/skills/zen-analyze-run/SKILL.md +162 -57
  79. package/templates/editor/.github/skills/zen-cli/references/finetune.md +74 -14
  80. package/templates/editor/.github/skills/zen-cli/references/inspect.md +16 -2
  81. package/templates/editor/.github/skills/zen-cli/references/projects.md +4 -6
  82. package/templates/editor/.github/skills/zen-cli/references/sandbox.md +25 -13
  83. package/templates/editor/.github/skills/zen-finetune/SKILL.md +74 -33
  84. package/templates/editor/.github/skills/zen-inspect/SKILL.md +14 -1
  85. package/templates/editor/.github/skills/zen-inspect-ask/SKILL.md +4 -3
  86. package/templates/editor/.github/skills/zen-instructions/SKILL.md +4 -12
  87. package/templates/editor/.github/skills/zen-memory/SKILL.md +64 -39
  88. package/templates/editor/.github/skills/zen-review/SKILL.md +6 -31
  89. package/templates/editor/.github/skills/zen-review/scripts/check-paths.sh +1 -2
  90. package/templates/editor/.github/skills/zen-review/scripts/review.sh +3 -12
  91. package/templates/editor/.github/skills/zen-sandbox/SKILL.md +2 -1
  92. package/templates/editor/.github/skills/zen-spec-sync/SKILL.md +2 -4
  93. package/templates/project/agents/fork-instructions.md +78 -28
  94. package/templates/project/agents/memory-instructions.md +222 -493
  95. package/templates/project/agents/tools-instructions.md +7 -0
  96. package/templates/editor/.github/skills/zen-memory/scripts/check-instructions.sh +0 -116
@@ -0,0 +1,131 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // ---------------------------------------------------------------------------
3
+ // zen sandbox top
4
+ //
5
+ // The resource report, redrawn on a timer. Nothing here measures anything or
6
+ // decides what a figure means: resources.ts samples and lays out, and this
7
+ // file only colours the lines it is handed and owns the keys.
8
+ //
9
+ // The frame is cut to the terminal's height before Ink sees it — a frame
10
+ // taller than the screen scrolls its own top away and every repaint leaves a
11
+ // copy of it behind (see tui/app.tsx).
12
+ // ---------------------------------------------------------------------------
13
+ import { Box, render, Text, useApp, useInput, useStdout } from 'ink';
14
+ import React, { useEffect, useState } from 'react';
15
+ import { layout, SORTS, } from "../resources.js";
16
+ import { resolveTheme } from "./theme.js";
17
+ const message = (err) => (err instanceof Error ? err.message : String(err));
18
+ function styleOf(tone, theme) {
19
+ switch (tone) {
20
+ case 'strong':
21
+ return { bold: true };
22
+ case 'heading':
23
+ return { bold: true, color: theme.accent };
24
+ case 'dim':
25
+ return { color: theme.chrome.color };
26
+ case 'good':
27
+ return { color: theme.code.color };
28
+ case 'warn':
29
+ return { color: theme.warn };
30
+ case 'bad':
31
+ return { color: theme.line.error.color };
32
+ case 'accent':
33
+ return { color: theme.accent };
34
+ default:
35
+ return {};
36
+ }
37
+ }
38
+ function Painted({ line, theme }) {
39
+ if (line.length === 0) {
40
+ return _jsx(Text, { children: " " });
41
+ }
42
+ return (_jsx(Text, { wrap: "truncate-end", children: line.map((span, i) => (_jsx(Text, { ...styleOf(span.tone, theme), children: span.text }, i))) }));
43
+ }
44
+ function Top({ sampler, intervalMs, explain: start, palette }) {
45
+ const { exit } = useApp();
46
+ const { stdout } = useStdout();
47
+ const [size, setSize] = useState({ columns: stdout.columns || 80, rows: stdout.rows || 24 });
48
+ useEffect(() => {
49
+ const resized = () => setSize({ columns: stdout.columns || 80, rows: stdout.rows || 24 });
50
+ stdout.on('resize', resized);
51
+ return () => {
52
+ stdout.off('resize', resized);
53
+ };
54
+ }, [stdout]);
55
+ const [view, setView] = useState();
56
+ const [failure, setFailure] = useState();
57
+ const [explain, setExplain] = useState(start);
58
+ const [sort, setSort] = useState('memory');
59
+ const [paused, setPaused] = useState(false);
60
+ useEffect(() => {
61
+ if (paused) {
62
+ return;
63
+ }
64
+ let stopped = false;
65
+ let timer;
66
+ const tick = async () => {
67
+ try {
68
+ const next = await sampler.next();
69
+ if (!stopped) {
70
+ setView(next);
71
+ setFailure(undefined);
72
+ }
73
+ }
74
+ catch (err) {
75
+ if (!stopped) {
76
+ setFailure(message(err));
77
+ }
78
+ }
79
+ if (!stopped) {
80
+ timer = setTimeout(() => void tick(), intervalMs);
81
+ }
82
+ };
83
+ void tick();
84
+ return () => {
85
+ stopped = true;
86
+ clearTimeout(timer);
87
+ };
88
+ }, [sampler, intervalMs, paused]);
89
+ useInput((input, key) => {
90
+ // A pasted or piped key can arrive with a newline behind it.
91
+ const k = input.trim()[0];
92
+ if (k === 'q' || key.escape) {
93
+ exit();
94
+ }
95
+ else if (k === 'e' || k === '?') {
96
+ setExplain((on) => !on);
97
+ }
98
+ else if (k === 's') {
99
+ setSort((now) => SORTS[(SORTS.indexOf(now) + 1) % SORTS.length]);
100
+ }
101
+ else if (k === 'p' || input === ' ') {
102
+ setPaused((on) => !on);
103
+ }
104
+ });
105
+ // One row for the keys, one spare so the frame never reaches the bottom.
106
+ const rows = Math.max(4, size.rows - 2);
107
+ const lines = view
108
+ ? layout(view, {
109
+ width: size.columns - 1,
110
+ rows: failure ? rows - 1 : rows,
111
+ explain,
112
+ sort,
113
+ live: intervalMs / 1000,
114
+ })
115
+ : [[{ text: 'asking podman…', tone: 'dim' }]];
116
+ const keys = [
117
+ `e notes ${explain ? 'off' : 'on'}`,
118
+ `s sort: ${sort}`,
119
+ paused ? 'p resume' : 'p pause',
120
+ 'q quit',
121
+ ].join(' · ');
122
+ return (_jsxs(Box, { flexDirection: "column", children: [lines.map((line, i) => (_jsx(Painted, { line: line, theme: palette }, i))), failure ? (_jsx(Text, { wrap: "truncate-end", color: palette.line.error.color, children: ` ✗ ${failure}` })) : null, _jsx(Text, { wrap: "truncate-end", color: palette.chrome.color, children: paused ? `paused · ${keys}` : keys })] }));
123
+ }
124
+ /** Runs the live screen until the person leaves it. */
125
+ export async function watch(options) {
126
+ // Asked before Ink takes the terminal, as tui/app.tsx does.
127
+ const palette = await resolveTheme(options.theme);
128
+ const instance = render(_jsx(Top, { ...options, palette: palette }));
129
+ await instance.waitUntilExit();
130
+ }
131
+ //# sourceMappingURL=sandbox.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenera/cli",
3
- "version": "1.1.25",
3
+ "version": "1.1.26",
4
4
  "description": "Command-line front end for @zenera/neo: agentic projects you can run, share and commit.",
5
5
  "keywords": [
6
6
  "agents",
@@ -52,7 +52,8 @@
52
52
  "@google/genai": "^2.18.0",
53
53
  "@inkjs/ui": "^2.0.0",
54
54
  "@openrouter/sdk": "^1.2.80",
55
- "@zenera/neo": "^1.1.25",
55
+ "@zenera/neo": "^1.1.26",
56
+ "@zenera/view": "^1.1.26",
56
57
  "google-auth-library": "^10.0.0",
57
58
  "ink": "^7.1.1",
58
59
  "openai": "^6.0.0",
@@ -113,29 +113,20 @@ tool access; give tool-based RAG users the configured RAG tools instead. Run
113
113
  `zen check` after adding or changing the skill.
114
114
 
115
115
  Memory has one such obligation and it is absolute: **a project with a `memory:`
116
- block carries the `zen-memory` skill's `references/memory-instructions.md` in its
117
- own `agents/memory-instructions.md`.** `zen init` writes both, since it scaffolds
118
- memory on; what needs watching is a project that deleted the file, or one whose
119
- copy has fallen behind the reference. Do not read the two files against each
120
- other - they drift by trailing whitespace inside tables, which is invisible.
121
- The skill ships the check:
122
-
123
- ```sh
124
- .github/skills/zen-memory/scripts/check-instructions.sh # the verdict
125
- .github/skills/zen-memory/scripts/check-instructions.sh fix # copy the reference over
126
- ```
127
-
128
- It is a copy, never a transcription - the reference ships inside the project,
129
- because `zen init` and `zen open` write this whole `.github/` tree, so `fix` is
130
- just `cp` from one to the other.
116
+ block carries `agents/memory-instructions.md` exactly as `zen` ships it.**
117
+ `zen init` writes it, since it scaffolds memory on; what needs watching is a
118
+ project that deleted the file, or one whose copy has fallen behind. `zen check`
119
+ reports the first as `memory.uninstructed` and the second as `rules.stale` -
120
+ by bytes, so trailing whitespace inside a table, invisible on screen, is caught
121
+ too - and `zen check --fix` repairs both.
131
122
 
132
123
  Nothing else tells a running agent how the store works, so without it nothing
133
124
  forbids an agent from pointing `grep` or `cat` at `/memory` - a read that
134
- bypasses the audience mask and serves superseded nodes as current. Keep the copy
135
- byte-identical and put this project's own memory policy in a second topic file,
136
- `agents/memory-policy-instructions.md`, which is read straight after it: then the
137
- copy can be re-run after any `zen init` or `zen open` refreshes the reference,
138
- without losing anything. Never paraphrase the reference into prose of your own.
125
+ bypasses the audience mask and serves superseded nodes as current. Leave the
126
+ file untouched and put this project's own memory policy in a second topic file,
127
+ `agents/memory-policy-instructions.md`, which is read straight after it: then
128
+ `zen check --fix` can replace the first after any upgrade without losing
129
+ anything. Never paraphrase it into prose of your own.
139
130
  See §5.3.
140
131
 
141
132
  A project with a `SPECIFICATION.md` carries one more: **`.spec-sync/` records
@@ -1334,13 +1325,11 @@ derived from `access` and are never listed in `tools:`.
1334
1325
 
1335
1326
  **Memory comes on.** `zen init` writes the block above, `memory: true` on the
1336
1327
  default agent, and the half nobody would guess was part of it:
1337
- `agents/memory-instructions.md`, a copy of the `zen-memory` skill's
1338
- `references/memory-instructions.md`, which the project already holds. Adding
1339
- memory to a project that has none is both of those edits, and a copy that was
1340
- lost or went stale is one command:
1328
+ `agents/memory-instructions.md`. Adding memory to a project that has none is
1329
+ both of those edits, and a file that was lost or went stale is one command:
1341
1330
 
1342
1331
  ```sh
1343
- .github/skills/zen-memory/scripts/check-instructions.sh fix
1332
+ zen check --fix
1344
1333
  ```
1345
1334
 
1346
1335
  It is what tells the agent that the store is reached only through the tools, that
@@ -1352,19 +1341,17 @@ what a node must carry to be worth having, and that a correction is a
1352
1341
  with it - and it carries `requires: [memory]`, so an agent without the store
1353
1342
  never reads a word of it.
1354
1343
 
1355
- **Leave that file as a pure copy.** Anything this project decides for itself -
1344
+ **Leave that file untouched.** Anything this project decides for itself -
1356
1345
  which audience holds what, what must never be written down, what an agent is
1357
1346
  expected to commit at the end of a job - goes in
1358
1347
  `agents/memory-policy-instructions.md`. Topic files are read in filename order,
1359
- so the policy lands directly after the rules it qualifies, and the copy stays
1360
- re-runnable: the reference is rewritten by every `zen init` and `zen open`, and
1361
- keeping up with it is then the same one-line command rather than a hand-patch.
1348
+ so the policy lands directly after the rules it qualifies, and the file stays
1349
+ replaceable: keeping up with a newer `zen` is then `zen check --fix` rather
1350
+ than a hand-patch.
1362
1351
 
1363
- `zen check` validates the `memory:` block and says nothing about the rules'
1364
- absence, so this is checked every time, by
1365
- `.github/skills/zen-memory/scripts/check-instructions.sh` and never by reading
1366
- the two files against each other: they drift by trailing whitespace inside a
1367
- table, and the script is what can see that.
1352
+ `zen check` reports a missing file as `memory.uninstructed` and any differing
1353
+ byte as `rules.stale`. Never compare the file by eye: it drifts by trailing
1354
+ whitespace inside a table, and only a byte comparison sees that.
1368
1355
 
1369
1356
  Do not treat memory as a database. It is for things learned that should
1370
1357
  persist. Anything authoritative - a rate, a policy clause, a procedure - belongs
@@ -1865,8 +1852,8 @@ ok, `1` failed, `2` usage, `3` invalid project, `4` no usable credential.
1865
1852
 
1866
1853
  ## 9. Review checklist
1867
1854
 
1868
- Four of these are decidable, and are one command - `zen check`, the path sweep,
1869
- the memory copy, the spec-sync record, in that order:
1855
+ Three of these are decidable, and are one command - `zen check`, the path sweep,
1856
+ the spec-sync record, in that order:
1870
1857
 
1871
1858
  ```sh
1872
1859
  .github/skills/zen-review/scripts/review.sh
@@ -1905,10 +1892,9 @@ Before finishing any change here:
1905
1892
  - [ ] Failure paths stated for every instruction that can fail
1906
1893
  - [ ] No facts, rates or figures embedded in a prompt
1907
1894
  - [ ] No hedging, no meta-talk about the runtime
1908
- - [ ] If any agent has `memory:`,
1909
- `.github/skills/zen-memory/scripts/check-instructions.sh` exits zero -
1910
- `agents/memory-instructions.md` is the reference byte for byte - and
1911
- anything project-specific is in `agents/memory-policy-instructions.md` - §5.3
1895
+ - [ ] If any agent has `memory:`, `zen check` reports neither
1896
+ `memory.uninstructed` nor `rules.stale` - and anything project-specific
1897
+ is in `agents/memory-policy-instructions.md` - §5.3
1912
1898
 
1913
1899
  **Paths (§2.5 - `.github/skills/zen-review/scripts/check-paths.sh` finds the
1914
1900
  candidates; these are the judgements to make about each one)**
@@ -2044,10 +2030,10 @@ candidates; these are the judgements to make about each one)**
2044
2030
  the turn that follows it - §2.5.
2045
2031
  - **Arithmetic in prose.** A skill that walks the model through a calculation it
2046
2032
  will get wrong, in a folder that could have held the script - §3.4.1.
2047
- - **The unguarded store.** `memory:` turned on and the skill's
2048
- `references/memory-instructions.md` never copied to
2033
+ - **The unguarded store.** `memory:` turned on and no
2049
2034
  `agents/memory-instructions.md`, so nothing tells the agent the store is
2050
- reached only through the tools - and `zen check` passes throughout - §5.3.
2035
+ reached only through the tools - `zen check` fails with
2036
+ `memory.uninstructed`, and `zen check --fix` writes it - §5.3.
2051
2037
  - **Reviewing a capability without its skill.** A project whose memory, index or
2052
2038
  sandbox was configured by an earlier pass looks finished because it loads. The
2053
2039
  obligations are in the editor skill, not in `agents.yaml` - §0.1.
@@ -10,9 +10,11 @@ audit cannot be graded without it.
10
10
 
11
11
  ## Which run
12
12
 
13
- The last line of this prompt may name the run - a run directory or a run id.
13
+ The line after this prompt may name the run - a run directory or a run id.
14
14
  If it does, use it. Words after it like `case=<id> ... feedback=<file>` mean
15
15
  the tuning loop sent you: follow section 7 of the skill and write that file.
16
+ A `## The brief` section below that line is what the loop already ran for
17
+ you: section 1 of the skill says how to use it.
16
18
 
17
19
  If it does not, list this project's most recent runs, newest first:
18
20
 
@@ -1,45 +1,197 @@
1
1
  ---
2
- description: Apply a batch of improvement requests from the tuning loop to the project's prose - merge them into patterns, edit prompts, skills and policy files, and record what was done with each. Run by `zen meta finetune`; the last line names the apply directory.
2
+ description: Apply a batch of improvement requests from the tuning loop to the project's prose - merge them into patterns, edit prompts, skills and policy files, tidy up every file touched, and record what was done with each. Run by `zen meta finetune`; the line after the prompt names the apply directory, and a brief follows it.
3
3
  ---
4
4
 
5
5
  The tuning loop has collected improvement requests from several cases and
6
- wants them applied **together**. The last line of this prompt names the apply
7
- directory. Load the `zen-instructions` skill before you edit anything under
8
- `agents/`, `zen-memory` when any request is from a run with memory, and
9
- `zen-code-python` when any request touches an agent that writes or runs code.
6
+ wants them applied **together**. The line after this prompt names the apply
7
+ directory.
8
+
9
+ Every sentence you add is read by every later call of every agent that loads
10
+ it, so prose has a price even when it fixes the case in front of you. The loop
11
+ measures it: after you finish, an apply that grows the prose past its budget
12
+ is **undone** - all of it. Then a few cases that passed before run again on
13
+ your edit; one it broke comes back to the next apply as a request.
10
14
 
11
15
  ## What you are given
12
16
 
17
+ A `## The brief` section after that line is what the loop already read and
18
+ worked out for you, from the files below. Work from it:
19
+
20
+ - Do not read a file the brief shows, and do not run a command it shows -
21
+ until you have edited that file yourself.
22
+ - Do not parse `inputs.json`, `deferred.json`, `budget.json` or `growth.json`
23
+ with a script: `Requests by file`, `The requests`, `Growth` and the
24
+ `budget.json` block are their content. Open one only for a field the brief
25
+ marks `(cut at ...)` or `(left out ...)`.
26
+ - Do not open other `finetune/applies/*` folders: `Earlier tries of these
27
+ cases` is what they hold about these cases.
28
+
29
+ The files behind it:
30
+
13
31
  - `<apply dir>/inputs.json` - the requests: each has `id` (`<case>@<phase>-<attempt>`),
14
32
  `case`, `phase` (`nomem` or `mem`), `summary`, `improvements` (each with `id`,
15
- `kind`, `file`, `change`, `why`, `expect`) and `file`, the feedback it came from.
16
- The analysis behind each is `analysis.md` beside that file - read it when an
17
- improvement is unclear.
18
- - Every earlier `finetune/applies/*/decisions.json` and `changes.md` - what
19
- was already tried. Do not re-apply a rule an earlier apply added and a later
20
- run showed did not work; change it instead.
21
- - `<apply dir>/check.log`, if it exists: your previous attempt left the project
22
- failing `zen check`, and the edit was undone. Read it first.
33
+ `kind`, `file`, `change`, `why`, `expect`), `file`, the feedback it came from,
34
+ and `missedSkills` - skills an earlier apply made for this case that its last
35
+ run never loaded. The analysis behind each is `analysis.md` beside that file -
36
+ read it when an improvement is unclear.
37
+ A request with `recheck` (id `<case>@recheck-<apply>`) is a **regression**: the
38
+ case passed before that apply and failed twice on it. Its analysis quotes the
39
+ hunk of that apply's `diff.patch` that did it. Narrow or revert that rule -
40
+ never stack an exception under it.
41
+ - `<apply dir>/deferred.json` - improvements earlier applies held back because
42
+ only one case asked for them, with their case and apply. They count as
43
+ evidence below.
44
+ - `<apply dir>/budget.json` - what the agents read, in bytes: `alwaysRead` per
45
+ agent (house rules, its prompt, preloaded skills, the skill index lines),
46
+ `skills` (each on-demand skill body), `visible` (skills each agent can see),
47
+ the same at the start of the tuning (`start`), and the limits: `budget` (the
48
+ most this apply may add to the always-read total), `ceiling` (above it, an
49
+ apply may add nothing), `skillCap`, `maxSkills`.
50
+ - `<apply dir>/growth.json` - per file under `agents/`: bytes at the start of
51
+ the tuning and now, how many applies changed it, and the latest of them.
52
+ - Earlier requests of the same cases, and what each apply decided about them -
53
+ the brief's `Earlier tries of these cases`. Do not re-apply a rule an
54
+ earlier apply added and a later run showed did not work; change it instead.
55
+ - From your previous attempt, if it was undone - the first files in the brief:
56
+ `check.log` (it failed `zen check`), `budget.md` (it grew the prose past a
57
+ limit - this attempt must cut) and `missing.md` (it ended without a decision
58
+ for every improvement).
59
+
60
+ ## Load the skills
61
+
62
+ A request says what a run did wrong; the rules for fixing it live in the editor
63
+ skills, not in the request. The brief's `Skills to load` lists the ones this
64
+ project's capabilities call for. Load every one of them now, before the first
65
+ edit. Load `zen-sandbox` too when any improvement is about the container,
66
+ installing packages, or a command that failed for want of a tool. No other
67
+ `zen-*` skill is needed.
68
+
69
+ An improvement that already sounds right is not a reason to skip its skill -
70
+ the skill is how you find out whether it is.
23
71
 
24
72
  ## What to do
25
73
 
26
- 1. **Merge before editing.** Group the improvements by the behaviour they fix.
27
- Several cases asking for the same thing in different words is one rule.
28
- Two that contradict each other: decide, and say why.
29
- 2. **Generalise.** Every rule must hold for queries no case asked. Never write
30
- a case's answer, its ids or its data into the prose - if a request only
31
- makes sense for its one case, reject it.
32
- 3. **Edit** prompts under `agents/prompts/`, skills under `agents/skills/`,
33
- `agents/instructions.md` and `agents/<topic>-policy-instructions.md`
34
- (create the policy file when the rule belongs to one capability). Requests
35
- from runs **with memory** change only the memory policy -
36
- `agents/memory-policy-instructions.md` - or the memory paragraph a request
37
- names.
38
- 4. **Never edit** `agents.yaml`, `agents/memory-instructions.md`,
39
- `agents/tools-instructions.md`, `agents/fork-instructions.md` or
40
- `agents/files-instructions.md`, nor anything outside `agents/`. A request
41
- that needs one of those is **structural**: record it, do not apply it.
42
- 5. **Check**: `zen check --no-models --no-sandbox` must pass when you finish.
74
+ 1. **Merge before editing.** The brief's `Requests by file` has already put
75
+ the improvements - and the entries of `deferred.json` - under the file each
76
+ names, with the distinct cases behind each file. Now group them by the
77
+ behaviour they fix, across files too. Several cases asking for the
78
+ same thing in different words is one pattern. Two that contradict each
79
+ other: decide, and say why. Count the **distinct cases** behind each
80
+ pattern.
81
+ 2. **Hold each against its skill.** An improvement's `change` is one analyst's
82
+ guess at the fix. A change that breaks a skill's rule - shell `grep` over an
83
+ index, a paraphrase of a copied house rule, a one-off inline script, a
84
+ handoff with no way back - is rewritten to what the skill prescribes, or
85
+ rejected naming the rule. When the skill already states the rule, the agent
86
+ never saw it: fix how the skill is reached (its description, a load line in
87
+ the prompt), not a second copy of the rule.
88
+ 3. **Prove the owner and the absence**, for every pattern:
89
+ 1. State the obligation in one sentence of your own, not the wording of
90
+ any request.
91
+ 2. Name exactly which agents must obey it, and choose the narrowest place
92
+ that reaches all of them - see the table in step 6.
93
+ 3. Search every file those agents read for the same obligation: house
94
+ rules (`agents/instructions.md`, every `agents/*-instructions.md`),
95
+ their prompts, their preloaded skills and the skills they would load
96
+ for it. Search its distinctive verbs and nouns and obvious other
97
+ wordings, not one exact quote.
98
+ 4. Choose exactly one disposition: `edit existing`, `move and delete`,
99
+ `delete contradiction`, `extract to skill`, or `add because absent`.
100
+ Every location found goes in `changes.md`.
101
+
102
+ If several places say it, consolidate into the one owner and delete the
103
+ others in this apply. If a broad rule caused the failure, rewrite or
104
+ narrow that rule - never keep it and add an exception elsewhere.
105
+
106
+ 4. **Evidence.** `add because absent` and `extract to skill` need **two or
107
+ more distinct cases** behind the pattern, counting `deferred.json`. With
108
+ one case you may only `edit existing`, `move and delete` or
109
+ `delete contradiction`, and only if the always-read total does not grow.
110
+ Anything else from one case is `deferred` - not applied, not rejected: it
111
+ comes back in `deferred.json` until a second case asks for it.
112
+ 5. **Generalise.** Write each rule for a class of queries, not for a case -
113
+ it must hold for queries no case asked. Never write a case's answer, ids,
114
+ names, numbers or data into the prose, nor an example lifted from a case's
115
+ query. Keep a specific only when the rule cannot be stated without it - a
116
+ tool, a command, a file path of this project. Before you save, check every
117
+ sentence you added: a noun, number or quoted phrase that comes from a case
118
+ and appears nowhere else in the project is overfit - replace it with the
119
+ class it belongs to, or drop the rule. A request that only makes sense for
120
+ its one case is rejected.
121
+ 6. **Route by behaviour, not by phase.** A request from a run with memory goes
122
+ where its behaviour is owned, like any other.
123
+
124
+ | The obligation is… | It goes in |
125
+ | -------------------------------------------------------------------- | --------------------------------------------------------- |
126
+ | one agent's behaviour, on every request it gets | `agents/prompts/<agent>.md` |
127
+ | a procedure or facts only some kinds of request need | an on-demand skill under `agents/skills/` - see step 7 |
128
+ | a standing rule every agent must obey | `agents/instructions.md` |
129
+ | what to commit to memory, when to recall, what to trust from it | `agents/memory-policy-instructions.md` |
130
+ | a rule every user of one capability must obey | that capability's `agents/<topic>-policy-instructions.md` |
131
+ | the wrong agent had a tool, a skill binding, the dataset or a rubric | **structural** - record it, do not compensate with prose |
132
+
133
+ 7. **Skills.** `extract to skill` moves a procedure or a set of facts out of a
134
+ prompt or a policy into `agents/skills/<name>/SKILL.md`, which the agent
135
+ loads only when a request needs it. Its body costs nothing until then; its
136
+ index line costs on every call.
137
+ - The prompt keeps **one line** pointing at the skill: the condition and
138
+ the name. Delete the moved prose from where it was.
139
+ - The `description:` says **when** to load it - the condition, in words a
140
+ request would match - and must not overlap another skill's.
141
+ - Never make a skill for one case's data: what one case needs to know
142
+ about its own data is memory's job. Rejected.
143
+ - A skill in `missedSkills` was not loaded by the case it was written for:
144
+ its description is the defect. Rewrite the description - not more
145
+ prose. A skill missed twice goes back into its owner (`move and delete`)
146
+ or into a skill that is loaded.
147
+ - Keep each skill under `skillCap` and each agent under `maxSkills`: an
148
+ oversized skill is split by when it is needed, overlapping ones merged.
149
+ - You cannot preload a skill: that is `agents.yaml`, structural.
150
+ 8. **Never write:**
151
+ - an exception stacked under a general rule, or "this overrides X" -
152
+ rewrite X;
153
+ - a tool-call script ("call A first", "read lines 1-200") - write the
154
+ invariant it serves;
155
+ - a prohibition with an exemption the agent judges for itself ("unless
156
+ clearly needed") - that is a permission. Forbid it, or do not.
157
+ 9. **Stay inside the budget** in `budget.json`. Over `ceiling`, this apply must
158
+ not grow the always-read total at all: cut, move or extract to make room.
159
+ 10. **Edit** prompts under `agents/prompts/`, skills under `agents/skills/`,
160
+ `agents/instructions.md` and `agents/<topic>-policy-instructions.md`
161
+ (create a policy file only when step 3 proved the rule absent and every
162
+ agent with that capability must obey it).
163
+ 11. **Never edit** `agents.yaml`, `agents/memory-instructions.md`,
164
+ `agents/tools-instructions.md`, `agents/fork-instructions.md` or
165
+ `agents/files-instructions.md`, nor anything outside `agents/`.
166
+ 12. **Tidy up every file you touched** - the whole file, not only your lines.
167
+ For each obligation in it, search the files the same agents read, and pick
168
+ one move:
169
+ - `merge duplicates` - the same obligation twice for the same audience:
170
+ keep it in the owner, delete the rest;
171
+ - `delete contradiction` - two sentences that cannot both be obeyed: keep
172
+ the one the later `changes.md` chose;
173
+ - `narrow` - a general rule followed by its exceptions: rewrite the rule so
174
+ it needs none, delete the exceptions;
175
+ - `move and delete` - a rule in a file wider than the agents it binds;
176
+ - `split skill` / `merge skills` - a skill over `skillCap`, two whose
177
+ descriptions overlap, or an agent over `maxSkills`.
178
+
179
+ Never weaken an obligation: what an agent must do stays what it must do.
180
+ The bytes this frees count against your budget, so a crowded file is where
181
+ to make room. Then take the largest growth in `growth.json` you did not
182
+ touch: if it says one thing twice, merge it too.
183
+
184
+ 13. **Read it back.** Search again for each obligation's terms, and read each
185
+ affected agent's prompt in the order it is assembled - house rules first,
186
+ then its prompt. Every remaining copy must have a different audience, or
187
+ go.
188
+ 14. **Gate**: when your edits are done, run once
189
+ `zen meta finetune gate <apply dir>`. It judges the edit exactly as the
190
+ loop will after you: the bytes moved per agent, skill and file, any limit
191
+ broken, and `zen check`. On `gate: fail`, fix what it names and run it
192
+ again. Do not measure or diff files yourself and do not use git: the loop
193
+ never commits, so `git diff` mixes in earlier applies, and it records the
194
+ diff and the bytes of this apply after you finish.
43
195
 
44
196
  ## What to write
45
197
 
@@ -54,38 +206,65 @@ directory. Load the `zen-instructions` skill before you edit anything under
54
206
  **The pattern:** what the cases did wrong, in one paragraph, with the node
55
207
  ids from their analyses - not a case's answer.
56
208
 
57
- **Before:** the sentence or section as it was, quoted (or "new section").
209
+ **Obligation:** the one sentence of step 3, and the agents it binds.
210
+
211
+ **Searched:** the terms you searched for, and every place they were found.
212
+
213
+ **Disposition:** `edit existing`, `move and delete`, `delete contradiction`,
214
+ `extract to skill` or `add because absent` - with the cases behind it.
58
215
 
59
216
  **After:** the text as it is now, quoted.
60
217
 
218
+ **Checked against:** the skill and rule it was held to, or "no skill
219
+ covers this".
220
+
61
221
  **Why it generalises:** which queries beyond these cases it changes, and
62
222
  which it must not.
63
223
 
64
- **Expect:** what the next run's graph should show if it worked.
224
+ **Expect:** what the next run's graph should show if it worked - for a
225
+ skill, the `skills <name>` node before the step it covers.
65
226
  ```
66
227
 
67
- Then a section **Not applied**: every rejected or structural improvement, with
68
- why.
228
+ A section for a tidy-up move has **Move**, **Obligation** and **After**
229
+ only. The diff and the bytes moved are added by the loop - do not write
230
+ them.
231
+
232
+ Then a section **Not applied**: every rejected, deferred or structural
233
+ improvement, with why.
69
234
 
70
235
  - `<apply dir>/decisions.json` - a decision for **every** improvement of every
71
- request, nothing skipped:
236
+ request, nothing skipped. When you apply or merge an entry of
237
+ `deferred.json`, add it under its own request id too:
72
238
 
73
239
  ```json
74
240
  {
75
241
  "plan-day@nomem-1": {
76
- "i1": { "decision": "applied", "note": "agents/prompts/default.md - planning section" },
242
+ "i1": {
243
+ "decision": "applied",
244
+ "disposition": "extract to skill",
245
+ "skill": "calendar-planning",
246
+ "note": "agents/skills/calendar-planning - planning procedure moved out of the prompt"
247
+ },
77
248
  "i2": { "decision": "merged", "note": "same rule as long-list-3@nomem-1 i1" }
78
249
  },
79
250
  "long-list-3@nomem-1": {
80
- "i1": { "decision": "applied", "note": "agents/pagination-policy-instructions.md" },
251
+ "i1": {
252
+ "decision": "applied",
253
+ "disposition": "edit existing",
254
+ "note": "agents/pagination-policy-instructions.md"
255
+ },
81
256
  "i2": { "decision": "structural", "note": "needs a tool in agents.yaml" },
82
- "i3": { "decision": "rejected", "note": "only true for this case's data" }
257
+ "i3": { "decision": "rejected", "note": "only true for this case's data" },
258
+ "i4": { "decision": "deferred", "note": "one case; waits for a second" }
83
259
  }
84
260
  }
85
261
  ```
86
262
 
87
- `decision` is one of `applied`, `merged`, `rejected`, `structural`. The note is
88
- one line a person reads in the case's FEEDBACK.md.
263
+ `decision` is one of `applied`, `merged`, `rejected`, `deferred`, `structural`.
264
+ `disposition` is the one from step 3, on every `applied`. `skill` names the
265
+ skill an improvement created or changed - the loop checks the case's next run
266
+ loads it. The note is one line a person reads in the case's FEEDBACK.md.
89
267
 
90
- Your answer is a short summary: how many rules, which files, and anything
91
- structural the user must decide.
268
+ Your answer is a short summary: how many rules, which files, what the tidy-up
269
+ merged or cut, the net change in bytes `gate` printed, and anything structural
270
+ the user must decide.
@@ -13,7 +13,7 @@ saying anything.
13
13
  .github/skills/zen-review/scripts/review.sh
14
14
  ```
15
15
 
16
- That is `zen check`, the §2.5 path sweep, the memory house-rules copy and the
16
+ That is `zen check`, the §2.5 path sweep and the
17
17
  spec-sync record, in the order they matter. Load the `zen-review` skill for what
18
18
  each one owns and how to read its output. Do not re-verify by hand anything it
19
19
  already decided, and do not go further while `zen check` fails - nothing below