Read the memory handle where the host writes it — the last line - #7
Merged
Conversation
The handle was looked for ANYWHERE in a value, while the host appends it on the
last line — the same place trimHostNote cuts, and the comment beside it already
said so. It makes no difference while a value is plain data. It makes all the
difference when a value QUOTES arbitrary content: a diff, a log, a user's
message. Any [mem:…] inside the data was read as a control marker.
Two failures came out of that, and the second is older than 2.2.1:
- a toolless step was handed a value the engine believed to be an unreadable
preview and marked degraded, although the value was whole all along. It landed
on exactly the repositories where this mechanism is implemented — that is, on
any embedder reviewing its own code — and looked like a flake, because it
depended on which chunk the quoting lines fell into;
- with a real note present as well, the FIRST match won. `<var>.mem` ended up
holding an id taken out of the data, so `{from: "{{var.mem}}"}` would hand a
tool whatever that id happened to resolve to. That one is on the `call` path
and has been there since the handle was first stored.
A last line that genuinely begins with the marker stays ambiguous, and
unavoidably so — the convention is textual. What is fixed is the far commoner
half: a marker in the MIDDLE of quoted content is data again.
The neighbouring parsers were checked and were already right: trimHostNote and
Vocabulary.TruncationNotes read the last line, ERROR:/DENIED: are matched at the
start of a value.
Engine fix, not a format change: EngineVersion 2.2.1 → 2.2.2.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The working-memory handle is read from the value's LAST line, where the host
writes it, instead of anywhere in the text.
Engine fix, not a format change:
EngineVersion2.2.1 → 2.2.2.Why
memHandlesearched the whole value; the host appends the handle on the lastline — the same place
trimHostNotecuts, and the comment beside it alreadysaid so. That makes no difference while a value is plain data, and all the
difference when a value quotes arbitrary content: a diff, a log, a user's
message. Any
[mem:…]inside the data was read as a control marker.Two failures came out of it, and the second is older than 2.2.1:
a toolless step was handed a value the engine believed to be an unreadable
preview and marked
degraded, although the value was whole all along. Itlanded on exactly the repositories where this mechanism is implemented — that
is, on any embedder reviewing its own code — and looked like a flake, because
it depended on which chunk the quoting lines fell into;
with a real note present as well, the first match won. The test says it
plainly: a call returning
<diff quoting [mem:kget-a3f7]>+\n[mem:kget-real]put
kget-a3f7intochunk.mem.{from: "{{chunk.mem}}"}then hands a toolwhatever that foreign id resolves to — silently, because a handle looks like a
handle. That path is on
call, and has been there since the handle was firststored.
Closes #
How
The regexp is anchored at the start of a line and matched against the last one.
The limit, stated rather than hidden: a last line that genuinely begins with
the marker stays ambiguous, and unavoidably so — the convention is textual. What
is fixed is the far commoner half: a marker in the MIDDLE of quoted content is
data again.
The second suggestion in the task was not taken. An unresolvable handle is
still reported rather than treated as "probably a quotation". After this fix,
reaching that state needs a real note in the note position, which means working
memory lost data it promised — and a step that cannot fetch it should say so.
The task allowed either choice.
The neighbouring parsers were checked
All three were already right, so nothing else changed:
trimHostNoteLastIndex("\n[")— from the endVocabulary.TruncationNotesERROR:/DENIED:inisBlankHasPrefixafterTrimSpace— from the startTesting
go vet ./...cleango test ./... -count=1all greentests named the symptoms before the fix existed
reaches
<var>.mem, a genuinely stale handle is still reported, and thecall-argument path does not fetch a foreign value
No dependencies
Format & API compatibility
EngineVersion2.2.1 → 2.2.2 — "engine fixes, the format did not change"CHANGELOG.mdupdatedSchema & docs
README.mdandREADME.ru.mdboth say where the handle is read from —next to
<name>.mem, which is where a skill author meets itengine, not something a skill file declares
Invariants
variable named; what stopped being reported is the case that was never a
failure
the class this repository already had written down
Checklist
memHandlecarries the reason, not just the rule🤖 Generated with Claude Code