Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
a006505
Wire the procedural arm's read path, and get 7.6's first real number …
joslat Aug 13, 2026
7b30b19
Record which backend build produced a corpus (S-4, new 3.8)
joslat Aug 13, 2026
90c8a22
Document how to read a stored procedure, and what silently breaks it
joslat Aug 13, 2026
4abadd2
Decide 8.3b for free instead of buying it (8.3c, 8.3d)
joslat Aug 13, 2026
a3f854e
Close the local half of 12.8, and validate 0.4 without spending CI
joslat Aug 13, 2026
8b21b2b
Score every memory type, root-cause all 10 failures, and stop the cor…
joslat Aug 13, 2026
6cb06ff
Isolate the stage where 97% of the loss actually is
joslat Aug 13, 2026
eee1987
Build the decomposed arm, and keep it from becoming a copy of the con…
joslat Aug 13, 2026
6ea72ff
Measure decomposed answering at perfect context, and kill it (B2b, B4)
joslat Aug 13, 2026
5e4b37c
Kill the context-precision lead one turn after proposing it (P1)
joslat Aug 13, 2026
86c8c0f
Add the representation arm: structured rendering at 100% recall (P2)
joslat Aug 13, 2026
b4293ce
Fix two silent-success bugs that made procedural memory look wired (0…
joslat Aug 13, 2026
e0fd4e4
Stop MCP shipping embedding vectors, and make procedural memory visib…
joslat Aug 13, 2026
ca6d5a0
Wire the MCP parameter that did nothing, and mark the interface that …
joslat Aug 13, 2026
932c0f3
Sweep gold COMPLETENESS, the mirror of the noise sweep (P3)
joslat Aug 13, 2026
86e905c
Find the lever: completeness is worth 80 points, everything else ~0 (…
joslat Aug 13, 2026
0f6d27d
The coverage curve is a step, and wire the lever that could not be me…
joslat Aug 13, 2026
ebfad52
Make coverage observable on the arm that ships (22.3)
joslat Aug 13, 2026
2296fa0
Fix the doc whose first step hard-fails, and three more silent absenc…
joslat Aug 13, 2026
59b70b5
Pre-register the coverage-lever run before spending on it (20.2, 22.4)
joslat Aug 13, 2026
a7ccb2c
Un-orphan every corpus sealed in a nine-hour window (22.4 blocker)
joslat Aug 13, 2026
d89f404
Un-orphan the frozen corpus, without removing the tamper guard (22.4 …
joslat Aug 13, 2026
404ce2e
Record what it took to start the coverage run (22.4)
joslat Aug 13, 2026
e70bd80
Compare a graph snapshot against what the seal recorded (22.4 blocker)
joslat Aug 13, 2026
30152de
Decide 22.4 from the control alone, and do not buy the treatment arm
joslat Aug 13, 2026
f2397a7
Make procedural memory and the rerankers reachable from outside (15.2…
joslat Aug 14, 2026
d8e707f
Document the quality effort that did not move, and measure a perf def…
joslat Aug 14, 2026
69e14ed
Measure whether the answer model can be pinned, and wire what the mea…
joslat Aug 14, 2026
2a16d42
Make gold-TURN coverage observable on the structured arm (27.1)
joslat Aug 14, 2026
caa9baf
Derive the oracle-impossible set by measurement, and correct the clai…
joslat Aug 14, 2026
dd21ba5
Reproduce the procedural-benefit claim and retain the artifact it nev…
joslat Aug 14, 2026
44bbf26
Publish the LongMemEval results, as bands rather than points (Phase 23)
joslat Aug 14, 2026
68fb820
Make the configure-lambda registration overload able to configure mem…
joslat Aug 14, 2026
1aceb06
State the short-term isolation boundary accurately instead of migrati…
joslat Aug 14, 2026
7e087b2
De-flake the vector-yield telemetry tests (found by a failing full-su…
joslat Aug 14, 2026
8d4c0db
Stop the context prefix from contradicting procedural memory (25.3)
joslat Aug 14, 2026
a454087
Wire the per-type reporting stack, and fix the bug that only running …
joslat Aug 14, 2026
5f6dfbb
Let an MCP operator configure memory at all (25.4)
joslat Aug 14, 2026
b2d0a6d
Make MemoryOptions.Recall the application default it claims to be (25.2)
joslat Aug 14, 2026
623cc5c
Wire the ranking intent into as-of recall, and pin the rest of the di…
joslat Aug 14, 2026
290378c
Add the closed-loop procedural memory sample (24.2 / 15.10)
joslat Aug 14, 2026
c322817
Cost a corpus that could discriminate retrieval, and recommend the ch…
joslat Aug 14, 2026
359b87c
Pre-register the query-formulation experiment before spending on it (…
joslat Aug 14, 2026
8831621
Separate a MISS from an abstention in procedure retrieval scoring (26.2)
joslat Aug 14, 2026
2deee3c
Fix procedural promotion, which had never worked, and measure retriev…
joslat Aug 14, 2026
3a5a114
Implement query formulation, bump AgentEval to 0.21.0-beta (27.4, Pha…
joslat Aug 14, 2026
de965f1
Retire query formulation on the pre-registered rule (27.4)
joslat Aug 14, 2026
5b6ddc2
Measure prospective memory for the first time (26.3)
joslat Aug 14, 2026
da8dc47
Verify the query-formulation null per question rather than in aggrega…
joslat Aug 14, 2026
5e8d73b
Move everything to .NET 10, except the shipped libraries which keep 8…
joslat Aug 14, 2026
64ce51c
Retire the hand-rolled oracle in favour of AgentEval's, on measured a…
joslat Aug 14, 2026
582bf78
Add a second procedural task shape, and record that net10 speed is no…
joslat Aug 14, 2026
8c3b848
Make the second procedural task reachable, run it, and report that it…
joslat Aug 14, 2026
7dbdf2c
Third procedural task: the arbitrary gate worked, promotion captured …
joslat Aug 14, 2026
5fd1b7e
Release-note the McpHost runtime change, and close 29.5 by checking r…
joslat Aug 14, 2026
64066dd
Reconcile architecture.md and memory-map.md with the measurement trac…
joslat Aug 15, 2026
f58dcf1
Give the extraction seed a writer, then measure that it does not work…
joslat Aug 15, 2026
402d39f
Build the SchemaExtension system, and retro-wrap procedural to prove …
joslat Aug 15, 2026
a9b1034
Close three gaps the first pass left open, found by auditing my own c…
joslat Aug 15, 2026
da868d7
Release-note the schema-extension surface, and document the bridge's …
joslat Aug 15, 2026
305f245
Seal the off-state prompt bytes, then lay the projection skeleton (30…
joslat Aug 15, 2026
2829b4a
Wire projection into both recall paths, and land match quality (30.2 …
joslat Aug 15, 2026
0839fb2
Read the supersession edges nothing ever read, and name conflicts out…
joslat Aug 15, 2026
7b6a679
Complete the projection layer: quotes, dates, one renderer, three sur…
joslat Aug 15, 2026
3480b38
Give procedures their own similarity floor, and say how long one is (…
joslat Aug 15, 2026
6609002
Fix five defects found reviewing my own Wave B work (30.2, 30.3)
joslat Aug 15, 2026
ff5ec14
Build the working-memory tier, and let the parity snapshot overrule t…
joslat Aug 15, 2026
30bc859
Delta recall: ask what changed instead of re-reading everything (30.5)
joslat Aug 15, 2026
06f8365
Arithmetic, prospective firing, and legible forgetting (30.6, 30.7, 3…
joslat Aug 15, 2026
0cb8f0a
Rename kind to fact_kind, and prove the four extensions install together
joslat Aug 15, 2026
fc2ea9f
Voting, quote-forcing, and a root-owned access queue (30.11, 30.12)
joslat Aug 15, 2026
0ae6d75
Self-review of Waves C-E: six defects that survived green suites
joslat Aug 16, 2026
602f365
Ship an operator path for extension DDL, and correct two overstatements
joslat Aug 16, 2026
a62e7f6
D1: Spike 0 — recall parity over a draft wire, on 5 fixtures
joslat Aug 16, 2026
17c8d6c
D2: a LangGraph BaseStore over AgentMemory, and two findings from bui…
joslat Aug 16, 2026
ce768fd
D3 + D4: the demo kit, and a dry run that actually broke things
joslat Aug 16, 2026
d4b0e50
Closing review: three adapter defects, red-probed, and a contract test
joslat Aug 16, 2026
b000854
Public docs for Waves A-E, and six claims that had drifted from the code
joslat Aug 16, 2026
0f6ddea
Count the mention when a fact arrives by dedup (the D2 finding, now f…
joslat Aug 16, 2026
2a44537
Wire the working-memory tier to the path that actually writes, and tw…
joslat Aug 16, 2026
5a816ba
Stop the enrichment queue losing work in silence, and two ignored tok…
joslat Aug 16, 2026
e9f77ea
Correct four claims the demo kit could not support, and five it overs…
joslat Aug 16, 2026
d84164c
Correct the demo's Finding 1 now that it is fixed, and one claim it g…
joslat Aug 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
132 changes: 132 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# AGENTS.md

A README for coding agents working in this repository. Humans should start at
[`README.md`](README.md) and [`CONTRIBUTING.md`](CONTRIBUTING.md); this file is the short version, plus
the conventions that are easy to violate without noticing.

## What this repo is

**Agent Memory for .NET** — a graph-native persistent memory engine for AI agents, backed by Neo4j.
Framework-agnostic core plus thin adapters (Microsoft Agent Framework, Semantic Kernel, MCP). It is a
from-scratch .NET reimplementation of the ideas in Python's `neo4j-labs/agent-memory`, not a port, and
it is verified against that project's compatibility kit.

- 15 shipped projects under `src/`, multi-targeting `net8.0;net9.0;net10.0`. Everything else
(tests, tools, samples) is `net10.0`. SDK pinned in `global.json`.
- 5 test projects under `tests/`, 5 tools under `tools/`, samples under `samples/`.
- Architecture: [`docs/architecture.md`](docs/architecture.md). What the memory layer does and does not
do, honestly labelled: [`docs/memory-map.md`](docs/memory-map.md). Schema extensions:
[`docs/extensions/`](docs/extensions/README.md).

## Build and test

Every command below is run from the repository root and is the same one CI runs
(`.github/workflows/ci.yml`).

```bash
dotnet restore AgentMemory.slnx
dotnet build AgentMemory.slnx # must be 0 errors AND 0 warnings
```

`TreatWarningsAsErrors` is on for `src/` projects and off for `tests/`. A warning in `src/` is a build
failure, not a note.

```bash
# unit + adapter unit suites (no Docker, no Neo4j, no LLM)
dotnet test AgentMemory.slnx --filter "Category!=Integration&Category!=Performance"

# integration — Testcontainers starts neo4j:5.26 automatically; Docker must be running
dotnet test tests/AgentMemory.Tests.Integration/AgentMemory.Tests.Integration.csproj \
--filter "Category=Integration"

# hermetic perf gates (query counts, not wall time)
dotnet test tests/AgentMemory.Tests.Performance/AgentMemory.Tests.Performance.csproj

# static upstream schema-parity check
dotnet run --project tools/AgentMemory.Cli/AgentMemory.Cli.csproj -- \
schema-parity --upstream-version 0.5.0
```

Single project, when you know where you are:

```bash
dotnet test tests/AgentMemory.Tests.Unit/AgentMemory.Tests.Unit.csproj
```

**Run the full unit suite before pushing, not a `--filter`ed subset.** A filtered run tests the happy
path of the change you just made; it has repeatedly passed while CI caught a real regression elsewhere.

Operational CLI verbs (all take `--uri`/`--password`, or the matching configuration/env values):
`migrate`, `bootstrap`, `schema-check`, `schema-parity`, `consolidate`, `decay`, `conflicts`,
`invalidate`, `supersede`, `history`, `evaluate`, `perf`, `block`.

## Conventions that are actually enforced

**Dependencies flow strictly inward.** `Abstractions ← Core ← Neo4j / adapters`. Abstractions takes
exactly one NuGet dependency (`Microsoft.Extensions.AI.Abstractions`); Core must not reference
`Neo4j.Driver` or any framework SDK; adapters never reference each other. Rules B1–B11 are in
[`docs/architecture.md` §5](docs/architecture.md#5-boundary-enforcement-rules) and are checked by
`AbstractionsContractGuardTests` / `PackageBoundaryGuardTests` — a violation fails the build, not the
review.

**`ConfigureAwait(false)` on every `await` in `src/`.** CA2007 is a warning in `src/.editorconfig`, and
warnings are errors there. Gotcha the auto-fixer gets wrong: it rewrites
`await using var x = Open().ConfigureAwait(false)` into a `ConfiguredAsyncDisposable` binding. Fix
those by hand, as a two-line disposal.

**Cypher lives in `Queries/` constants**, one file per domain, inside `AgentMemory.Neo4j`. Never inline
a Cypher string in a repository.

**Domain types are `sealed record` with `required` members.** Timestamps are `DateTimeOffset` with a
`Utc` suffix. Collections are `IReadOnlyList<T>` / `IReadOnlyDictionary<K,V>` and default to empty,
never null. Every async method takes `CancellationToken cancellationToken = default` and passes it
through.

**New capabilities ship off by default, and "off" means byte-identical.** Not "an unchanged graph" —
the query is not issued, the service is not called, the prompt bytes do not move. The current roster of
flags and defaults is [`docs/architecture.md` §3.6](docs/architecture.md#36-every-capability-in-this-cycle-ships-dark).
If you add a flag, say what off costs in its doc comment, and prove it.

**Supersession and invalidation are non-destructive.** No `DETACH DELETE` on any contradiction,
supersession, decay or prune path: the losing record is stamped `invalidated_at` (plus `valid_until`)
and linked to the winner by `SUPERSEDED_BY`. Hard deletion exists only where a caller explicitly asked
for it — `ClearSessionAsync` and the delete APIs — and nowhere else.

**Tests are written red-first, and target the trigger.** A regression test must be shown to fail
*before* the fix and pass after. A test that exercises the happy path of the fixed code proves nothing
about the defect. When a fix changes behaviour, audit that behaviour's consumers rather than assuming
the change is local.

**Schema changes have an owner.** Adding a label, relationship type or property means either a base
migration reviewed as base, or a schema extension that declares it —
[`docs/extensions/README.md`](docs/extensions/README.md) has the rules and the how-to. `schema-check`
fails when a shape has no owner.

**No `TODO`, `FIXME`, or `HACK` comments.** Finish the work or open an issue.

**Adding a project under `src/` does not publish it.** It must be listed in `eng/release-packages.txt`,
and CI fails when `src/*/` and that manifest disagree.

## Docs

Update docs in the same change as the code, not afterwards:

- `docs/architecture.md` — architectural changes, new options, new capabilities
- `docs/memory-map.md` — anything that changes what the memory layer can or cannot do, with its honest
BUILT / WIRED / MEASURED status
- `docs/extensions/<id>.md` — **enforced by a test** for every shipped schema extension: the page must
exist, carry the sections `## Shape`, `## Cypher`, `## Semantics`, `## Conformance`,
`## Parity delta`, name every declared shape and parity-delta entry, and be linked from the index
- `docs/schema.md` — graph schema changes
- `docs/getting-started.md` — configuration or DI registration changes
- `CHANGELOG.md` — user-visible changes, under `[Unreleased]`

## Commits and PRs

Branches: `feature/<desc>`, `fix/<desc>`, `docs/<desc>`, `refactor/<desc>`.

Commit messages are imperative and specific — say what changed and, in the body, why. Do not add
tool-generated footers.

Before opening a PR: zero build warnings in `src/`, full unit suite green, integration suite green if
you touched persistence, no boundary violations, docs updated. Reviewers check exactly that list.
1 change: 1 addition & 0 deletions AgentMemory.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<Project Path="samples/AgentMemory.Sample.RealAgent/AgentMemory.Sample.RealAgent.csproj" />
<Project Path="samples/AgentMemory.Sample.McpHost/AgentMemory.Sample.McpHost.csproj" />
<Project Path="samples/AgentMemory.Sample.NamsAgent/AgentMemory.Sample.NamsAgent.csproj" />
<Project Path="samples/AgentMemory.Sample.ProceduralMemory/AgentMemory.Sample.ProceduralMemory.csproj" />
<Project Path="samples/AgentMemory.Sample.ShoppingAssistant/AgentMemory.Sample.ShoppingAssistant.csproj" />
<Project Path="samples/AgentMemory.Samples.Shared/AgentMemory.Samples.Shared.csproj" />
</Folder>
Expand Down
Loading
Loading