Skip to content

emrg: the rotation bookmark can be written into a shape nothing refuses #2513

Closed

Description

@argszero

The rotation bookmark can be written into a shape nothing refuses

What was observed

scripts/check-memory-rotation.py is the reader of
.emrg/memory/project-memory-rotation-bookmark.md — the per-project table that answers
"which projects' memory moved since I last read them". It is thorough about the table's
rows and says nothing about the file's structure above them. Three shapes were
written into temp copies of the real bookmark and read back (2026-10-23, on this checkout):

shape written what the reader answered
the real file, unchanged exit 0, every project has a row and every row names a project (32 of 32)
a row's disambiguating qualifier dropped (aitokenpool for aitokenpool (github)) exit 1 — the bookmark's row 'aitokenpool' names 2 projects — already caught
the cycle section rewritten to end of file, taking the project table with it exit 2 — carries no markdown table ... a bookmark in another shape is not an empty bookmark
a second ## Cycle section appended below the table exit 0 — every project has a row and every row names a project (32 of 32)

Why the two bad answers matter

The appended section is invisible. The file's own text states the rule — "Update this
file in place every cycle — never append a second entry"
— and records why: measured
2026-10-21, this file had grown to 359 lines carrying eight per-cycle sections, one of
them duplicated. Every row still parsed, so the reader reports a clean file. The growth is
what the rule exists to prevent, and nothing measures it today. This file is embedded in a
cycle's prompt, so the growth is paid for on every round that reads it.

The truncated write is refused for the wrong reason. The section rewrite that runs
past the table header is the shape that once deleted all 32 rows. The reader does refuse
it, which is the good half — but the sentence it refuses with says the file is "a bookmark
in another shape"
, whose remedy is to re-shape a file the writer never mis-shaped. The
actual cause is one mechanism, named in the same file: "A cycle section is replaced from
its ## heading to the next ## heading or the table header — never to end of file."

A reader who meets that refusal needs to be told which boundary was overrun, not that their
file is in an unfamiliar format.

What the fix must satisfy

  1. A second ## Cycle section is a fault, and the reading survives it. It is reported
    with the row count it read, exit 1, in the same list the coverage faults are printed in —
    not as not measurable, because the rows are measurable and a refusal would throw away
    a valid reading of the rotation.
  2. The message names the rule, not the symptom: one cycle section, replaced in place,
    with the measured consequence of appending.
  3. A file that carries a cycle section and no table row anywhere is refused as the
    section-rewrite shape
    , in those words, and distinguished from a bookmark written in
    another format — that second message stays for the file that carries no section either.
  4. A bookmark with no cycle section at all is not a fault. A minimal or first-ever
    bookmark has only the table, and the existing tests' fixtures are that shape.
  5. Both directions are measured: a one-section file is clean, a two-section file is a
    fault, and the arm that removes the check reddens the test that names it.
  6. The host-side counterpart is the existing command — check-memory-rotation.py --bookmark <path> — because the bookmark lives under the host's home and no CI leg can
    see it. The CI side is fixture tests over files written in tmp_path.

Activity

  1. argszero commented on Oct 23, 2026

    @argszero
    OwnerAuthor

    Handled by #2514

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions