v5.1.0
Consolidated 5.1.0. The tier1 graph/session-intelligence layer ships
together with handoff-v2 persistence, the dynamic-flow firewall + router,
named pipelines, capability-aware dispatch, and the session-lifecycle
catch-up/summarizer. First PyPI publish since 5.0.1.
Added — dynamic-flow, session-lifecycle, SDD
- Dynamic-flow firewall + closure (Phase 1):
scripts/mb-flow-verify.shis
the sole exit-code authority (0=pass / 1=fail / 2=broke); Stop-hook
(mb-flow-closure-guard.sh) + git-hooks closure guards gated on agoal.md
predicate; AGENTS.md firewall contract; goal primitive + validator. Shipped
through the governed dual-review (Codex + lead) + judge pipeline. (REQ-DF-010..062) - Dynamic-flow router + patterns (Phase 2):
analyze-taskdeterministic
router, five-route catalogue, six workflow pattern templates, stateless
mb-fanout.shagent-invoke + per-agent sub-invoke contract with
parallel-fence write-once discipline. (REQ-DF-070..084) - Session-lifecycle:
mb-session-catchup.sh(SessionStart lazy-summarize of
sessions leftsummarized:falseby a SIGKILLed SessionEnd), extracted DRY
mb-session-summarize.sh,mb-session-prune.sh(archive contentless stubs),
mb-settings-ensure-timeout.py(inject the SessionEnd timeout). All fail-safe. - SDD hybrid requirements:
requirements.mdnow pairs Kiro User Stories with
EARS acceptance criteria;mb-ears-validate.shis case-insensitive and
validates only the REQ bullets;mb-plan.shplan template gains YAML
frontmatter (type/topic/status/depends_on/parallel_safe/linked_specs/created). - Cursor extension finished — sessionEnd registry auto-capture.
handoff-v2. A persistence layer that lets a long-running agent survive
context compaction and session boundaries: a small handoff capsule written
before compaction and restored at the next session, mandatory/mb done
gates that run even without an active plan, and a sha256 hash chain that makes
tampering of historicprogress.mdentries a CRITICAL drift. Shipped through
the governed dual-review (Codex + lead) + judge pipeline, with a fix-cycle per
task.
Added
- Handoff capsule (
scripts/mb-handoff.sh+memory_bank_skill/handoff_capsule.py).
--actualize/--read/--rotatea ≤1500-byte capsule under
.memory-bank/handoff/. The five sections (Now / Done / Open blockers / Next
concrete step / Pointers) always survive truncation — the skeleton is reserved
first and only the bullet lists are byte-fit, so the most important section is
never dropped. UTF-8-safe byte cap; colon-free archive names;
copy-then-atomic-rename so a capsule is never lost on interrupt; owner-token
mkdirlock for single-writer safety. (REQ-120) - PreCompact actualize (
hooks/mb-pre-compact.sh, renamed from
mb-compact-reminder.sh). OnpreCompact, refreshes the capsule within a ~2s
portable budget and never blocks compaction — on timeout/failure/no-bank it
WARNs and exits 0, killing the whole actualize process tree (no orphans). Opt
out withMB_PRECOMPACT_HANDOFF=off. (REQ-120, REQ-121) - SessionStart capsule consumption (
hooks/mb-session-start-context.sh).
Prepends the capsule only when it is newer than the most recentprogress.md
date heading; otherwise the normal context is unchanged. (REQ-121) - Mandatory
/mb donegates (scripts/mb-done-gates.sh). Tests + rules
(with--diff-filesso the CRITICAL TDD-delta check runs) + placeholder scan,
honouringdone_gates.required.--forcerequires a single-line--reason
(newline-injection rejected), records a NOTE inprogress.md+ a failure JSON,
and fails closed whenallow_force:falseor a projectpipeline.yaml
cannot be parsed. Configurable viapipeline.yaml:done_gates. (REQ-122, REQ-123) - Append-only hash chain (
scripts/mb-progress-chain.sh+
memory_bank_skill/progress_chain.py).--rebuild-tail/--verifya sha256
chain of the last 20progress.mdentries inindex.json:progress_chain;
mb-drift.shraises CRITICAL on a mismatch, deletion, ambiguous match, or a
malformed index.json. Canonical-form hashing (LF-normalised, trailing
separators excluded) keeps legitimate appends stable while in-body content and
whitespace edits remain tamper. (REQ-124) scripts/mb-rules-check.sh --placeholders-only— scan-only mode for the
done-gate, withtests/-path and# mb-rules-check: allow-placeholder
exemptions.- Docs —
docs/handoff-2.0.md(capsule lifecycle, done-gate + force
semantics, hash-chain limits).
Changed — defaults
/mb donenow runs the done-gate set as step 0 (enabled by default; failures
require--force --reason). Existing plan/spec verification is unaffected.settings/hooks.jsonregistersmb-pre-compact.shonpreCompact(replacing
the old weekly compact reminder, which remains available inadapters/cline.sh
viaMB_COMPACT_REMIND). Re-registration stays idempotent.
tier1-graph-memory (Phase 5) — 2026-06-14
tier1-graph-memory. Sharper code-graph retrieval (RRF fusion, import-aware
Python call resolution, PageRank god-nodes), richer session memory
(progressive-disclosure recall, per-turn outcomes, structured summaries), and
three new$0memory-hygiene commands (/mb recap,/mb conflicts,
/mb consolidate). Every new opt-in layer keeps base output byte-identical.
Changed — defaults
- RRF fusion is the default auto-backend in code search. With embeddings
installed,mb-semantic-search.py --backend autonow fuses the embeddings and
BM25 rankings via Reciprocal Rank Fusion (rrf_merge,by_idbuilt at index
time,O(k)query fusion) instead of using embeddings alone.autowithout
embeddings stays pure BM25 (byte-identical to before); explicit--backend bm25/embeddingsare regression-locked. (REQ-001/REQ-002) - Import-aware call resolution for Python.
calledges in.pyfiles now
resolve through the file's actual imports — binding order is: localdefwinsexplicit import (relative level +
as-alias aware) > single star-import
match > unique project-wide fallback > suppress homonyms. Dotteddst
namespacing via the newcodegraph_binding.py. Non-.pyedges pass through
verbatim; the graph cache is bumped toCACHE_VERSION=2. Resolution for the
tree-sitter languages (Go/JS/TS/Rust/Java) stays name-based. (REQ-003/REQ-004) god-nodes.mdis ranked by PageRank, with degree as a secondary column
(was degree-only). Pure-stdlib power iteration (networkx.pageranksemantics,
no numpy/scipy) incodegraph_rank.py, full-precision sort with 6-dp display,
cross-process deterministic. Withoutnetworkxthe report degrades to
degree-only and prints a one-line install hint. (REQ-005/REQ-006)
Added
rrf_merge(rankings, k=60)— standalone Reciprocal Rank Fusion module
(memory_bank_skill/rrf.py), the single source of truth for rank fusion across
code search and/mb recall. (REQ-001)churn_30dranking signal under/mb graph --cochange. Per-file 30-day
churn is derived from the same git-log pass as co-change mining (one
subprocess, asserted) and emitted as additive{"type":"node-attr"}JSONL
rows only under--cochange; semantic search applies a1+0.1·log1p(churn)
boost after ranking/fusion over the full candidate set, then truncates. No
churn attrs → ranking byte-identical. (REQ-007)- Community-summary retrieval in code search. When a
/mb wikiarticle lands
in the top-3 final hits,mb-semantic-search.pyappends a labeled
community_filesblock (member files from.wiki-packs.json, sorted, capped
at 10). Fail-open: missing/malformed packs or non-article hits → byte-identical
no-wiki output. (REQ-008) - Per-turn capture upgrade —
outcome+ diffstat. Each session Live-log
bullet now records anok | err(N)outcome (turn-scopedis_errorcount) and
an aggregate+A/-Bdiffstat from a singlegit diff --numstat; fails closed
outside work trees / bare repos. (REQ-009) - Structured summary schema v2. The session-end Haiku summarizer now consumes
the session's own distilled Live log (never the raw transcript tail) and is
prompted for exactly four sections — What changed / Decisions / Open questions
/ Files.summary_schema: v2is stamped only after a strict in-order heading
validation passes (duplicate/out-of-order headings are rejected, see I-069);
non-conforming output is stored unflagged. (REQ-010/REQ-011) - Progressive-disclosure
/mb recall. Default output is now a compact index
— oneid · age · summary · sourceline per hit (~15 tokens/line, no chunk
bodies).--expand <id>returns one full chunk (exit 3 on unknown id),
--fullkeeps the legacy bodies. Semantic + lexical hits are fused via RRF
when the semantic backend is available (fail-open to lexical-only otherwise);
[SUPERSEDED]chunks sort last with a⊘label. (REQ-001/REQ-016–019) /mb recap <sid>— rebuild a fullprogress.mdentry from a session stub
via one Haiku call (scripts/mb-recap.sh). Surgically replaces only that
session's auto-capture stub (atomic temp→mv, neighbors byte-identical),
idempotent viarecappedfrontmatter; strict no-write refuse paths with pinned
exit codes (missing session/progress → 2, no claude → 3, no stub → 4,
error-shaped output → 5); ambiguous prefix → refuse and list candidates.
(REQ-020/REQ-021)/mb conflicts [--judge] [--threshold N]— surface memory entries with
high lexical overlap and opposing/replacement assertions (en+ru negation
markers) as conflict candidates overnotes/+lessons.md+ recent
progress.md.$0default pass (token-set Jaccard >N, default 0.3, zero
LLM calls);--judgeconfirms/rejects each candidate via one Sonnet call and
prints a suggested[SUPERSEDED: YYYY-MM-DD -> <ref>]marker. PRINT-ONLY —
never writes to any bank file. (REQ-022/REQ-023)/mb consolidate [--apply] [--days N]— fold sessions older thanNdays
(default 30) that cluster by shared files / lexical overlap into 5–15 line
notes/candidates, archive those session files verbatim →session/archive/,
and move only their contiguous auto-capture progress stubs verbatim →
progress-archive.md. Zero LLM calls; dry-run is the default (bank
byte-identical); real progress entries never move. (REQ-012/013/014)[SUPERSEDED]convention + drift checker. The append-new + mark-old
[SUPERSEDED: YYYY-MM-DD -> <ref>]convention is documented in
agents/mb-manager.md+references/metadata.mdand enforced by a new
mb-drift.shchecker: malformed markers and dangling refs acrossnotes/,
lessons.md,progress.md,session/→ greppable warnings + exit 1 (with
real Gregorian calendar validation). (REQ-015)/mb graph --sessionslayer. Bridges session memory into the code graph:
onesessionnode per session that touched a graph module, aworked_onedge
to each touched module carrying a one-line work summary, and an append of that
summary to the module node'sdoc(capped at the 3 most recent sessions per
module) so semantic search answers work-history queries. Every
session-derived string isredact_secrets'd and<private>-stripped at
graph-write time (graph.jsonstays committable). The layer is applied as the
last mutation — after community/betweenness/PageRank analytics — so god-node
ranking is never skewed (god-nodes.mdis byte-identical with or without the
flag). (REQ-024/025/026)- Staleness-aware incremental
/mb wikirebuild.wiki/index.mdrecords a
per-article SHA256 over the canonical graph records touching each community's
files; a$0plan splits communities into scheduled vs fresh and filters the
dispatch — a fully-fresh cache → zero Haiku/Sonnet dispatches,--forceor a
legacy/no cache → full rebuild. Hash recording is idempotent. (REQ-027) - Deterministic Decisions section in wiki evidence packs. Each community pack
can carry adecisionslist —notes/entries + session summaries matched
against the community's file basenames (token-bounded matching), top-5 with
source refs,$0, deterministic order. Session files contribute only their
## Summarybody (frontmatter / Live log /### Filespath list never leak).
(REQ-028) semanticedge confidence bands documented + a 0.5 floor enforced. The
references/code-graph.mdreference now defines the meaning ofconfidenceon
semanticedges (High ≥ 0.9 / Medium 0.7–0.9 / Low 0.5–0.7 / dropped < 0.5) as
the single source of truth; the wiki synthesizer assigns by these bands and
merge-edgesenforces the< 0.5drop, so asemanticedge ingraph.json
always meansconfidence ≥ 0.5. (REQ-029)
Added — named pipelines
- Multiple named pipelines per project. A project can keep several pipelines
under.memory-bank/pipelines/<name>.yaml, each a full standalone config (same
schema + validator aspipeline.yaml) with its own model routing and workflow.
/mb work --pipeline NAME(or$MB_PIPELINE) selects one explicitly; a
pipeline whoseagents:lists the current code-agent host
(claude-code/pi/opencode/codex/…) is auto-selected per host, so one
repo can run a fast solo loop under Claude Code and a governed review-ensemble
under pi/opencode with no flag. Selection ladder: flag/env → host binding →
.mb-config pipeline=NAME→ in-filedefault: true→ legacypipeline.yaml→
bundled default. /mb pipelinecommand (commands/pipeline.md):list·
new NAME [--agent a,b] [--from NAME|default] [--default] [--force]·
use NAME(non-destructive default switch via<bank>/.mb-config) ·show·
path·validate [--all](cross-file conflict detection: duplicate
pipeline_name, more than onedefault, an agent bound to multiple pipelines).scripts/_lib.sh:mb_detect_host(host from$MB_PIPELINE_HOST→$MB_AGENT
→ env signatures),mb_pipeline_dir,mb_pipeline_meta.mb-pipeline.sh
selection ladder;mb-pipeline-validate.shvalidates the optional
pipeline_name/default/agentsmetadata keys.- Consumers (
mb-work-*.sh,mb-workflow.sh) read the selected pipeline with no
changes — they already resolve throughmb-pipeline.sh path, which now honors
$MB_PIPELINEand host binding. - Backward compatible: with no
pipelines/directory and no--pipeline,
resolution is byte-for-byte identical to the prior single-pipeline.yamlpath.
Added — security
- Automatic secret redaction in session capture (default on). Recognizable
API keys/tokens (sk-…,ghp_…/github_pat_…,AKIA…/ASIA…,xox?-…,
AIza…,hf_…,npm_…,pypi-…, JWTs,Bearer <token>,*_API_KEY=-style
env assignments) are replaced with[REDACTED]before they reach
.memory-bank/session/*.mdor the semantic index. Applies at three layers:
the per-turn Live-log bullet, the transcript fed to the Haiku summarizer /
Sonnet judge, and the semantic chunker. Off-switch:MB_REDACT_SECRETS=off.
Implementation:hooks/lib/redact.py+sc_redact_secretsin
hooks/lib/session-common.sh. Regression for a real leak: an OpenRouter key
quoted in a transcript error was persisted verbatim. - Semantic-index chunker now also strips
<private>…</private>blocks
(mirrorsmb-index-json.py), closing the gap where private content was
excluded fromindex.jsonbut still indexed for/mb recall.
Fixed
- I-069 — strict v2 heading state machine. The schema-v2 summary validator
now rejects a duplicate or out-of-order### …heading instead of stamping
summary_schema: v2on it; a rejected body is still stored, just without the
(now-honest) flag. - I-066 — unique-fallback binds module-level defs only. Rule 3 of the
import-aware binder no longer collapses a class method (Worker.process) or
nested function to its bare suffix, so it can no longer invent a falsecall
edge to a non-module-level definition. - I-067 — no leading-dot
dstfor root__init__.py. A unique definition in
a root__init__.py(empty module prefix) now emits a baredstinstead of a
leading-dot.foo. session-end-autosave.shprogress stub no longer promises a reconstruction
that never happened ("Details will be reconstructed on the next /mb start");
it now points at the actually-captured session summary (/mb recall).