memgineering 0.4.2 → 0.6.0
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.
- package/CHANGELOG.md +667 -0
- package/NOTICE +22 -0
- package/README.md +32 -8
- package/assets/MEMGINEERING.md +44 -140
- package/assets/memgineering-memory/SKILL.md +44 -303
- package/assets/memgineering-recall/SKILL.md +142 -0
- package/assets/memgineering-rules/SKILL.md +111 -0
- package/assets/memgineering-setup/SKILL.md +184 -105
- package/assets/memgineering-writing/SKILL.md +183 -0
- package/bin/memgineering.js +0 -0
- package/dist/index.js +4981 -1222
- package/package.json +2 -2
- package/scripts/postinstall.mjs +59 -10
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,673 @@ language the reader wants. The bilingual rule the monorepo applies to
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [0.6.0] — 2026-08-16
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **A memory can say it binds.** `memgineering remember "<the decision>" --rule`
|
|
19
|
+
marks something as a decision rather than a fact — a colour you will not use, a
|
|
20
|
+
step never to skip. `memgineering rules` lists what is marked. Ordinary
|
|
21
|
+
observations are untouched, and a note that never mentions this is stored
|
|
22
|
+
exactly as before.
|
|
23
|
+
|
|
24
|
+
- **Your rules turn up before an edit, not after somebody asks.** With the hooks
|
|
25
|
+
installed (`memgineering setup`, Claude Code and Codex), whichever agent is
|
|
26
|
+
working in a folder is handed your marked decisions the first time it goes near
|
|
27
|
+
a file in that session — once, capped at eight lines, silent for the rest of the
|
|
28
|
+
session. It never blocks an edit and never answers whether one is allowed; the
|
|
29
|
+
worst it can do is stay quiet.
|
|
30
|
+
|
|
31
|
+
This exists because the session-start summary alone was measured not to work.
|
|
32
|
+
Twice, a session was given a recorded decision — "this site uses no blue", hex
|
|
33
|
+
codes included — at session start, and shipped a blue page; adding a stronger
|
|
34
|
+
instruction to that opening made the next run worse. A decision has to arrive
|
|
35
|
+
when it is about to be broken.
|
|
36
|
+
|
|
37
|
+
- **`memgineering undo` works on a hosted brain for more than `remember`.** A
|
|
38
|
+
`revise`, `retire` or `unretire` made against a hosted brain could not be taken
|
|
39
|
+
back — the refusal said the reverse patch was "not written yet", which was true
|
|
40
|
+
of nothing: it had been recorded all along and nothing read it. A change to a
|
|
41
|
+
memory that cannot be reversed is the one thing this tool promises never to
|
|
42
|
+
make, and it was making it. The reversal is byte for byte, refuses if the note
|
|
43
|
+
has been written since, and will not run twice.
|
|
44
|
+
|
|
45
|
+
- **Rules work on a hosted brain.** `memgineering rules` lists them and
|
|
46
|
+
`remember --rule` creates them there; both used to answer "a hosted brain does
|
|
47
|
+
not store the marking yet", which was true of the schema and false of the note —
|
|
48
|
+
a hosted brain keeps the whole text, so the marking arrived with every push and
|
|
49
|
+
nothing read it. Pushing a brain holding five standing decisions produced a
|
|
50
|
+
rules list of zero. Rules already pushed are backfilled, so they appear without
|
|
51
|
+
anyone re-writing them.
|
|
52
|
+
|
|
53
|
+
The before-edit hook still reads a brain on this machine: a network call on the
|
|
54
|
+
path of every file write is not a trade worth making. On a machine pointed at a
|
|
55
|
+
hosted brain, `memgineering rules --local` is what the hook will actually
|
|
56
|
+
deliver.
|
|
57
|
+
|
|
58
|
+
- **A memory can become a rule after it was written**, on a brain in a folder or
|
|
59
|
+
a hosted one. `memgineering revise <ref> --rule` marks an existing memory as a
|
|
60
|
+
decision that binds, and `--no-rule` stops it being one; leaving both off
|
|
61
|
+
changes nothing, as before. Until now the marking was fixed at the moment a note
|
|
62
|
+
was created, which is the wrong moment — a conclusion usually becomes a rule
|
|
63
|
+
later, when it changes.
|
|
64
|
+
|
|
65
|
+
The hosted half briefly shipped as the worst version of this: the command took
|
|
66
|
+
the flag, sent nothing, and reported success, so a rule somebody had just turned
|
|
67
|
+
off was still a rule and nothing said so. It carries now.
|
|
68
|
+
|
|
69
|
+
- **`memgineering use --json` says where the next write goes.** `destination` is
|
|
70
|
+
`"hosted"`, `"local"`, or `"pending"` — the third meaning a sign-in is waiting
|
|
71
|
+
to be approved, so writes land in `brain` until then and in `hosted` after
|
|
72
|
+
(`destination_until_approved` names the first half). `hosted.sign_in_pending`
|
|
73
|
+
carries the same distinction as a boolean. `hosted.signed_in` alone cannot
|
|
74
|
+
answer the question: it is false for both the logged-out and the waiting
|
|
75
|
+
state, and those land in different places.
|
|
76
|
+
|
|
77
|
+
- **`memgineering log --json` carries `superseded` on every operation**, on a
|
|
78
|
+
brain in a folder and a hosted one alike. It is what the printed line uses to
|
|
79
|
+
decide whether to offer `undo`, and a caller reading the structured output had
|
|
80
|
+
no way to reach the same conclusion.
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
|
|
84
|
+
- **A large push is no longer stopped by the server's rate limit.** The server
|
|
85
|
+
allows 300 requests a minute and `push` sends one per note, in order, so a brain
|
|
86
|
+
past that size climbed to the ceiling and stopped part-way — some notes across,
|
|
87
|
+
some not. A refusal is now waited out and the note re-sent, up to a bounded
|
|
88
|
+
number of times, and the pause says why once rather than going quiet. Only
|
|
89
|
+
`429` is retried: it means the request was refused, so nothing was written and
|
|
90
|
+
repeating it cannot double anything.
|
|
91
|
+
|
|
92
|
+
- **A hook can no longer hold your session open.** Both callbacks now give up
|
|
93
|
+
after five seconds and print nothing, and the hook `setup` installs carries a
|
|
94
|
+
timeout for the host to enforce as well. Neither existed before, and the gap was
|
|
95
|
+
not theoretical: a brain kept in a folder the OS syncs to the cloud, whose notes
|
|
96
|
+
had been evicted and would not come back, blocked `resurface` for over two
|
|
97
|
+
minutes — at the start of every session, because that is when it runs. Run by
|
|
98
|
+
hand, `resurface` still waits as long as your brain takes; you asked for it and
|
|
99
|
+
you are watching.
|
|
100
|
+
|
|
101
|
+
- **`memgineering setup --agent --hook off` now removes the callbacks.** It used
|
|
102
|
+
to skip installing them, which is right on a machine that never had them and
|
|
103
|
+
wrong on every machine that did — so the hooks stayed armed under a report that
|
|
104
|
+
had just printed "Turn it back off with `--hook off`". Only the groups
|
|
105
|
+
memgineering wrote are taken out; every other hook and setting in that file is
|
|
106
|
+
left exactly as it was, and a settings file that cannot be parsed is reported
|
|
107
|
+
rather than passed over in silence.
|
|
108
|
+
|
|
109
|
+
- **A guide whose markers were deleted no longer duplicates in silence.** Without
|
|
110
|
+
`<!-- memgineering-start -->` and `<!-- memgineering-end -->` the file read as
|
|
111
|
+
"never installed", so a second copy of the whole guide was appended — into every
|
|
112
|
+
session, permanently, with nothing to detect it.
|
|
113
|
+
|
|
114
|
+
Where setup can prove it wrote that file, it now skips it, names it, finishes
|
|
115
|
+
the rest of the run, and exits non-zero. Where it cannot — an install from a
|
|
116
|
+
release before this one, or a machine whose config is gone — it installs anyway,
|
|
117
|
+
because refusing there would make a first install impossible for anyone whose
|
|
118
|
+
own notes happen to use the same two verbs, and says so: "Appended below an
|
|
119
|
+
unmarked guide", with what to check. Losing only the end marker still repairs
|
|
120
|
+
itself.
|
|
121
|
+
|
|
122
|
+
- **Replacing something you edited is said out loud.** setup owns the guide block
|
|
123
|
+
and the skill files, so an upgrade overwrites them; it now records what it wrote
|
|
124
|
+
and tells you when what it replaced was not that. Ordinary upgrades stay quiet.
|
|
125
|
+
|
|
126
|
+
- **A flag that does not exist now says what does.** An unknown option used to
|
|
127
|
+
answer with one line and nothing to act on, and the recovery — opening the help
|
|
128
|
+
page — costs ten times what the answer does. The error now lists the command's
|
|
129
|
+
flags inline, and near-misses get a "did you mean" as well.
|
|
130
|
+
|
|
131
|
+
- **Codex gets both callbacks too.** `memgineering setup --hook on` now writes
|
|
132
|
+
them to `~/.codex/hooks.json` as well as Claude Code's settings, with a matcher
|
|
133
|
+
naming the tools Codex actually reports (`apply_patch` and `Bash` — it has no
|
|
134
|
+
Read or Grep tool, so its reading is a shell call). Codex was previously listed
|
|
135
|
+
as unable to run either one; a live session showed otherwise, including that
|
|
136
|
+
the before-edit hook's context reaches the model. One difference worth knowing:
|
|
137
|
+
Codex asks you to review new hooks once, at the start of the next session, and
|
|
138
|
+
runs nothing until you answer — the setup report now says so.
|
|
139
|
+
|
|
140
|
+
- **Grok is a supported tool.** `memgineering setup` installs the guide into
|
|
141
|
+
`~/.grok/rules/memgineering.md` and the skills into `~/.grok/skills/`, and Grok
|
|
142
|
+
loads both on its own.
|
|
143
|
+
|
|
144
|
+
Your rules reach it at the end of a turn rather than before an edit, and that
|
|
145
|
+
is the most the host allows. Three of Grok's hook events were each tried with a
|
|
146
|
+
value the session could not otherwise know — `PreToolUse` with
|
|
147
|
+
`additionalContext`, `SessionStart` stdout, `UserPromptSubmit` with
|
|
148
|
+
`additionalContext` — and all three hooks ran while none of the three arrived.
|
|
149
|
+
`Stop` does arrive. So the rules land as the turn finishes: too late for what
|
|
150
|
+
that turn already wrote, in time for everything after it. It costs one extra
|
|
151
|
+
round, once a session, because speaking there keeps the agent working.
|
|
152
|
+
`resurface` gets no hook on Grok at all; the guide asks for it instead.
|
|
153
|
+
|
|
154
|
+
- **The third tool is called Antigravity now.** Gemini CLI is discontinued and
|
|
155
|
+
Antigravity CLI took its place, keeping the same home — a line planted in
|
|
156
|
+
`~/.gemini/GEMINI.md` came back out of an `agy` session word for word, and one
|
|
157
|
+
planted in `~/.antigravity/` did not. So nothing moves: the guide and the
|
|
158
|
+
skills install exactly where they did, `--tools gemini` still selects it, and
|
|
159
|
+
only the name shown to you changes. It still has no hooks, so its skills tell
|
|
160
|
+
its agent to run `resurface` and `rules` itself.
|
|
161
|
+
|
|
162
|
+
- `memgineering setup --hook on` now arms two callbacks instead of one, and the
|
|
163
|
+
report names both. `--hook off` still installs neither.
|
|
164
|
+
|
|
165
|
+
- `sync-rules` is described as copying the brain's **read/index exclusions**,
|
|
166
|
+
which is what it has always copied. "Rules" alone now has another owner.
|
|
167
|
+
|
|
168
|
+
- **The bundled skills are English throughout, including their trigger
|
|
169
|
+
phrases.** 0.5.0 shipped a handful of Korean phrases in those triggers, so a
|
|
170
|
+
Korean speaker's agent could match a skill from the words they actually used;
|
|
171
|
+
everyone else got a package with one arbitrary second language in it. Picking
|
|
172
|
+
the trigger language at `setup` time is the right answer and is not built yet,
|
|
173
|
+
so until it is, the phrases are English.
|
|
174
|
+
|
|
175
|
+
Measured before saying so: the same Korean request that used to open a skill
|
|
176
|
+
still opens it with only English phrases installed, and six Korean requests
|
|
177
|
+
across two shapes were all handled correctly. A description is read by a model
|
|
178
|
+
that knows the language either way — the phrases name the situation, not the
|
|
179
|
+
wording. Asking for your memory in Korean still works.
|
|
180
|
+
|
|
181
|
+
- **The guidance now says a fact has to be checked, not worked out.** A session
|
|
182
|
+
that reads an address, an identifier or a version and then reasons its way to a
|
|
183
|
+
different one can write that reasoning into the brain as fact, where every later
|
|
184
|
+
session recalls it as one. A guess in a file turns up in a diff; a guess in a
|
|
185
|
+
memory does not. Two sentences, in the hub and in `memgineering-writing`: a
|
|
186
|
+
decision is whatever the user says it is, and anything a command or a file could
|
|
187
|
+
confirm goes in verified or not at all.
|
|
188
|
+
|
|
189
|
+
- **Tools that nothing calls for them now get told so.** On Antigravity — which
|
|
190
|
+
loads no skills of its own, measured — the installed guide was a router
|
|
191
|
+
pointing at five skills that were never opened, so a brain full of answers went
|
|
192
|
+
unread across a whole session. `setup` now appends two lines to the guide it
|
|
193
|
+
writes for any tool with no session hook: run `memgineering resurface` when you
|
|
194
|
+
start work in a folder, and `memgineering rules` before changing a file. Tools
|
|
195
|
+
that do get called back are unchanged, and see nothing extra.
|
|
196
|
+
|
|
197
|
+
Measured on the same task before and after: no memory calls and a generic
|
|
198
|
+
answer, then `resurface` + `rules`, the right answer, and the decision recorded
|
|
199
|
+
as a rule without being asked.
|
|
200
|
+
|
|
201
|
+
### Fixed
|
|
202
|
+
|
|
203
|
+
- **Everything on the install screen is drawn by the same hand.** The
|
|
204
|
+
comparison's row rules were 1px hairlines running directly underneath
|
|
205
|
+
hand-drawn frames — the only straight edges on the page, and the first thing
|
|
206
|
+
the eye found. Rules, the recommended badge and the checkboxes are drawn now,
|
|
207
|
+
and hovering a drawn control makes its outline quiver in place the way the
|
|
208
|
+
site's do, instead of repainting a background the way nothing else in the
|
|
209
|
+
product does. Reduced-motion settings hold it to a single frame.
|
|
210
|
+
|
|
211
|
+
- **The first install screen stops asking you to match a table to a pair of
|
|
212
|
+
cards.** It compared "this machine only" against "in an account" in a table,
|
|
213
|
+
and then offered the choice underneath as two cards — in the opposite order to
|
|
214
|
+
the columns, worded differently from the column headers. Someone seeing it for
|
|
215
|
+
the first time could not tell which card the left column was about, which is
|
|
216
|
+
the one thing that screen exists to make obvious. The two answers are now the
|
|
217
|
+
table's own column headers: picking one paints its whole column, so every row
|
|
218
|
+
is read against the answer it belongs to. The recommended one is first in both
|
|
219
|
+
senses, because there is only one order left to be first in.
|
|
220
|
+
|
|
221
|
+
- **The Korean install screen is written the way the rest of it should have
|
|
222
|
+
been.** Every sentence moved to 해요체 and lost the clauses it did not need —
|
|
223
|
+
the register a person deciding something is spoken to, rather than one being
|
|
224
|
+
informed of a decision. The draft terms moved with it; a policy nobody can read
|
|
225
|
+
is not a stricter policy.
|
|
226
|
+
|
|
227
|
+
- **A rule about a command now actually arrives.** The before-edit hook is
|
|
228
|
+
installed with a tool matcher, and `Bash` was not in it — so a decision about
|
|
229
|
+
committing, deleting or deploying could never be shown, because those are shell
|
|
230
|
+
calls. A fresh agent asked to make "never put emoji in commit messages" stick
|
|
231
|
+
ran its whole task through `Bash` and was handed that rule zero times. The
|
|
232
|
+
matcher already carried `Read`, `Glob` and `Grep`, none of which writes
|
|
233
|
+
anything, so waiting for a "file tool" was never waiting for a write.
|
|
234
|
+
**Re-run `memgineering setup` to pick this up** — the matcher lives in your
|
|
235
|
+
tool's settings and an upgrade alone does not rewrite it.
|
|
236
|
+
|
|
237
|
+
- **Renaming your notes folder no longer makes your rules disappear.** When the
|
|
238
|
+
brain you set as default is not on disk, everything falls through to the one
|
|
239
|
+
that is — deliberate, so an unmounted drive does not stop you working. Nothing
|
|
240
|
+
said it had happened, so `rules` answered from the other brain with "no
|
|
241
|
+
standing decisions recorded", which reads as "I never wrote any down" and gets
|
|
242
|
+
acted on by writing them again, into a brain that is not the one you lost.
|
|
243
|
+
`use` said "because it is the only brain linked" while two were linked.
|
|
244
|
+
`rules`, `use` and `resurface` now name the folder they could not reach, say
|
|
245
|
+
the answer came from somewhere else, say nothing is lost, and give the one
|
|
246
|
+
command that fixes it. Silent when your default is fine.
|
|
247
|
+
|
|
248
|
+
- **The sign-in screens are on memgineering.com.** Approving a sign-in used to
|
|
249
|
+
happen on `api.memgineering.com`, an API subdomain, on a page built from
|
|
250
|
+
colours that matched nothing else in the product. Approval, the refusals and
|
|
251
|
+
the "you're done" screen are now all at `memgineering.com/auth/device`, drawn
|
|
252
|
+
from the same stylesheet as the rest of the site. Nothing changes in the CLI —
|
|
253
|
+
`login` opens whichever address the server hands it.
|
|
254
|
+
|
|
255
|
+
- **The install screen draws itself again.** `memgineering setup --web` serves one
|
|
256
|
+
self-contained page under `default-src 'none'`, and that policy named no
|
|
257
|
+
`img-src` and no `font-src` — so the browser silently dropped every asset the
|
|
258
|
+
page was carrying inside itself. The hand-drawn borders around the cards, the
|
|
259
|
+
inputs and the buttons never painted, and neither did the typeface. On the
|
|
260
|
+
account step this cost the reader the way forward: the `Next` button is drawn
|
|
261
|
+
rather than filled with a colour, so it rendered as an invisible rectangle with
|
|
262
|
+
a label the same shade as the page. The policy now permits `data:` for images
|
|
263
|
+
and fonts, and nothing else — no host, no scheme, no wildcard — so the screen
|
|
264
|
+
still opens with the machine offline. A test now reads the page for the
|
|
265
|
+
schemes it actually uses and asks the policy about each one, which is the
|
|
266
|
+
comparison nobody was making: both files were correct about themselves.
|
|
267
|
+
|
|
268
|
+
- **A hosted brain shows why a memory changed, in the output you get without
|
|
269
|
+
asking.** Every write is told to carry a `--reason`, on the argument that it is
|
|
270
|
+
the only part of the record still worth anything six months later — and then
|
|
271
|
+
neither read command printed one. On a hosted brain, `memgineering evidence`
|
|
272
|
+
answered with `surfaced 8 · opened 4` and stopped, and `memgineering log` gave a
|
|
273
|
+
timestamp and a path. The reasons had been in the response all along, and in
|
|
274
|
+
`--json`, so nothing was lost; it was simply never shown, which for a default
|
|
275
|
+
output is the same thing.
|
|
276
|
+
|
|
277
|
+
Both commands now print the same report from a hosted brain that they print
|
|
278
|
+
from one on your disk: the title, the standing and what it means, the ledger,
|
|
279
|
+
and the reason quoted. `log` additionally shows who made each change, whether
|
|
280
|
+
it was already undone, and whether the note has moved on since — all of which
|
|
281
|
+
the server was sending and the client was discarding.
|
|
282
|
+
|
|
283
|
+
- **`memgineering use` named the wrong brain.** Signed in and pointed at a
|
|
284
|
+
hosted brain, it reported the folder on this disk — a real folder, that
|
|
285
|
+
nothing had written to in weeks — while every `recall` and `remember` went to
|
|
286
|
+
the server. Naming the wrong destination is the one thing this tool cannot do:
|
|
287
|
+
nothing about the answer looks wrong until somebody goes looking for a note
|
|
288
|
+
that was never written there.
|
|
289
|
+
|
|
290
|
+
It now answers with whichever brain the next command will actually use, in all
|
|
291
|
+
three states: the hosted one when signed in; the folder when the pointer is
|
|
292
|
+
there but the sign-in is not, because that is where writes land; and, when a
|
|
293
|
+
sign-in is merely waiting to be approved, both — the folder until somebody
|
|
294
|
+
approves it, the hosted brain after. It reads state off the disk, so it
|
|
295
|
+
answers with the server down and it never completes a sign-in as a side
|
|
296
|
+
effect of being asked a question. See the `--json` fields under Added.
|
|
297
|
+
|
|
298
|
+
- **`memgineering pull` uses the brain this machine is pointed at.** It was the
|
|
299
|
+
only hosted verb that could not answer "which brain" from state every other
|
|
300
|
+
verb reads, so on an account with two, the command somebody runs to back up
|
|
301
|
+
the brain they had been using all session answered "more than one hosted brain
|
|
302
|
+
— say which". `--brain` still wins, an unpointed machine with two brains still
|
|
303
|
+
gets the refusal, and the success line now names the brain it downloaded.
|
|
304
|
+
|
|
305
|
+
- **`memgineering pull` says which of your brains the folder does not contain.**
|
|
306
|
+
A tester pulled, was told 21 notes had arrived, and had no reason to doubt it —
|
|
307
|
+
the other 45 of their 66 were in a second hosted brain on the same account, and
|
|
308
|
+
a successful run never mentioned that it existed. A backup nobody knows is
|
|
309
|
+
partial is worse than one that failed. Both the real run and `--dry-run` now
|
|
310
|
+
name the other brains and give a command that fetches one; `--json` carries
|
|
311
|
+
`other_brains` and a hint saying not to call this a backup until each has been
|
|
312
|
+
pulled.
|
|
313
|
+
|
|
314
|
+
- **Asking where an install stands no longer means running the command that
|
|
315
|
+
installs.** There is no `status` verb, and the answer lives behind
|
|
316
|
+
`memgineering setup --agent --dry-run`, which writes nothing. A tester looking
|
|
317
|
+
for it either avoided `setup` — whose name says it installs — and got no
|
|
318
|
+
answer, or ran it and changed something to find out. `--help` now names the
|
|
319
|
+
dry run on the `setup` line, and the setup skill collects the three read-only
|
|
320
|
+
questions (`setup --dry-run`, `whoami`, `use`) in one place. It also names
|
|
321
|
+
`memgineering guard` as the hook's entry point, which stays out of `--help` on
|
|
322
|
+
purpose: it reads a hook payload on stdin and does nothing without one.
|
|
323
|
+
|
|
324
|
+
- **A question asked as a sentence is told what `recall` actually matched.**
|
|
325
|
+
"Only titles, aliases and summaries are searched" printed on zero results only
|
|
326
|
+
— the one case where there is nothing to misread. Asked as a whole sentence,
|
|
327
|
+
recall can return notes that share a single ordinary word with the question,
|
|
328
|
+
and every card reads `stated` with nothing to say the match was on "not"
|
|
329
|
+
rather than on the subject. That sentence now also appears under the results
|
|
330
|
+
when the query is a question or four words or more. It is not a warning: this
|
|
331
|
+
cannot know whether the results are any good, and a ⚠ over a right answer is
|
|
332
|
+
how a reader learns to skip the line.
|
|
333
|
+
|
|
334
|
+
- **A hosted card with no age no longer reads `NaN years ago`.** The guard
|
|
335
|
+
tested for `null` and a server that omits the field sends `undefined`, so a
|
|
336
|
+
real answer arrived wearing a number that was not one.
|
|
337
|
+
|
|
338
|
+
- **`memgineering recall` says which results are decisions you already made.**
|
|
339
|
+
`resurface` has labelled them "a standing decision" since rules existed, and
|
|
340
|
+
`recall` — the verb an agent reaches for far more often — returned a decision
|
|
341
|
+
and an ordinary observation looking identical. A brain with five standing
|
|
342
|
+
decisions in it could answer a question without saying which of the answers
|
|
343
|
+
the user had already committed to. The card now says so, and `--json` carries
|
|
344
|
+
a `binding` field on every card: present and `false` on an ordinary memory, so
|
|
345
|
+
a caller can tell "not a rule" from "this version does not say".
|
|
346
|
+
|
|
347
|
+
A hosted brain shows this once its server is updated; nothing breaks in the
|
|
348
|
+
meantime, the label is simply absent.
|
|
349
|
+
|
|
350
|
+
- **An id from `memgineering log` no longer looks like one from `recall`.** They
|
|
351
|
+
are the same length in the same alphabet, arrive in the same backticks, and
|
|
352
|
+
nothing said which was which — so an agent read an operation id off `log`, ran
|
|
353
|
+
`open` on it, and was told "nothing here matches — try searching". No search
|
|
354
|
+
can return an operation id. `log` now labels each one `undo:`, and `op:`
|
|
355
|
+
wherever `undo` would refuse it: an operation already undone, one that is
|
|
356
|
+
itself an undo, one whose note has been written since, or a verb that brain
|
|
357
|
+
cannot reverse — a hosted brain cannot reverse an `exclude`, and neither side
|
|
358
|
+
reverses an `import`. Fed one anyway, `open` says what the id is, which change
|
|
359
|
+
it names, the note it touched, and how to read that note; a truncated id works
|
|
360
|
+
there too, since `undo` accepts one.
|
|
361
|
+
|
|
362
|
+
- **`memgineering log` no longer warns that notes changed when they did not.**
|
|
363
|
+
It checked each operation's file through the note reader, which refuses
|
|
364
|
+
excluded and deny-listed paths — and read that refusal as "the file is gone".
|
|
365
|
+
So every `exclude` anybody ran was reported as changed (its target is
|
|
366
|
+
`.memgignore`, which is deny-listed), and so was the entire history of any
|
|
367
|
+
note that had been excluded. Separately, the divergence check was handed the
|
|
368
|
+
rows newest-first while it keeps the last one it sees per note, so it compared
|
|
369
|
+
against the OLDEST operation — an ordinary remember-then-revise reported the
|
|
370
|
+
note as edited outside the tool, about the tool's own write. Measured in each
|
|
371
|
+
case: the warning appeared and `undo` reversed the operation happily.
|
|
372
|
+
|
|
373
|
+
- **A crafted name from a hosted brain can no longer rewrite your terminal.**
|
|
374
|
+
Titles, paths, handles, brain names, account names, ranking reasons and server
|
|
375
|
+
hints were printed as they arrived, so a string containing terminal escape
|
|
376
|
+
sequences could erase the lines above it, move the cursor, or plant a
|
|
377
|
+
clickable link that goes somewhere else. `pull` was worse than a rendering
|
|
378
|
+
bug: with no destination given it names the folder after the brain, so a
|
|
379
|
+
crafted name created a directory on your disk carrying those bytes.
|
|
380
|
+
|
|
381
|
+
Every command that renders one of these strings now strips it — `recall`
|
|
382
|
+
(cards and the contradictions block), `open`, `evidence`, `log`, `resurface`,
|
|
383
|
+
`rules`, `remember`, `revise`, `undo`, `retire`, `unretire`, `exclude`,
|
|
384
|
+
`unexclude`, `use`, `whoami`, `push`, `pull`, `login`, `setup`'s sign-in step,
|
|
385
|
+
`update`, `link`'s previews, and the error output. Handles are stripped where
|
|
386
|
+
they are built rather than where they are printed, because a handle this tool
|
|
387
|
+
did not mint is the note's own `id:` field and there are a dozen places that
|
|
388
|
+
print one.
|
|
389
|
+
|
|
390
|
+
A brain in a folder gets the same treatment, and it took three passes to mean
|
|
391
|
+
it. The first sweep drove only each verb's hosted half, so a local note's
|
|
392
|
+
title, path, claim, scope, headings and ledger target still reached the
|
|
393
|
+
terminal. Patching those by hand missed five more, and the round after that
|
|
394
|
+
missed six — which is what finally replaced "check each one" with mutation
|
|
395
|
+
testing: break one strip, and a suite has to go red. `stripControl` says why
|
|
396
|
+
this is in scope at all — a folder brain can have synced from another machine
|
|
397
|
+
or be written by a team — and a note that arrived over Dropbox is as much
|
|
398
|
+
somebody else's writing as one that arrived over HTTPS.
|
|
399
|
+
|
|
400
|
+
Two suites drive it, one per brain, against notes and responses poisoned at
|
|
401
|
+
both ends of every string: eighteen local surfaces and eighteen hosted ones,
|
|
402
|
+
plus three server replies the fixture previously could not produce — a
|
|
403
|
+
reversal the server cannot describe, a curation that changed nothing, and a
|
|
404
|
+
recall carrying a contradiction.
|
|
405
|
+
|
|
406
|
+
Coverage is stated as measured rather than asserted. Breaking each of the 120
|
|
407
|
+
strips one at a time and re-running the suite, 92 are caught by a test. Of the
|
|
408
|
+
28 that are not, most cannot be: `revise`'s diff renders YAML source, and the
|
|
409
|
+
serializer has already turned any control character into the four letters
|
|
410
|
+
`\x1b` before it reaches a screen; `open`'s claim line prints two enums;
|
|
411
|
+
`.memgignore` refuses a path with control characters before the branch that
|
|
412
|
+
would echo one; ids and error codes are excluded from the poisoned fixture on
|
|
413
|
+
purpose, since a caller passes an id back as a selector and branches on a code.
|
|
414
|
+
What is left genuinely untested is small and named: the browser consent screen,
|
|
415
|
+
which needs a terminal; the two `login` lines that need a browser to open and a
|
|
416
|
+
device flow to be approved; and a handful of second arms only a particular
|
|
417
|
+
server reply produces. Saying "every command is covered" was wrong four
|
|
418
|
+
releases running, so this says the number instead.
|
|
419
|
+
|
|
420
|
+
### Agent guidance
|
|
421
|
+
|
|
422
|
+
- **Re-run `memgineering setup` after upgrading, then restart the
|
|
423
|
+
conversation.** Two things this release changes live outside the package: the
|
|
424
|
+
guidance block in your tool's instructions file, and the before-edit hook's
|
|
425
|
+
tool matcher — which gains `Bash`, without which a rule about a command is
|
|
426
|
+
never shown. Upgrading the CLI rewrites neither; `setup` does. The restart is
|
|
427
|
+
because the guidance is read once, when a conversation starts.
|
|
428
|
+
|
|
429
|
+
- **The block memgineering writes into your `CLAUDE.md` is now a third of the
|
|
430
|
+
size** — 178 lines to 52, and no command syntax at all. That block is in your
|
|
431
|
+
agent's context for every session forever, and it had grown into a second copy
|
|
432
|
+
of a manual that already existed as an on-demand skill. What it keeps is what
|
|
433
|
+
has to be true before any skill loads: what a brain is, which tools this
|
|
434
|
+
actually reaches, when to reach for it, and where the detail is.
|
|
435
|
+
|
|
436
|
+
- **Five skills instead of two.** `memgineering-memory` is now the map — which
|
|
437
|
+
verb answers which question — and points at `memgineering-recall` (recall,
|
|
438
|
+
open, evidence, resurface), `memgineering-writing` (remember, revise, undo,
|
|
439
|
+
retire, exclude, filling in `01_BASE/`), `memgineering-rules` (`--rule`, the
|
|
440
|
+
eight-slot budget, what the before-edit hook shows) and `memgineering-setup`,
|
|
441
|
+
which gains `push`/`pull`. Nothing was dropped; `resurface` had been explained
|
|
442
|
+
twice and now is explained once.
|
|
443
|
+
|
|
444
|
+
- `MEMGINEERING.md` 0.2.0 → 0.4.0, covering `--rule`: what counts as a decision,
|
|
445
|
+
and that a user saying "from now on" or "never" is making one without using
|
|
446
|
+
the word. **Restart your agent session after upgrading** so the new guidance
|
|
447
|
+
is read.
|
|
448
|
+
|
|
449
|
+
## [0.5.0] — 2026-08-12
|
|
450
|
+
|
|
451
|
+
### Added
|
|
452
|
+
|
|
453
|
+
- **Every command works on a hosted brain.** `revise`, `resurface`, `retire`,
|
|
454
|
+
`unretire`, `exclude` and `unexclude` used to refuse when this machine was
|
|
455
|
+
pointed at a hosted brain and tell you to add `--local`. They go to the server
|
|
456
|
+
now. Nothing memgineering offers says no because your brain is not on this
|
|
457
|
+
disk.
|
|
458
|
+
|
|
459
|
+
- **The setup screen starts with where your memory goes.**
|
|
460
|
+
`memgineering setup --web` used to open a Google sign-in before it showed you
|
|
461
|
+
anything, so the first thing you saw was a consent page for a product that
|
|
462
|
+
had not told you what it was. It now opens on the choice — what memgineering is in one
|
|
463
|
+
sentence, then a plain comparison of keeping the memory on this machine
|
|
464
|
+
against keeping it in an account, and what each costs. One brain is free, and
|
|
465
|
+
stays free. The sign-in only starts once you have picked it, and the code to
|
|
466
|
+
approve is shown on the last screen. Draft terms and a privacy draft are
|
|
467
|
+
reachable from the same screen; they are marked as drafts because they have
|
|
468
|
+
not been through legal review.
|
|
469
|
+
|
|
470
|
+
- **`memgineering pull [folder]`** — download your hosted brain back to this
|
|
471
|
+
machine, as the markdown it is. Until now notes went up and nothing came back,
|
|
472
|
+
so "your memory is yours" stopped being demonstrable the moment you used the
|
|
473
|
+
hosted side. It **never overwrites**: a file already at that path is left
|
|
474
|
+
exactly as it is and reported as skipped, which is what makes it safe to point
|
|
475
|
+
at the wrong folder and what makes an interrupted download finishable by
|
|
476
|
+
running the command again. Notes your rules exclude come down too — excluded
|
|
477
|
+
means "stop reading this", not "this is no longer yours" — and `.memgignore`
|
|
478
|
+
travels with them, so the folder does not silently un-exclude anything. The
|
|
479
|
+
result is plain markdown; `memgineering link <folder>` is what turns it into a
|
|
480
|
+
brain on this machine, and it is not done for you. `--dry-run` lists what would
|
|
481
|
+
be written without writing it.
|
|
482
|
+
|
|
483
|
+
- **`memgineering push`** — upload the brain on this machine to your hosted one,
|
|
484
|
+
keeping every note at the path it already had. Nothing is deleted locally, a
|
|
485
|
+
note already up there is counted as already up there rather than as a failure
|
|
486
|
+
(so an interrupted upload is finished by running the command again), and any
|
|
487
|
+
note the server refuses is listed in the summary instead of quietly dropped
|
|
488
|
+
from the count. `--dry-run` lists what would go without sending anything.
|
|
489
|
+
|
|
490
|
+
### Changed
|
|
491
|
+
|
|
492
|
+
- **Setup no longer decides about accounts behind your back.** Run by an agent,
|
|
493
|
+
it skipped sign-in and said nothing — so you got a folder on one machine and
|
|
494
|
+
found out later that your memory does not follow you. It now says plainly that
|
|
495
|
+
no account was used and how to connect one, and the install tells your agent to
|
|
496
|
+
ask you first: memory on this machine, or synced across your devices and tools.
|
|
497
|
+
|
|
498
|
+
- **After install, your agent finishes the job.** Installing used to print
|
|
499
|
+
`Next: memgineering setup` — which agents dutifully relayed to their user as a
|
|
500
|
+
command to type, in a product whose whole premise is that the agent does this
|
|
501
|
+
for you. The install now tells the agent to ask you one question — should it
|
|
502
|
+
set things up, or would you rather choose on a screen — and then run setup
|
|
503
|
+
itself. The message is also no longer suppressed when output is piped, which
|
|
504
|
+
is exactly the case where an agent is the one reading it.
|
|
505
|
+
|
|
506
|
+
- **`--local` still does exactly what it did.** The product works with no
|
|
507
|
+
server: pass `--local` to any command and it reads and writes the folder on
|
|
508
|
+
this machine, whether or not you are signed in.
|
|
509
|
+
|
|
510
|
+
- **A hosted `resurface` says what it ranked by.** It has three signals where a
|
|
511
|
+
local brain has four — it cannot know which folder you asked from, because the
|
|
512
|
+
server records what was recalled and never where you were standing. The output
|
|
513
|
+
names the signals it used rather than leaving you to notice that "recalled 14×
|
|
514
|
+
in this folder" stopped appearing.
|
|
515
|
+
|
|
516
|
+
- **`revise --input` is refused against a hosted brain**, rather than partly
|
|
517
|
+
honoured. The JSON can name a different memory and set fields the flags do not
|
|
518
|
+
expose, so sending only the understood parts would report a success for a
|
|
519
|
+
change you did not ask for. Pass the change as flags, or use `--local`.
|
|
520
|
+
|
|
521
|
+
- **What you exclude travels with your brain.** The rules live in a
|
|
522
|
+
`.memgignore` file inside the brain rather than in a setting beside it, so a
|
|
523
|
+
hosted brain pulled back down to a folder is still scoped the way you scoped
|
|
524
|
+
it. `undo` for an exclusion is `unexclude`, not `undo <op_id>`.
|
|
525
|
+
|
|
526
|
+
- **`memgineering login`, `logout` and `whoami`** — sign in to a hosted brain.
|
|
527
|
+
Optional, and nothing that already worked needs it: a brain is still a folder
|
|
528
|
+
of markdown files on your machine, and every other command works on it with no
|
|
529
|
+
account and no network.
|
|
530
|
+
|
|
531
|
+
`login` pairs this machine with an account without a token ever appearing in a
|
|
532
|
+
browser. It prints a code, opens an approval page, and collects the token
|
|
533
|
+
itself once you approve — so the credential never lands on a screen, in a
|
|
534
|
+
scrollback, or in a chat window.
|
|
535
|
+
|
|
536
|
+
**Agents should use `login --emit-only`.** It starts the sign-in, opens the
|
|
537
|
+
browser and returns immediately rather than waiting for a human to click,
|
|
538
|
+
which no agent's command timeout survives. The next `memgineering` command
|
|
539
|
+
claims the token automatically. Show the printed code in your reply: the
|
|
540
|
+
approval page asks the user to check it against what they were shown, and on
|
|
541
|
+
surfaces where you are the only thing that saw it, they cannot.
|
|
542
|
+
|
|
543
|
+
`logout` revokes on the server before forgetting anything locally — a token
|
|
544
|
+
deleted only here still works for whoever has a copy. `--all` ends every
|
|
545
|
+
session on the account, `--local` forgets it here when the server is
|
|
546
|
+
unreachable and says plainly what that does not do.
|
|
547
|
+
|
|
548
|
+
- **`setup` offers an account as its first step, and lets you walk past it.**
|
|
549
|
+
Skipping installs byte-for-byte the same files; there is a test that compares
|
|
550
|
+
the two trees. With no terminal it does nothing unless you pass `--login`, so
|
|
551
|
+
an agent running `setup --agent` never opens a browser you did not ask for.
|
|
552
|
+
|
|
553
|
+
- **`MEMGINEERING_API_URL`** points the account commands at a different brain
|
|
554
|
+
server. The token is stored with the server that minted it and is never sent
|
|
555
|
+
anywhere else.
|
|
556
|
+
|
|
557
|
+
- **The `--human` prompt no longer hangs where there is no terminal.** Asking for
|
|
558
|
+
`--human` says which mode you want; it does not conjure a screen to draw a
|
|
559
|
+
prompt on.
|
|
560
|
+
|
|
561
|
+
- **The setup screen no longer promises a sync it does not perform.** Its first
|
|
562
|
+
screen ticks "the same memory on another machine" for keeping the memory in an
|
|
563
|
+
account — and choosing that only signed you in. No hosted brain was created and
|
|
564
|
+
no note was uploaded, so you would have found out on the second machine. The
|
|
565
|
+
last screen now says the notes are still only on this machine and what changes
|
|
566
|
+
that; the machine-readable half tells your agent the same thing, and to ask you
|
|
567
|
+
before sending anything to a server.
|
|
568
|
+
|
|
569
|
+
- **Two screens no longer ask near-identical questions.** "기억을 어디에
|
|
570
|
+
둘까요?" (this machine or an account) was followed two screens later by "기억을
|
|
571
|
+
어디에 담을까요?" (which folder to read). The second is now "어느 폴더를
|
|
572
|
+
쓸까요?".
|
|
573
|
+
|
|
574
|
+
- **The screen separates what is kept here from what an upload sends.** It said
|
|
575
|
+
only a note's title and first paragraph get stored — true of the index on this
|
|
576
|
+
machine, and read as the whole of what reaches the server by anyone who had
|
|
577
|
+
just chosen an account. Uploading sends the entire file, and the screen now
|
|
578
|
+
says so where the claim is made.
|
|
579
|
+
|
|
580
|
+
- **The privacy draft says notes are stored in plain text.** No end-to-end
|
|
581
|
+
encryption; whoever runs the server can technically read them, and not doing so
|
|
582
|
+
is a promise rather than an impossibility. It was the one fact a person
|
|
583
|
+
weighing whether to put a diary in an account most needs, and the easiest to
|
|
584
|
+
leave out.
|
|
585
|
+
|
|
586
|
+
- **The setup screen stopped handing out commands.** It answered three of a
|
|
587
|
+
non-developer's questions with one — how to stop a note being surfaced, how to
|
|
588
|
+
update, how to connect a folder — and each answer was a command to type, on the
|
|
589
|
+
one screen built for somebody who has never opened a terminal. Each is now
|
|
590
|
+
phrased as something to ask their agent for. A test fails if any
|
|
591
|
+
`memgineering <verb>` reappears on that page.
|
|
592
|
+
|
|
593
|
+
- **Folder suggestions say how many notes each one holds.** The list offered
|
|
594
|
+
every folder containing at least one markdown file, so a photo archive with a
|
|
595
|
+
stray README sat beside somebody's actual notes with nothing to tell them
|
|
596
|
+
apart. The count is the reason each row is there, so it is now on the row.
|
|
597
|
+
Filtering harder was the wrong fix: a folder with one note is still notes.
|
|
598
|
+
|
|
599
|
+
- **The terms draft lists what it has not decided.** Legal entity and
|
|
600
|
+
jurisdiction, where the servers are, how long a deletion takes to reach
|
|
601
|
+
backups, how a breach would be announced, and where to delete an account —
|
|
602
|
+
absent from the draft, and now absent in writing rather than by omission.
|
|
603
|
+
|
|
604
|
+
- **`recall` stopped telling Korean users their own Korean notes were
|
|
605
|
+
unreachable.** When a query found nothing, the footer could claim "this
|
|
606
|
+
brain's notes are mostly written in English … no rewording in another
|
|
607
|
+
language will reach them" — in a brain holding Korean notes. Two scaffolding
|
|
608
|
+
files were voting: `01_BASE/` was already excluded, `00_HUB/` was not, and on
|
|
609
|
+
a small brain one English note `init` wrote decides the count. A note like
|
|
610
|
+
`글꼴은 Pretendard 하나로` then votes English on the strength of the product
|
|
611
|
+
name, and the majority flips. The hub no longer votes, and the warning is
|
|
612
|
+
suppressed outright when any note somebody wrote is in the asker's script —
|
|
613
|
+
the claim is about reachability, and one such note makes it false.
|
|
614
|
+
|
|
615
|
+
Caught by a fresh-context agent, which read the footer, believed it, and told
|
|
616
|
+
its user that Korean titles are not searchable. A hint that is wrong does not
|
|
617
|
+
merely mislead — it stops the tool being used.
|
|
618
|
+
|
|
619
|
+
- **`resurface` shows what a brain holds before anything has been recalled from
|
|
620
|
+
it.** It ranked purely on evidence of use — recalled here, recalled anywhere,
|
|
621
|
+
read lately — and dropped everything that scored zero. A note that had only
|
|
622
|
+
ever been written scored zero, so a brain nobody had searched yet returned its
|
|
623
|
+
five untouched `01_BASE/` templates and none of its actual notes, even at
|
|
624
|
+
`--limit 8`. That is a loop with no way in: a note is not surfaced until it has
|
|
625
|
+
been recalled, and surfacing is how you find out it exists.
|
|
626
|
+
|
|
627
|
+
It runs at session start, so that was an agent's entire first impression of the
|
|
628
|
+
brain. Measured: one saw five "not filled in yet" placeholders, concluded there
|
|
629
|
+
was nothing there, and did not call memgineering again for the rest of the
|
|
630
|
+
session.
|
|
631
|
+
|
|
632
|
+
Never-reached notes now rank, below anything with evidence behind them, and
|
|
633
|
+
untouched templates take at most two of the slots instead of all five. When
|
|
634
|
+
nothing has been recalled yet the page says so in a line — the order means
|
|
635
|
+
"what this holds", not "what matters here". Refusing to guess was right;
|
|
636
|
+
refusing to speak was not.
|
|
637
|
+
|
|
638
|
+
- **Checking whether you are signed in no longer opens a Google consent page.**
|
|
639
|
+
The `not_signed_in` hint read "YOU run `memgineering login --emit-only`" with
|
|
640
|
+
no precondition attached, and agents follow instructions — so an agent that
|
|
641
|
+
ran `whoami` to orient itself started a sign-in. Measured during testing:
|
|
642
|
+
three consent windows appeared in a user's browser in a session where nobody
|
|
643
|
+
had mentioned accounts. `setup` already refused to do this on the grounds that
|
|
644
|
+
nobody should be sent to a consent screen they did not ask for; the tool held
|
|
645
|
+
both positions and this one ran more often. The hint now leads with the fact
|
|
646
|
+
that an account is optional and `--local` is right there, and gates the
|
|
647
|
+
sign-in on the user having asked for one.
|
|
648
|
+
|
|
649
|
+
- **`resurface` says what to do with what it just showed.** It printed five
|
|
650
|
+
cards and stopped, at session start, to a reader that is always an agent. One
|
|
651
|
+
was handed a note saying this site does not use blue, with the hex codes in
|
|
652
|
+
the summary, and shipped a page with a blue accent: the memory reached its
|
|
653
|
+
context and never reached its output. It now closes with three lines — these
|
|
654
|
+
are the user's own decisions, follow them unasked, recall before answering
|
|
655
|
+
something already settled, remember what this session decides. Untouched
|
|
656
|
+
templates also stop explaining themselves at length when real notes share the
|
|
657
|
+
page; six lines about unfilled files were burying the two that mattered.
|
|
658
|
+
|
|
659
|
+
- **A hosted brain answers the same way as a local one when nothing has been
|
|
660
|
+
recalled from it yet** — the notes, plus a line saying the order is what the
|
|
661
|
+
brain holds rather than what matters here. It used to return an empty list,
|
|
662
|
+
which reads as an empty brain.
|
|
663
|
+
|
|
664
|
+
### Agent guidance
|
|
665
|
+
|
|
666
|
+
- **The hub now says which tools this actually reaches.** A fresh-context test
|
|
667
|
+
asked an agent to make ChatGPT, Claude and Codex share one memory; it set up
|
|
668
|
+
the two it could and then had to read the product's source code to find out
|
|
669
|
+
whether ChatGPT was possible at all. On a machine without that source it
|
|
670
|
+
would have had to guess. The guidance now states plainly that `setup` covers
|
|
671
|
+
Claude Code, Codex and Gemini CLI, that anything with a shell works, and that
|
|
672
|
+
web and phone surfaces have no connector yet — including the specific wrong
|
|
673
|
+
answer to avoid ("you are signed in, so it works everywhere").
|
|
674
|
+
|
|
675
|
+
- The bundled guidance changed: the hub now tells your agent to fetch your
|
|
676
|
+
notes back with `pull` whenever you ask for them, and the setup skill says
|
|
677
|
+
the account question on the first screen is yours to answer rather than
|
|
678
|
+
something it should decide or pre-empt. **Restart your agent session after
|
|
679
|
+
upgrading** — the guidance is read once, when the session starts.
|
|
680
|
+
|
|
14
681
|
## [0.4.2] — 2026-08-10
|
|
15
682
|
|
|
16
683
|
### Fixed
|