Skip to content

v4.14.9

Choose a tag to compare

@github-actions github-actions released this 30 Aug 17:39
· 3 commits to master since this release
c7dc245

Fixed

  • memo token-savings published a percentage its own gate rejected. It
    printed crusher_L1 +44.4% (measured, gate-passed) while
    memo eval tokens --gate exited 1 on that lever with Δquality -0.48 — the
    stored passed: true is a claim about the run that wrote it, not about
    today, and nothing re-checked it. The saving fraction was also recorded
    without the sample it was folded from, so the command could not tell a lever
    measured over 49 live prompts from one measured over the 2 synthetic cases in
    eval/token_corpus.json (whose own _doc predicts the quality guard should
    fail). LeverRow now carries n_samples, gate_metrics records it, and a
    lever folded from fewer than ten cases — or from a baseline written before
    the count existed — is named rather than published. An empty gate now also
    points at the context proxy, which is measured separately, so "no lever
    passed" cannot read as "memo saves nothing". The pre-existing fixture omitted
    n_samples entirely, which is why no test caught this.
  • memo config flags reported the environment, not the configuration. Its
    active column was active_flags() — env vars only — so every flag pinned
    through memo config set rendered blank, and a blank cell beside a default of
    False reads as OFF. On this machine that hid 60 flags: the graph subsystem
    showed as entirely disabled while graph-config.md had it on. Markdown config
    is the channel that reaches daemons, hooks, and the MCP server, so the layer
    the column omitted is the one that decides behaviour. The table now shows the
    resolved effective value and the source layer that decided it
    (env > config > overlay > default), --active means explicitly
    configured anywhere rather than exported in this shell, and the raw env value
    stays available as active in --json.
  • Dead statement in aggregate_capture. len(samples) or 1 was evaluated
    and discarded; the count it was computing is now the recorded n_samples.
  • The reliability nudge showed the same seven memories forever, and its
    action did not work.
    superseded_pairs() ordered inactive/*.md with
    sorted(glob(...)) — by FILENAME, which for these files is the hex memory
    id, so a store with 767 archived memories surfaced the alphabetically-first
    seven at every session start indefinitely, all resolved weeks earlier. The
    scan now orders most-recently-superseded first and drops supersessions older
    than 30 days, because the caller is an interrupt surface and a supersession
    is only worth interrupting for while it is news. Entries with no
    superseded_at sort last but are kept, so archives written before the stamp
    existed are not hidden. The nudge's action pointed at the stale id, which
    lives in inactive/ and which memo get does not read — every one of those
    seven answered not found; it now points at the successor, which exists and
    is the memory worth reading. Neither fixture stamped superseded_at, and the
    ordering fixture used ids whose filename order already matched the expected
    order, so the sort could not be observed as wrong.
  • The proxy A/B session floor counted stray rows as independent draws. The
    distinct-session count treated any non-empty session_key as a session, so
    the live holdout arm read as two sessions when it held 37 real requests from
    ONE session plus a single stray row. One more such row would have cleared the
    three-session floor added in 4.14.8 and published a ratio that is still one
    session of evidence — the floor would have withheld the small version of the
    bad number and shipped the large one, which is the exact failure it was added
    to prevent. A session must now carry at least two requests to count: a
    singleton cannot exhibit any within-session variation, which is precisely
    what the session count exists to detect.