Skip to content

Read the memory handle where the host writes it — the last line - #7

Merged
inhuman merged 1 commit into
mainfrom
quoted-handle
Aug 3, 2026
Merged

Read the memory handle where the host writes it — the last line#7
inhuman merged 1 commit into
mainfrom
quoted-handle

Conversation

@inhuman

@inhuman inhuman commented Aug 3, 2026

Copy link
Copy Markdown
Owner

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: EngineVersion 2.2.1 → 2.2.2.

Why

memHandle searched the whole value; the host appends the handle on the last
line — the same place trimHostNote cuts, and the comment beside it already
said 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. 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. The test says it
    plainly: a call returning <diff quoting [mem:kget-a3f7]> + \n[mem:kget-real]
    put kget-a3f7 into chunk.mem. {from: "{{chunk.mem}}"} then hands a tool
    whatever 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 first
    stored.

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:

parser how it reads verdict
trimHostNote LastIndex("\n[") — from the end correct
Vocabulary.TruncationNotes matched on that same last line only correct
ERROR: / DENIED: in isBlank HasPrefix after TrimSpace — from the start correct

Testing

  • go vet ./... clean
  • go test ./... -count=1 all green
  • Every failure was reproduced FIRST, from the repro in the task, and the
    tests named the symptoms before the fix existed
  • Both directions covered: a quoted marker is data, a real note still
    reaches <var>.mem, a genuinely stale handle is still reported, and the
    call-argument path does not fetch a foreign value

No dependencies

  • Production code still imports stdlib only
  • No new test dependency

Format & API compatibility

  • No field added, changed or removed; every skill file loads as before
  • EngineVersion 2.2.1 → 2.2.2 — "engine fixes, the format did not change"
  • CHANGELOG.md updated
  • Go API unchanged

Schema & docs

  • README.md and README.ru.md both say where the handle is read from —
    next to <name>.mem, which is where a skill author meets it
  • Schema unchanged: the handle is a runtime convention between host and
    engine, not something a skill file declares

Invariants

  • A failure is LOUD: a genuinely stale handle is still degraded with the
    variable named; what stopped being reported is the case that was never a
    failure
  • The engine still logs nothing and reaches nowhere
  • A parser of content that may quote its own markers now survives them —
    the class this repository already had written down

Checklist

  • Godoc updated: memHandle carries the reason, not just the rule
  • No secrets / tokens in the diff

🤖 Generated with Claude Code

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.
@inhuman
inhuman merged commit e7e0e21 into main Aug 3, 2026
1 check passed
@inhuman
inhuman deleted the quoted-handle branch August 3, 2026 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant