@zenera/cli 1.1.19 → 1.1.21

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.
@@ -0,0 +1,151 @@
1
+ ---
2
+ requires: [fork]
3
+ ---
4
+
5
+ # Forking
6
+
7
+ These rules are for agents that can fork. If `fork` is not among your tools,
8
+ work that looks parallel stays sequential here.
9
+
10
+ Forking runs work in separate conversations and brings back only the answers.
11
+
12
+ A branch is a run of its own: its own conversation, its own tool calls, its own
13
+ reasoning. None of that returns. What returns is each branch's final answer, as
14
+ the result of your `fork` call — so whatever you will need afterwards has to be
15
+ _in_ that answer, and the branch only knows it if your instructions say so. Work
16
+ whose value is the trace rather than the conclusion should not be forked at all.
17
+
18
+ The instructions you write are the entire assignment. A branch cannot ask you a
19
+ question, cannot see what its siblings are doing, and cannot be corrected once
20
+ it starts. Say what it must do, what it must leave alone, and the exact shape of
21
+ what it must hand back.
22
+
23
+ **One branch is delegation**: the work happens elsewhere and you get the
24
+ conclusion instead of the transcript. Use it when another agent is better suited
25
+ to the job, or when the job would otherwise fill this conversation with material
26
+ you have no use for afterwards — a long file survey, a noisy build loop, an
27
+ exploration down a path that may go nowhere. **Several branches are a fan-out**:
28
+ independent parts of one task, worked at the same time, merged by you. It is the
29
+ same call either way; the number of branches is the only difference.
30
+
31
+ Do not fork a sequence. Branches run at once and can exchange nothing, so a step
32
+ that needs the step before it has to stay in this conversation.
33
+
34
+ ## When it is worth it
35
+
36
+ One question decides it: **could this be finished by someone who cannot ask you
37
+ anything, and would a written answer be all you want back?** If either half is
38
+ no, the work stays here.
39
+
40
+ | The work in front of you | What it is |
41
+ | -------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
42
+ | The same question asked of twenty things — files, endpoints, regions, candidate fixes | A fan-out: one branch each, merged by you |
43
+ | One task whose parts need different skills and none of them the others | A fan-out too: each branch on the agent that fits |
44
+ | A job another agent is plainly better at | Delegation: one branch, on that agent |
45
+ | Long and noisy with a short verdict — a build loop, a bisect, a survey that may find nothing | Delegation: you get the verdict, not the noise |
46
+ | Find the config, then change it, then test it | Not a fork. Each step needs the one before it |
47
+ | A change you would want to steer while it happens | Not a fork. A branch cannot be corrected once it starts |
48
+ | One read, one search, one command | Not a fork. A whole conversation to save yourself a line |
49
+ | Two jobs that would write the same file | Not a fork until they write different files — see below |
50
+
51
+ ## Fanning out
52
+
53
+ Branches run at the same time, so a fan-out costs about as long as its slowest
54
+ branch instead of the sum of all of them. That alone is reason enough: work you
55
+ would otherwise grind through one item at a time, whose items do not need each
56
+ other, is a fan-out. It is the most ordinary use of this tool.
57
+
58
+ Which agent runs a branch is set per branch, and that is what tells the two
59
+ shapes apart.
60
+
61
+ **One job, many subjects.** The same work repeated over different material, so
62
+ every branch runs the agent that would have done it anyway — usually you. Write
63
+ the assignment once, then vary the subject and the destination:
64
+
65
+ > `auth` — Audit `/workspace/src/auth/**` for calls that bypass the rate
66
+ > limiter. Write the hits to `/workspace/reports/audit-auth.md`, one line each
67
+ > as `file:line — call — why`. Return how many and the worst one.
68
+ >
69
+ > `billing` — The same, over `/workspace/src/billing/**`, to
70
+ > `/workspace/reports/audit-billing.md`.
71
+ >
72
+ > `admin` — The same, over `/workspace/src/admin/**`, to
73
+ > `/workspace/reports/audit-admin.md`.
74
+
75
+ **One job, many trades.** The task divides by what each part demands rather than
76
+ by what it is about, so the branches differ from each other and each names the
77
+ agent that fits:
78
+
79
+ > `tests`, on the agent that runs the suite — Run it against the current tree.
80
+ > Return every failure with the first assertion of each, and nothing else.
81
+ >
82
+ > `security`, on the agent that reviews for security — Review the change in
83
+ > `/workspace/src/auth/**`. Return findings worst first, file and line for each.
84
+ > Change nothing.
85
+ >
86
+ > `docs`, on the writing agent — Bring `/workspace/docs/auth.md` in line with
87
+ > the code as it now stands. Return the path and a one-line note per section you
88
+ > touched.
89
+
90
+ Both shapes hold to the same two rules. Divide so that nothing is covered twice
91
+ and nothing is left out: overlap is paid for twice over, and a gap comes back as
92
+ silence rather than as a complaint. And repeat in each branch's instructions
93
+ whatever that branch needs, because a sibling's finding will never reach it.
94
+
95
+ ## Choosing `context`
96
+
97
+ `context` decides what each branch starts from. It is one setting for the whole
98
+ call, chosen per call:
99
+
100
+ - `inherit` — everything said here so far. For work that only makes sense
101
+ against the case as it stands: reviewing what has just been written here,
102
+ continuing an investigation whose earlier findings are the thing being built
103
+ on.
104
+ - `compact` — the same, without the tool traffic: what was decided, not how it
105
+ was found out. The usual choice for a wide fan-out, where branches need the
106
+ case and the plan but not the fifty reads that produced them.
107
+ - `none` — nothing but its own instructions. The cheapest, and the honest one
108
+ when the assignment is self-contained: a lookup, one file summarised, a
109
+ command run elsewhere. Everything the branch needs must then be written out in
110
+ the instructions, paths included.
111
+
112
+ When two modes seem possible, write the missing facts into the instructions and
113
+ take the cheaper one. Instructions are exact; an inherited transcript is only
114
+ approximately about the branch's job.
115
+
116
+ ## What comes back, and what stays
117
+
118
+ Only the answer comes back, and it is prose. Everything else a branch does is
119
+ real and outlasts it: branches share this workspace with you and with each
120
+ other, so a file one of them writes is a file you can read after the join, and
121
+ anything committed to memory is there for every later run.
122
+
123
+ So decide, for each branch, which of the two carries its result:
124
+
125
+ - **Prose, in the answer** — findings, a verdict, a short list, anything you are
126
+ about to reason with. If it is not in the answer it is gone.
127
+ - **A file, and its path in the answer** — anything bulky, or meant to be used
128
+ rather than read: a generated document, extracted data, a patch, a long log.
129
+ Pasting it into the answer puts it in this conversation whether you need it
130
+ there or not.
131
+
132
+ Say which you want in the branch's own instructions, and be exact:
133
+
134
+ > Read `/workspace/docs/api/*.md` and find every endpoint still documenting the
135
+ > v1 auth header. Write them to `/workspace/reports/v1-auth.md`, one line each
136
+ > as `path — section — the quoted line`. Change nothing else. Return the path,
137
+ > how many you found, and the two you are least sure about.
138
+
139
+ Give every branch a path of its own. Two branches writing one file is a lost
140
+ write that nothing reports — the join reads the same either way. The same holds
141
+ for anything else they could contend over: one branch installing while another
142
+ builds, two branches reformatting the same tree.
143
+
144
+ ## When a branch comes back wrong
145
+
146
+ Each branch reports under its own name, with its status, and a failed one says
147
+ why. What the final answer is remains your decision, not the join's.
148
+
149
+ A branch rarely fails at random; the usual cause is an assignment missing
150
+ something it could not ask for. Re-running the same instructions gets the same
151
+ answer. Fix them and fork again, or do that piece here.
@@ -1,9 +1,18 @@
1
+ ---
2
+ requires: [memory]
3
+ ---
4
+
1
5
  # Memory
2
6
 
3
7
  This project has a memory: a graph of what earlier runs worked out, kept with
4
- the project rather than with the session. It is reached **only** through the
5
- `memory_*` tools - `memory_search` to find, `memory_load` to read,
6
- `memory_commit` to write.
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, `memory_load` to read.
11
+
12
+ Not every agent may write to it. Read what follows against the tools you
13
+ actually have: if `memory_commit` is not among them, everything under
14
+ [Updating it](#updating-it) is not yours to do, and if `memory_forget` is not
15
+ among them, neither is [Forgetting](#forgetting).
7
16
 
8
17
  It exists to make the next run cheaper. Work that cost something - a long
9
18
  investigation, a fan-out of searches, a build, an invocation found by trial -
@@ -51,7 +60,7 @@ runs past a line or two, it is content, and content goes in the file.
51
60
  | `snippet` | a few lines of code or configuration |
52
61
  | `file` | an artifact kept whole - a script to re-run, an answer or passage too big for a text |
53
62
  | `operation` | an external call that was made - endpoint, command, query. The call, not its answer |
54
- | `preference` | a standing instruction from the user |
63
+ | `preference` | a standing instruction from the user, or what they told you about themselves |
55
64
 
56
65
  | Relation | Reads as |
57
66
  | ------------ | --------------------------------------------------- |
@@ -93,6 +102,30 @@ its own source.
93
102
  160 characters. `memory_load` is what reads a node whole, by id - load anything
94
103
  you are going to rely on.
95
104
 
105
+ ### The shape of a recollection
106
+
107
+ A recollection arrives in a `<memory-recollection>` block, and it is a subgraph
108
+ rather than a ranked list - the links are as much of the answer as the nodes. It
109
+ is an outline, and the indentation is the graph.
110
+
111
+ A line at the left margin reads `score kind id` and is something the search
112
+ matched; a root the walk reached rather than matched carries `--` where the
113
+ score would be. A line indented under it reads `<arrow>relation kind id` and is
114
+ a neighbour: `→produced` means the line above produced this one, `←informed`
115
+ means this one informed the line above. A neighbour the search matched in its
116
+ own right carries its score too, after the arrow.
117
+
118
+ Under each header, indented further, is that node's text. A `file` node carries
119
+ one line more, above the text: the path under `/memory` to open or run, its
120
+ size, and how often it has been read.
121
+
122
+ A line beginning `+` is a link to an id already shown above, for an edge the
123
+ outline could not nest. It never points forward, so resolving one only ever
124
+ means looking back up the block.
125
+
126
+ Text is clipped at 160 characters - copy an id into `memory_load` to read a node
127
+ whole. `memory_search` finds ids; it does not return contents.
128
+
96
129
  A remembered file appears at `/memory/<id>.<ext>`. Open it or run it, but arrive
97
130
  at that path through `memory_load`, never by looking around in the directory.
98
131
 
@@ -121,6 +154,19 @@ Search **before** paying for anything: an investigation, an index query, a
121
154
  build, a long command. The point is not to find a pointer - it is to arrive at
122
155
  the answer without buying it twice.
123
156
 
157
+ Four moments are each worth one search:
158
+
159
+ | At | Search for |
160
+ | ---------------------------------------- | ---------------------------------------------------------------------- |
161
+ | a request arriving | the request itself, before the first step is planned |
162
+ | arriving by handoff, or as a fork branch | the brief you were handed - it is new to you, not to the project |
163
+ | the point where real work would start | the question that work would answer, whenever it is more than one call |
164
+ | a dead end mid-run | what you now know you are missing, in the words you would ask it in |
165
+
166
+ Search the QUESTION, not the turn. Asking the same question again in different
167
+ words is a round trip for an answer you already have; search again when what
168
+ you need to know changes, not when the step does.
169
+
124
170
  One `memory_load` is not cheaper than re-reading the single file a node names.
125
171
  It is far cheaper than redoing what produced that node: several documents read
126
172
  in sequence, a fan-out of searches, a delegated lookup, a long run. Price a
@@ -166,10 +212,46 @@ the documents and line ranges it was taken from. The pointer says where to look
166
212
  and the conclusion says what it meant, but only the passage saves the next run
167
213
  from opening the sources to find out what they actually said.
168
214
 
169
- Then the rules for writing it down:
215
+ ### When to commit
216
+
217
+ That test says what is worth keeping. It does not say when to write it down, and
218
+ work that is never written down cost what it cost for nothing.
219
+
220
+ Two things call for a commit while the run is still going:
221
+
222
+ - **A search came back empty, or came back beside the point, and you went on to
223
+ work the answer out anyway.** That gap is the next run's gap too, and you are
224
+ the only one in a position to close it. It is the usual reason a memory stays
225
+ useless: every run pays for the same answer, no run writes it down.
226
+ - **Something cost more than a `memory_load` will** - several reads, a fan-out,
227
+ a build, a long command, a delegated lookup - or produced an artifact that
228
+ works: a script, a query, a request body, the invocation that finally ran.
229
+
230
+ And three moments must not pass without one:
231
+
232
+ | Before | Because |
233
+ | -------------------------------------- | ----------------------------------------------------------------- |
234
+ | returning your final answer | the turn ends there, and nothing is written after it |
235
+ | handing off to another agent | control moves and does not come back - what you know goes with it |
236
+ | returning to the agent that forked you | only your answer returns; your transcript is dropped at the join |
237
+
238
+ Commit a piece of work when it is finished rather than saving all of it for one
239
+ call at the end: a run that is interrupted, or that runs out of room, loses
240
+ whatever was being held back. That is not licence to split one subgraph across
241
+ calls - refs resolve only within a single `memory_commit`, so whatever links
242
+ together is still committed together.
243
+
244
+ ### How to write it down
170
245
 
171
246
  **Commit the whole subgraph in one call.** A script with no record of what asked
172
- for it, or a fact with nothing that acts on it, is a memory nobody can use.
247
+ for it, or a fact with nothing that acts on it, is a memory nobody can use. Refs
248
+ resolve only within a single `memory_commit`, so a subgraph split across calls
249
+ arrives without its links.
250
+
251
+ **Do not re-commit what a search already returned.** A node that says what one
252
+ already in memory says is folded into it, and its existing id comes back under
253
+ your ref - so the links you asked for still land, on the memory that was already
254
+ there.
173
255
 
174
256
  **Say where the content came from.** This is what lets an incomplete
175
257
  recollection be continued instead of believed:
@@ -266,8 +348,8 @@ of it again - which is the reading the memory was supposed to buy.
266
348
  A body or a result set may still be worth keeping as a SPECIMEN - a shape to
267
349
  write against, a case to reproduce. Commit it as a `file` node whose text says
268
350
  what was asked, when, and that it is what came back then, never what the data
269
- is. Keep credentials and personal data out of the store: it outlives the
270
- session and every later run can read it.
351
+ is. Keep credentials out of the store, along with any personal data the specimen
352
+ did not need: it outlives the session and every later run can read it.
271
353
 
272
354
  **Correct by superseding, never by editing.** Commit the new node and link it to
273
355
  the old one with `SUPERSEDES`. Recall then stops serving the wrong answer
@@ -276,3 +358,33 @@ without destroying the record of why it changed.
276
358
  **Ask whether it will still be true next month.** Memory has no expiry and no
277
359
  reviewer. A durable fact about this project survives; a fact about this
278
360
  afternoon's state is how a graph becomes confidently wrong.
361
+
362
+ ### Preferences
363
+
364
+ A `preference` is a standing instruction from the user, and it is not recalled
365
+ like everything else: every preference you can see is rendered into a
366
+ `<memory-preferences>` block at the start of every later run, each with its id.
367
+ They apply unless that run's request contradicts them.
368
+
369
+ So commit one only when the user's own words generalise - "always", "from now
370
+ on", "I prefer", "never". A single request being fulfilled is not a standing
371
+ instruction, and one committed by mistake is in every future prompt until
372
+ something supersedes it.
373
+
374
+ What the user says about THEMSELVES belongs here too, and for the same reason: a
375
+ later run that has to ask again has already lost what the block is for. Their
376
+ name and how they want to be addressed, the role they work in, the timezone
377
+ their dates are in, which of several accounts, environments or repositories is
378
+ theirs, the language or the units they want answers in. Commit what they stated,
379
+ in their own terms - never what you inferred from how they happened to phrase a
380
+ request, and never a credential or a secret, which is not a preference however
381
+ it was offered.
382
+
383
+ To change one, commit the replacement and link it to the id shown in that block
384
+ with `SUPERSEDES`.
385
+
386
+ ### Forgetting
387
+
388
+ Forget only what is wrong and has no successor. A superseded memory is already
389
+ hidden from recall and should stay for the history, so `memory_forget` is for
390
+ what should never have been written, not for what has been replaced.