@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
@@ -4,496 +4,225 @@ requires: [memory]
4
4
 
5
5
  # Memory
6
6
 
7
- This project has a memory: a graph of what earlier runs worked out, kept with
8
- the project rather than with the session, and shared with every other agent that
9
- can see it. It is reached **only** through the `memory_*` tools - `memory_search`
10
- to find by meaning, `memory_grep` to find an exact string, `memory_load` to
11
- read.
12
-
13
- Not every agent may write to it. Read what follows against the tools you
14
- actually have: if `memory_commit` is not among them, everything under
15
- [Updating it](#updating-it) is not yours to do, and if `memory_forget` is not
16
- among them, neither is [Forgetting](#forgetting).
17
-
18
- It exists to make the next run cheaper. Work that cost something - a long
19
- investigation, a fan-out of searches, a build, an invocation found by trial -
20
- should be paid for once. A recollection is a cache hit: check it, do not
21
- rebuild it.
22
-
23
- ## What belongs in it
24
-
25
- One question decides both what to keep and how far to trust it:
26
-
27
- **Can the next run get this itself, cheaply and current?**
28
-
29
- | When the answer is | Keep |
30
- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
31
- | one read, one call, one command away | the way to get it - the route, the call, the script, the invocation |
32
- | assembled from several sources, with a judgement on top | what you concluded, and a pointer to every source it came from |
33
- | out of something that cannot change - a released spec, a pinned or versioned document | the finding itself, whole, in a file that names where it came from |
34
- | a reading of the moment - an API response, a query result, what a script printed | the call that produces it, never the reading |
35
-
36
- Remember the **route** when the answer is cheap, the **answer** when the route
37
- is expensive, and never a value that is stale by the next run.
38
-
39
- ## How it is organised
40
-
41
- A node is one thing worth keeping. It carries a `kind`, a `text` - the only
42
- thing searched - and optionally a remembered file. An edge says how one node led
43
- to another.
44
-
45
- The two halves do different jobs, and the split is the same every time: the
46
- **text is how the node is found** - what it is, what it establishes, where it
47
- came from - and the **file is what the node holds**. Only the text is searched,
48
- and only its first 160 characters are ever shown, so content written into it is
49
- both unfindable and in the way. Once something is worth committing at all, the
50
- usual shape is therefore a short description and a file behind it.
51
-
52
- A node with no file is for what fits on **one line** - a path and a line range,
53
- a command, a standing instruction, a single stated fact. If what you are keeping
54
- runs past a line or two, it is content, and content goes in the file.
55
-
56
- | Kind | Is |
57
- | ------------ | ------------------------------------------------------------------------------------ |
58
- | `task` | the request that started a piece of work |
59
- | `plan` | an approach that worked and would work again |
60
- | `fact` | a durable truth about this codebase, API or environment |
61
- | `snippet` | a few lines of code or configuration |
62
- | `file` | an artifact kept whole - a script to re-run, an answer or passage too big for a text |
63
- | `operation` | an external call that was made - endpoint, command, query. The call, not its answer |
64
- | `preference` | a standing instruction from the user, or what they told you about themselves |
65
-
66
- | Relation | Reads as |
67
- | ------------ | --------------------------------------------------- |
68
- | `PRODUCED` | the source led to the target being made |
69
- | `CALLS` | the source invokes the target |
70
- | `SUPERSEDES` | the source replaces the target; the target is stale |
71
- | `INFORMED` | the source was context the target was built from |
72
-
73
- So a remembered piece of work is a subgraph, not a row:
74
-
75
- ```
76
- task the request that started this
77
- PRODUCED → file | snippet | operation what came out of it
78
- INFORMED ← fact what had to be known first
79
- file
80
- CALLS → operation what it calls
81
- ```
82
-
83
- What you are shown is ranked, masked and clipped. **Assume a recollection is
84
- part of the answer, never all of it.**
85
-
86
- Relation is what decides where the clipping falls. Everything reached across
87
- `PRODUCED`, `CALLS` or `SUPERSEDES` is the work itself; everything reached
88
- across `INFORMED` is context, and context is what a short recollection drops
89
- first - so the answer degrades by losing its background rather than by being cut
90
- in half. Attach with `INFORMED` what **explains** a node, never what the next run
91
- needs in order to **use** it: the endpoint a script calls, or the request that
92
- produced it, belongs on the spine, where it is still there when the budget is
93
- tight.
94
-
95
- `INFORMED` also reads in a direction - from the background to the work it fed,
96
- so a `fact` informs an answer and never the other way round. Written backwards
97
- it still traverses, and still renders; it just says the answer was context for
98
- its own source.
99
-
100
- ## Reading it
101
-
102
- `memory_search` hands back an outline of a subgraph with each node's text cut to
103
- 160 characters. `memory_grep` hands back the nodes containing an exact string,
104
- with the lines it matched on. `memory_load` is what reads a node whole, by id -
105
- load anything you are going to rely on.
106
-
107
- ### The shape of a recollection
108
-
109
- A recollection arrives in a `<memory-recollection>` block, and it is a subgraph
110
- rather than a ranked list - the links are as much of the answer as the nodes. It
111
- is an outline, and the indentation is the graph.
112
-
113
- A line at the left margin reads `score kind id` and is something the search
114
- matched; a root the walk reached rather than matched carries `--` where the
115
- score would be. A line indented under it reads `<arrow>relation kind id` and is
116
- a neighbour: `→produced` means the line above produced this one, `←informed`
117
- means this one informed the line above. A neighbour the search matched in its
118
- own right carries its score too, after the arrow.
119
-
120
- Under each header, indented further, is that node's text. A `file` node carries
121
- one line more, above the text: the path under `/memory` to open or run, its
122
- size, and how often it has been read.
123
-
124
- A line beginning `+` is a link to an id already shown above, for an edge the
125
- outline could not nest. It never points forward, so resolving one only ever
126
- means looking back up the block.
127
-
128
- Text is clipped at 160 characters - copy an id into `memory_load` to read a node
129
- whole. `memory_search` finds ids; it does not return contents.
130
-
131
- A remembered file appears at `/memory/<id>.<ext>`. Open it or run it, but arrive
132
- at that path through `memory_load`, never by looking around in the directory.
133
-
134
- **Never read the store directly.** `/memory` holds `graph.json`, `vectors.f32`,
135
- `vectors.json` and `manifest.json` - its internal format. Do not open, list,
136
- grep, `cat` or `find` them, and do not point a shell command at that directory:
137
-
138
- - `graph.json` is every node ever committed, as one line;
139
- - a raw read bypasses the audience mask and serves **superseded** nodes -
140
- corrections that were withdrawn - as if they were current;
141
- - it records no use, so the ranking that decides what gets recalled next decays;
142
- - another run may be writing, and the manifest is written last.
143
-
144
- **`memory_grep` is that search, done properly.** It reads every node exactly -
145
- the text, the metadata and the bytes of remembered files - and hands back the
146
- matching lines with the node they belong to. It applies the mask, it leaves out
147
- what has been superseded unless you ask for it, and it names any file it could
148
- not read, so a file that went unsearched never passes for one with no match.
149
-
150
- A memory is a record, not an authority - but checking one is not the same as
151
- redoing it, and how you check depends on where its content came from.
152
- **Pinned** - a released spec, a versioned document: its content cannot have
153
- moved, so use what the node says and check only that the route still resolves.
154
- **Living** - code, an API, anything that changes: confirm the named lines still
155
- say what the node says, the route still resolves, the command still exists.
156
- Work it out from nothing only when that check fails, or when being wrong is
157
- expensive. A check that costs what the original investigation cost is not a
158
- check - it is the investigation again, and the memory bought nothing.
159
-
160
- ### None of it appears in an answer
161
-
162
- The store is your apparatus, not your subject. An answer says what was found and
163
- where it can be checked - the sources, the commands, the files the work left
164
- behind. It never says that a recollection was what put you on to them.
165
-
166
- Never write `/memory`, a node id, or the words "memory", "recalled" or
167
- "remembered" into an answer. Read your text before you send it: if it holds
168
- `/memory` or a node id, cut the sentence around it and say what was done
169
- instead. "Loaded the script from memory (`/memory/01J….py`) and ran it" is
170
- "ran `<path>`" with your working left in by mistake.
171
-
172
- Two reasons, and both hold even where the reader would find it interesting. A
173
- node id names nothing the reader can open, so it reads as a citation and cannot
174
- be followed; and it stops being true the moment the node is superseded, while
175
- the source it was drawn from does not. Cite the source, never the memory of it.
176
-
177
- This binds on a branch's answer exactly as it binds on the final one. A branch
178
- rejoins as a single result that the agent above writes its own answer from, so
179
- an id that survives the join is an id in the reply.
180
-
181
- The one exception is a question about the store itself - what is known about
182
- something, whether it was seen before, what to forget. Then it is the subject,
183
- and ids are what the reader needs.
184
-
185
- ## Searching it
186
-
187
- Search **before** paying for anything: an investigation, an index query, a
188
- build, a long command. The point is not to find a pointer - it is to arrive at
189
- the answer without buying it twice.
190
-
191
- Four moments are each worth one search:
192
-
193
- | At | Search for |
194
- | ---------------------------------------- | ---------------------------------------------------------------------- |
195
- | a request arriving | the request itself, before the first step is planned |
196
- | arriving by handoff, or as a fork branch | the brief you were handed - it is new to you, not to the project |
197
- | the point where real work would start | the question that work would answer, whenever it is more than one call |
198
- | a dead end mid-run | what you now know you are missing, in the words you would ask it in |
199
-
200
- Search the QUESTION, not the turn. Asking the same question again in different
201
- words is a round trip for an answer you already have; search again when what
202
- you need to know changes, not when the step does.
203
-
204
- One `memory_load` is not cheaper than re-reading the single file a node names.
205
- It is far cheaper than redoing what produced that node: several documents read
206
- in sequence, a fan-out of searches, a delegated lookup, a long run. Price a
207
- recollection against what it **saves**, never against one read.
208
-
209
- Phrase the query as the question you are actually asking, in the words a person
210
- would use - node texts are written to be found that way. Narrow with `kinds`,
211
- `newer_than`, `limit`, `max_hops` and `max_nodes` when a recollection comes back
212
- broad rather than wrong.
213
-
214
- ### Which of the two
215
-
216
- `memory_search` ranks, so it returns what is closest and stops. That makes it
217
- right for a question and wrong for a fact about the store itself - whether one
218
- exact name, path or command was ever written down. An empty search on a
219
- question is still the answer to that question: it matched by meaning, so other
220
- wordings of the same question were covered. Do not follow it with a
221
- `memory_grep` for words taken from the question.
222
-
223
- `memory_grep` is exact and complete. Reach for it when the thing you are looking
224
- for is a **string** rather than a subject, and when the answer has to be all of
225
- them:
226
-
227
- | Looking for | Use |
228
- | --------------------------------------------------------------- | --------------- |
229
- | what was learned about a subject, however it was phrased | `memory_search` |
230
- | a name, path, id, host, flag or command, spelled exactly | `memory_grep` |
231
- | whether an exact name, path or command was written down at all | `memory_grep` |
232
- | everywhere a thing is mentioned, before changing or retiring it | `memory_grep` |
233
- | a starting point, when you do not yet know the vocabulary | `memory_search` |
234
-
235
- Either way, ids from one are ids for the other: grep a name, then `memory_load`
236
- what it turned up.
237
-
238
- Recalling nothing is not proof of anything: work it out normally, then commit
239
- the result so the next run does not repeat it. A `memory_grep` that found
240
- nothing is stronger - it means the string is not there - but it says nothing
241
- about the subject under another name.
242
-
243
- ## Updating it
244
-
245
- Commit when **the next run would otherwise have to work this out again** and
246
- working it out cost more than a `memory_load` will. The measure is what the
247
- answer COST, not what kind of thing it is: one cheap tool call away, do not;
248
- five reads, a fan-out and a judgement, commit the judgement and not only the
249
- five paths.
250
-
251
- | Worth committing | Not worth committing |
252
- | ----------------------------------------------------------------- | ------------------------------------------------------------------- |
253
- | The route through the codebase to a recurring question | A verbatim copy of one living file, which a read gives current |
254
- | What a schema or docs search resolved to, and what you made of it | The ranked guesses it returned on the way there |
255
- | The call or command sequence that turned out to be necessary | A single tool call that answers in milliseconds |
256
- | The exact invocation that finally worked, with its directory | The request restated, or notes on progress |
257
- | A working script or request body, committed whole | What running it printed - a reading, which the script gives current |
258
- | An interface that behaved differently from its documentation | What a call returned, which the call gives current |
259
- | The passage itself, when its source cannot change under you | A passage quoted out of something that can |
260
- | A proven absence - looked here and here, it is not there | Anything not actually verified |
261
-
262
- A restatement is not merely wasted space. Recall seeds on text alone, so a run
263
- that commits its own request as a task, a plan and a result has committed three
264
- near-copies of one sentence - and on the next similar question those three take
265
- the seed slots between them. Everything actually learned then ranks below them
266
- and is never reached.
267
-
268
- A search over a schema or a documentation index costs a round trip and comes
269
- back ranked, so it is the thing most worth not paying for twice. Commit what it
270
- **resolved to** - the operation and its shape, or the document, heading and line
271
- range - **and what you concluded from reading it**. The pointers alone make the
272
- next run repeat the reading; the conclusion alone cannot be checked. Both, in
273
- one subgraph, and the next run answers at once and verifies cheaply.
274
-
275
- When the index is over something pinned - a released spec, a versioned reference
276
- tree - go one further and carry the passage itself in a `file` node, headed with
277
- the documents and line ranges it was taken from. The pointer says where to look
278
- and the conclusion says what it meant, but only the passage saves the next run
279
- from opening the sources to find out what they actually said. Say in the node's
280
- text which kind of source it was, so a later run can see why a copy was allowed.
281
-
282
- ### When to commit
283
-
284
- That test says what is worth keeping. It does not say when to write it down, and
285
- work that is never written down cost what it cost for nothing.
286
-
287
- Two things call for a commit while the run is still going:
288
-
289
- - **A search came back empty, or came back beside the point, and you went on to
290
- work the answer out anyway.** That gap is the next run's gap too, and you are
291
- the only one in a position to close it. It is the usual reason a memory stays
292
- useless: every run pays for the same answer, no run writes it down.
293
- - **Something cost more than a `memory_load` will** - several reads, a fan-out,
294
- a build, a long command, a delegated lookup - or produced an artifact that
295
- works: a script, a query, a request body, the invocation that finally ran.
296
-
297
- And three moments must not pass without one:
298
-
299
- | Before | Because |
300
- | -------------------------------------- | ----------------------------------------------------------------- |
301
- | returning your final answer | the turn ends there, and nothing is written after it |
302
- | handing off to another agent | control moves and does not come back - what you know goes with it |
303
- | returning to the agent that forked you | only your answer returns; your transcript is dropped at the join |
304
-
305
- Commit a piece of work when it is finished rather than saving all of it for one
306
- call at the end: a run that is interrupted, or that runs out of room, loses
307
- whatever was being held back. That is not licence to split one subgraph across
308
- calls - refs resolve only within a single `memory_commit`, so whatever links
309
- together is still committed together.
310
-
311
- ### How to write it down
312
-
313
- **Commit the whole subgraph in one call.** A script with no record of what asked
314
- for it, or a fact with nothing that acts on it, is a memory nobody can use. Refs
315
- resolve only within a single `memory_commit`, so a subgraph split across calls
316
- arrives without its links.
317
-
318
- **Use `ref` (not `id`) for new nodes.** A new node uses `ref` as its local name
319
- (for example, `"ask"`, `"script"`), and edges connect them using those refs:
320
-
321
- ```json
322
- {
323
- "nodes": [
324
- { "ref": "ask", "kind": "task", "text": "audit firewall rules for risky ports" },
325
- { "ref": "script", "kind": "file", "text": "risk report generator", "file": "report.py" }
326
- ],
327
- "edges": [{ "from": "ask", "to": "script", "relation": "PRODUCED" }]
328
- }
329
- ```
330
-
331
- Use `id` only when updating an existing node that is already in memory from a
332
- previous search or load. Never pass `id` when creating a new node, and do not
333
- pass both `ref` and `id` on the same node.
334
-
335
- **Do not re-commit what a search already returned.** A node that says what one
336
- already in memory says is folded into it, and its existing id comes back under
337
- your ref - so the links you asked for still land, on the memory that was already
338
- there.
339
-
340
- **Take the task text you were handed.** When your instructions give you the
341
- task text, commit that text verbatim as your `task` node and look nothing up for
342
- it. Agents that commit at the same moment cannot see each other; identical
343
- wording is what folds their nodes into one.
344
-
345
- **Grep for an entity before minting a node for it.** An endpoint, a command, a
346
- host, a tool, a file - anything that recurs across runs is one node the rest of
347
- the graph hangs off, and folding by similarity will not catch a second copy
348
- worded differently. `memory_grep` the exact string first, and attach your edges
349
- to what comes back. One grep per entity you are about to mint, for its exact
350
- string. A sentence describing the subject is not an entity, and neither is a
351
- task's text: a literal phrase misses every other wording of it, and a
352
- near-duplicate is folded anyway.
353
-
354
- A duplicated hub is worse than a missing one. It splits the graph into islands:
355
- the question reaches one copy, the artifact that answers it hangs off another,
356
- and the walk out from a seed cannot cross between them - so a memory that is
357
- present returns nothing, and nothing in the recollection says it happened.
358
-
359
- **Say where the content came from.** This is what lets an incomplete
360
- recollection be continued instead of believed:
361
-
362
- | The node holds | Name |
363
- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
364
- | A fact about this codebase | the file and the line range it was read from - `src/models/factory.ts:120-168` |
365
- | Anything spanning several files | every one of them, each with its range, in the order they are read |
366
- | An API route or a behaviour | the document and operation id, or the request sent and the status that came back |
367
- | Something a document states | document, heading and line range, next to what it states - the pointer is how the passage is checked, not a substitute for it |
368
- | Something a command established | the exact command, its arguments, and the directory it ran in |
369
- | A plan | the steps, and where each step's target lives |
370
- | A negative result | where you looked, so the search is not repeated |
371
-
372
- **Write the text as the question.** Not the way the system that produced it
373
- names things, and with the identifying facts first - only the first 160
374
- characters appear in a recollection.
375
-
376
- | Instead of | Write |
377
- | ----------------- | ------------------------------------------------------------------------------------------ |
378
- | `fix for the 409` | `A duplicate customer email returns 409, not 422 - retry is wrong (src/billing.ts:88-104)` |
379
- | `retry.ts` | `Where retries are configured: one policy for all adapters, src/models/factory.ts:40-96` |
380
-
381
- **Put the content in a file, not in the text.** This is the usual shape, not a
382
- special case: a script, a config, a query, a request body, a rendered table of
383
- findings, a passage worth keeping whole, an answer that took several sources to
384
- assemble - all of it is a `file` node split in two. The `text` describes the
385
- content and says where it came from; the file holds the content itself, whole
386
- and exactly as it was - the entire block, not a summary of it. Content in a file
387
- costs nothing until a `memory_load` asks for it, and comes back at
388
- `/memory/<id>.<ext>` to be read or run. Commit a node with no file only when the
389
- whole of what you know is one line long.
390
-
391
- **The file must exist in the workspace first.** `memory_commit` copies an
392
- existing file from the workspace; it is not an upload channel and does not
393
- write file contents from raw arguments. Write the file to the workspace first
394
- (using `write_file`, `apply_patch`, `copy_file`, or a command saving under
395
- `/workspace`), then pass its workspace path (e.g. `"file": "report.py"` or
396
- `"file": "/workspace/report.py"`). Write it with its provenance header (below)
397
- the first time: adding the header in a second write pays for the whole file
398
- twice.
399
-
400
- Do not commit files from the living codebase (use a pointer with file and line
401
- ranges instead - copies go stale silently), raw ephemeral command logs, or
402
- anything outside the workspace.
403
-
404
- **Name the sources inside the file as well as in the text.** The two halves
405
- arrive separately - a recollection shows the text, and only a later
406
- `memory_load` opens the file - so a file read on its own is an assertion with
407
- nothing behind it. Open it with a header naming every document, heading and line
408
- range the content came from, and when it was taken, then the content verbatim:
409
-
410
- ```markdown
411
- <!-- reference-docs-1.4/overview.html.md:112-160 and
412
- reference-docs-1.4/architecture.html.md:38-91
413
- pinned 1.4 reference tree, read 2026-04-09 -->
414
-
415
- ...the passages, whole and unedited...
416
- ```
417
-
418
- Use whatever comment form the file's own format takes. A header costs two lines
419
- and is the difference between a copy that can be re-checked against its source
420
- and one that can only be believed.
421
-
422
- Make the file self-contained - it will be opened in a different workspace, so it
423
- takes its inputs as arguments and reads credentials from the environment - and
424
- say so in the text. **Give it a configurable output path.** `/memory` is
425
- read-only: a script that writes beside itself fails, while one that takes
426
- `--out` writes into the workspace and is reusable unchanged. Use a `snippet`
427
- only for the few lines that are read rather than run.
428
-
429
- A remembered script runs from where it is - the mount is readable, so
430
- `python3 /memory/<id>.py` or `node /memory/<id>.js` needs no copy first:
431
-
432
- ```
433
- python3 /memory/01JD9Q7X8N2K4M6P8R0T2V4W6Y.py --out ./report.csv
434
- ```
435
-
436
- **Read it before running it.** It is code an earlier run wrote, recalled by
437
- similarity: `memory_load` returns its contents, or its path when it is large, in
438
- which case read the file. Confirm it is the thing you want, and that its
439
- arguments are what you think, before executing anything.
440
-
441
- **Commit what produces the answer, not the material it was made from.** This is
442
- about what to keep, not what form to keep it in - whatever survives the test
443
- still goes in a file. A file the project holds: the pointer, never a copy - a
444
- copy goes stale silently and looks exactly as authoritative when it is wrong. An
445
- external call: the `operation` - route, auth, the parameters that mattered, the
446
- status a case returns - never the body that came back. A script: the file and
447
- the invocation that worked, never its output. What a run ESTABLISHED belongs in
448
- the node's text - that it works, what it was run against, the verdict that was
449
- the point; the rows it emitted do not.
450
-
451
- Two things fall outside that. An answer you assembled from several sources is a
452
- copy of none of them and exists nowhere in the project, so commit it, with a
453
- pointer node per source `INFORMED`ing it. And a passage from a pinned source
454
- does not go stale silently, so it may be kept whole, as described for indexes
455
- above.
456
-
457
- A body or a result set may still be worth keeping as a SPECIMEN - a shape to
458
- write against, a case to reproduce. Commit it as a `file` node whose text says
459
- what was asked, when, and that it is what came back then, never what the data
460
- is. Keep credentials out of the store, along with any personal data the specimen
461
- did not need: it outlives the session and every later run can read it.
462
-
463
- **Correct by superseding, never by editing.** Commit the new node and link it to
464
- the old one with `SUPERSEDES`. Recall then stops serving the wrong answer
465
- without destroying the record of why it changed.
466
-
467
- **Ask whether it will still be true next month.** Memory has no expiry and no
468
- reviewer. A durable fact about this project survives; a fact about this
469
- afternoon's state is how a graph becomes confidently wrong.
470
-
471
- ### Preferences
472
-
473
- A `preference` is a standing instruction from the user, and it is not recalled
474
- like everything else: every preference you can see is rendered into a
475
- `<memory-preferences>` block at the start of every later run, each with its id.
476
- They apply unless that run's request contradicts them.
477
-
478
- So commit one only when the user's own words generalise - "always", "from now
479
- on", "I prefer", "never". A single request being fulfilled is not a standing
480
- instruction, and one committed by mistake is in every future prompt until
481
- something supersedes it.
482
-
483
- What the user says about THEMSELVES belongs here too, and for the same reason: a
484
- later run that has to ask again has already lost what the block is for. Their
485
- name and how they want to be addressed, the role they work in, the timezone
486
- their dates are in, which of several accounts, environments or repositories is
487
- theirs, the language or the units they want answers in. Commit what they stated,
488
- in their own terms - never what you inferred from how they happened to phrase a
489
- request, and never a credential or a secret, which is not a preference however
490
- it was offered.
491
-
492
- To change one, commit the replacement and link it to the id shown in that block
493
- with `SUPERSEDES`.
494
-
495
- ### Forgetting
496
-
497
- Forget only what is wrong and has no successor. A superseded memory is already
498
- hidden from recall and should stay for the history, so `memory_forget` is for
499
- what should never have been written, not for what has been replaced.
7
+ This project shares a persistent graph between runs. Reach it only through the
8
+ `memory_*` tools. Never inspect, list, grep, or modify the store directly.
9
+
10
+ Use only the capabilities you hold. If `memory_commit` is absent, do not update
11
+ the graph. If `memory_forget` is absent, do not remove nodes.
12
+
13
+ Memory exists to avoid paying twice for durable work. Reuse and verify useful
14
+ prior work; do not treat the graph as an authority or a store for current API
15
+ results.
16
+
17
+ ## Read
18
+
19
+ Search before starting work that costs more than one cheap read or call:
20
+
21
+ - On request arrival, search for the question before planning.
22
+ - On handoff or fork arrival, search for the brief you received.
23
+ - Before a substantial investigation, search for the question it would answer.
24
+ - At a dead end, search for the newly identified missing fact.
25
+
26
+ Do not repeat the same search in different words. Search again only when the
27
+ question has changed.
28
+
29
+ ### Choose the retrieval tool
30
+
31
+ | Need | Tool |
32
+ | ---------------------------------------------- | --------------- |
33
+ | A subject, however it was phrased | `memory_search` |
34
+ | A known name, path, id, host, flag, or command | `memory_grep` |
35
+ | Every occurrence of an exact string | `memory_grep` |
36
+ | The complete content of a returned node | `memory_load` |
37
+
38
+ Use `memory_search` with the complete natural-language question. Narrow broad
39
+ results with `kinds`, `newer_than`, `limit`, `max_hops`, or `max_nodes`.
40
+
41
+ Never use `memory_grep` as a generic first lookup or after an empty semantic
42
+ search. An empty `memory_search` means no semantic match was recalled, not that
43
+ the subject is absent. An empty `memory_grep` establishes only that the exact
44
+ string is absent.
45
+
46
+ Load every node you will rely on. Search results contain clipped descriptions,
47
+ not complete node contents.
48
+
49
+ ### Read recollections as graphs
50
+
51
+ A `<memory-recollection>` is an outline of nodes and relations, not a ranked
52
+ list; the indentation is the graph. A root line reads `score kind id`; a root
53
+ the walk reached without matching carries `--` instead of a score. An indented
54
+ line is a connected node, prefixed by its relation: `→produced` means the line
55
+ above produced it, `←informed` means it informed the line above.
56
+ `PRODUCED`, `CALLS`, and `SUPERSEDES` form the reusable work; `INFORMED` adds
57
+ background. A `+` reference points to an id already shown above.
58
+
59
+ Node text is clipped to 160 characters. A file node adds one line with its
60
+ `/memory/<id>.<ext>` path, size, and use count. Use `memory_load` to obtain the
61
+ complete node and its usable path. Touch only paths returned by a `memory_*`
62
+ tool.
63
+
64
+ Direct store access is prohibited because it bypasses audience controls, may
65
+ serve superseded nodes, does not record use, and can race with another writer.
66
+
67
+ ### Verify before reuse
68
+
69
+ - For a pinned release, versioned specification, or immutable document, verify
70
+ that the recorded source still resolves.
71
+ - For code, APIs, commands, and other living sources, verify the cited location,
72
+ route, or invocation still behaves as recorded.
73
+ - Redo the investigation only when that cheap check fails or the cost of being
74
+ wrong justifies it.
75
+
76
+ Read a remembered script before running it. Confirm its purpose, arguments,
77
+ inputs, outputs, and credentials handling.
78
+
79
+ ### Keep memory out of ordinary answers
80
+
81
+ Report findings and checkable sources, not the mechanism that found them. Do
82
+ not expose `/memory` paths, node ids, or say that something was recalled or
83
+ remembered. The exception is a request about the store itself, where ids and
84
+ memory state are the subject.
85
+
86
+ ## Keep only durable value
87
+
88
+ Commit something only when the next run would otherwise have to do meaningful
89
+ work again and the result should still be valid next month.
90
+
91
+ Keep:
92
+
93
+ - A route, call, command, or invocation that retrieves a current answer.
94
+ - A conclusion assembled from several sources, with every source named.
95
+ - A proven absence, with the complete search boundary named.
96
+ - A reusable plan, request body, query, or verified script.
97
+ - A passage copied from an immutable, pinned source, with provenance.
98
+
99
+ Do not keep:
100
+
101
+ - Raw user input, progress notes, or a restatement of the request.
102
+ - A value available from one cheap current call.
103
+ - Live API results, inventories, counts, or raw command output.
104
+ - Unverified, failed, partial, or speculative work.
105
+ - A copy of a living project file that will silently become stale.
106
+ - A duplicate of a node already returned by search.
107
+
108
+ Remember the route when the answer is cheap and current. Remember the supported
109
+ conclusion when deriving it is expensive. Remember the script, never what its
110
+ last run printed.
111
+
112
+ ## Write the graph
113
+
114
+ A node is one reusable thing. Its `text` is how it is found; an optional file
115
+ holds content too large for one line.
116
+
117
+ | Kind | Use |
118
+ | ------------ | ------------------------------------------------------ |
119
+ | `task` | The request that initiated the work |
120
+ | `plan` | A reusable approach that worked |
121
+ | `fact` | A durable truth with provenance |
122
+ | `snippet` | A few lines intended to be read |
123
+ | `file` | A complete reusable artifact |
124
+ | `operation` | An endpoint, command, or query that was used |
125
+ | `preference` | A standing instruction or user fact stated by the user |
126
+
127
+ | Relation | Meaning |
128
+ | ------------ | ---------------------------------------- |
129
+ | `PRODUCED` | The source produced the target |
130
+ | `CALLS` | The source invokes the target |
131
+ | `SUPERSEDES` | The source replaces the stale target |
132
+ | `INFORMED` | The source was background for the target |
133
+
134
+ Put required reusable work on the `PRODUCED`, `CALLS`, or `SUPERSEDES` spine.
135
+ Use `INFORMED` only for background that may be omitted under a tight recall
136
+ budget. Direct `INFORMED` from the background fact to the work it informed.
137
+
138
+ ### Commit at the right time
139
+
140
+ Commit finished durable work as soon as it is verified. Do not pass any of
141
+ these points with uncommitted reusable work:
142
+
143
+ - Before a final answer.
144
+ - Before a handoff, because control does not return automatically.
145
+ - Before returning from a fork, because only the branch answer rejoins.
146
+
147
+ Commit one connected subgraph in one `memory_commit`. Refs resolve only inside
148
+ that call; splitting connected nodes across calls loses their links.
149
+
150
+ ### Create nodes correctly
151
+
152
+ - Use `ref` as the local name for every new node.
153
+ - Use `id` only for an existing node returned by search or load.
154
+ - Never set both `ref` and `id` on one node.
155
+ - Link the task to what it produced and link artifacts to operations they call.
156
+ - When instructions supply canonical task text, use it verbatim so parallel
157
+ commits fold together.
158
+ - Do not recommit a node that search already returned; link to its existing id.
159
+
160
+ Before creating a recurring entity node such as an endpoint, command, host,
161
+ tool, or file, use `memory_grep` for its exact string. Reuse the existing id
162
+ when found. Do not grep prose subjects or task text merely to avoid semantic
163
+ near-duplicates; normal folding handles those.
164
+
165
+ Write node text as the question a future user will ask. Put identifying facts
166
+ first because recall shows only the first 160 characters. Keep the text short;
167
+ put substantial content in a file node.
168
+
169
+ ### Record provenance
170
+
171
+ Every durable claim must name how it can be checked:
172
+
173
+ - Codebase fact: file and line range.
174
+ - Multi-file conclusion: every file and range used.
175
+ - API behavior: document and operation id, or request and returned status.
176
+ - Document fact: document, heading, and opened line range.
177
+ - Command result: exact command, arguments, and working directory.
178
+ - Negative result: every location and query checked.
179
+
180
+ A pointer without a conclusion makes the next run repeat the reading. A
181
+ conclusion without a pointer cannot be checked. Store both.
182
+
183
+ ### Commit files safely
184
+
185
+ Use a file node for scripts, configurations, request bodies, substantial
186
+ answers, multi-source findings, and passages from pinned sources. The node text
187
+ describes what the file does and its provenance; the file holds the complete
188
+ content.
189
+
190
+ The source file must already exist under `/workspace`. `memory_commit` copies
191
+ it; it does not accept file contents. Never commit files outside the workspace,
192
+ raw logs, live result sets, credentials, unnecessary personal data, or copies
193
+ of living project files.
194
+
195
+ Put provenance in the file itself as a short header. Make executable artifacts
196
+ self-contained, take request-specific values as arguments, read credentials
197
+ from the environment, and accept an output path under `/workspace`. The
198
+ `/memory` mount is read-only.
199
+
200
+ Commit a script only after it ran successfully against the intended environment
201
+ and produced verified output. Commit its invocation and operations, not its
202
+ output. When reusing a remembered script, run it from the path returned by
203
+ `memory_load` only after reading it.
204
+
205
+ A response body or result set may be kept only as an explicit specimen for
206
+ development or reproduction. Its text must say what was requested, when it was
207
+ captured, and that it is historical output rather than a current fact.
208
+
209
+ ### Correct and replace
210
+
211
+ Never edit an existing memory as though its old claim had always been correct.
212
+ Commit the replacement and connect it to the old node with `SUPERSEDES`. Recall
213
+ then hides the stale node while preserving the history.
214
+
215
+ ## Preferences
216
+
217
+ Use `preference` only for a standing instruction or personal fact the user
218
+ explicitly states: wording such as "always", "from now on", "I prefer", or
219
+ "never". Do not infer a preference from one request and never store a secret.
220
+
221
+ Preferences appear in every later prompt. Replace one by committing the new
222
+ preference with a `SUPERSEDES` edge to the old id.
223
+
224
+ ## Forget
225
+
226
+ Use `memory_forget` only for information that should never have been stored and
227
+ has no valid successor. Do not forget a corrected node: superseding already
228
+ hides it and preserves why the correction happened.