Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7b2087a
feat(memory): freeze M2 episode contracts
Anduin9527 Aug 23, 2026
72d0895
feat(memory): add repository keyed digest
Anduin9527 Aug 23, 2026
6c8830f
feat(memory): add core projection schema
Anduin9527 Aug 24, 2026
7985982
feat(memory): add FTS5 episode search projection
Anduin9527 Aug 24, 2026
5a2a30e
feat(memory): add context selection receipt ledger
Anduin9527 Aug 24, 2026
0df535e
feat(memory): add typed linear ref transaction
Anduin9527 Aug 24, 2026
d0193aa
feat(memory): add authoritative memory writer
Anduin9527 Aug 24, 2026
523bf55
feat(memory): protect local-only memory ref
Anduin9527 Aug 24, 2026
79d8039
feat(memory): add projection replay and rebuild
Anduin9527 Aug 24, 2026
460db36
feat(memory): add bounded episode source admission
Anduin9527 Aug 25, 2026
7123658
feat(memory): add recoverable generation jobs
Anduin9527 Aug 25, 2026
31e52fc
feat(memory): add task episode compiler
Anduin9527 Aug 25, 2026
40b1403
feat(memory): add intent iteration compiler
Anduin9527 Aug 25, 2026
2b33e25
feat(memory): add deterministic episode reader
Anduin9527 Aug 25, 2026
42b2b26
feat(memory): add audited context injection
Anduin9527 Aug 25, 2026
aec189d
merge: integrate upstream main for memory core
Anduin9527 Aug 25, 2026
4ca7dbc
feat(memory): add runtime lifecycle and public CLI
Anduin9527 Aug 26, 2026
79e492e
merge: sync upstream main for memory core
Anduin9527 Sep 2, 2026
98e9934
fix(ci): refresh CLI help and web assets
Anduin9527 Sep 3, 2026
ae3869b
feat(memory): add bridge recall and DSH episode capture
Anduin9527 Sep 7, 2026
d2e268c
merge: preserve current PR history with memory bridge updates
Anduin9527 Sep 7, 2026
a92b29e
merge: sync upstream main and reconcile memory with operation v2
Anduin9527 Sep 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ test-group = 'external'
filter = 'test(/(^|::)mcp_http_and_stdio_expose_identical_tool_set$/)'
test-group = 'external'

[[profile.default.overrides]]
filter = 'test(/(^|::)memory_public_cli_lifecycle_after_agent_terminal$/)'
test-group = 'external'

[[profile.default.overrides]]
filter = 'test(/(^|::)metadata_model_field_prefers_event_model$/)'
test-group = 'external'
Expand Down
83 changes: 83 additions & 0 deletions .github/workflows/memory-portability.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Memory SQLite portability

on:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
memory-fts5-probe:
name: memory-fts5-probe (${{ matrix.platform }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: linux-amd64
runner: ubuntu-latest
target: x86_64-unknown-linux-gnu
- platform: linux-arm64
runner: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
- platform: macos-arm64
runner: macos-latest
target: aarch64-apple-darwin
- platform: windows-amd64
runner: windows-latest
target: x86_64-pc-windows-msvc
env:
LIBRA_SKIP_WEB_BUILD: "1"
EXPECTED_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
MATRIX_TARGET: ${{ matrix.target }}
steps:
- name: Checkout reviewed head
uses: actions/checkout@v5
with:
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
ref: ${{ github.event.pull_request.head.sha || github.sha }}
submodules: recursive
persist-credentials: false

- name: Set up release Rust target
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
target: ${{ matrix.target }}

- name: Verify tested commit
shell: bash
run: |
actual_sha="$(git rev-parse HEAD)"
if [[ "$actual_sha" != "$EXPECTED_SHA" ]]; then
echo "::error::checked out $actual_sha but expected reviewed head $EXPECTED_SHA"
exit 1
fi

- name: Select Perl for vendored OpenSSL
if: runner.os == 'Windows'
shell: pwsh
run: |
$selected = $null
$candidates = Get-Command perl.exe -All -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty Source -Unique
foreach ($candidate in $candidates) {
& $candidate -MLocale::Maketext::Simple -e "1" 2>$null
if ($LASTEXITCODE -eq 0) {
$selected = $candidate
break
}
}
if (-not $selected) {
throw "No Perl installation with Locale::Maketext::Simple is available"
}
"OPENSSL_SRC_PERL=$selected" >> $env:GITHUB_ENV

- name: Probe release-linked FTS5
shell: bash
run: |
cargo test --locked --release \
--features keyring \
--target "$MATRIX_TARGET" \
--test fts5_capability_test -- --nocapture
5 changes: 3 additions & 2 deletions COMPATIBILITY.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions docs/commands/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ Every Libra command accepts the following global flags:
| `libra graph` | | Inspect a Libra Code thread version graph (`--json`/`--machine`; interactive TUI entry removed in the W5 breaking release, use Web Code UI) | [graph.md](graph.md) |
| `libra sandbox` | | Inspect AI sandbox diagnostics, including OS backend availability and downgrade warnings | [sandbox.md](sandbox.md) |
| `libra agent` | | Manage external-agent capture, checkpoints, hooks, and RPC adapters | [agent.md](agent.md) |
| `libra memory` | | Search, inspect, diagnose, and rebuild repository development-history Memory | [memory.md](memory.md) |

### Low-Level & Inspection

Expand Down Expand Up @@ -211,6 +212,7 @@ On error:
| `LBR-IDX-*` | Index/staging area errors (corrupt index, lock contention) |
| `LBR-OBJ-*` | Object storage errors (missing object, hash mismatch) |
| `LBR-VAULT-*` | Vault and encryption errors (unseal failure, key generation) |
| `LBR-MEMORY-*` | Agent Memory query, policy, projection, and storage errors |

## Design Philosophy

Expand Down
2 changes: 1 addition & 1 deletion docs/commands/agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ for any other non-roster agent — return an actionable unsupported error.
| `rpc trust --dir <path>` | Register a trusted directory (`agent.external_agents.trusted_dirs`, default `~/.libra/agents`): external binaries are only trustable when their canonical path lives under one. The path is canonicalized and must be an existing, non-world-writable directory |
| `rpc untrust <slug>` | Revoke trust; the binary returns to quarantine (always available, even while external agents are disabled) |
| `rpc invoke` | Invoke one JSON-RPC method on a trusted `libra-agent-*` binary |
| `bridge --stdio` | Run the repository-scoped DeepSeek Harness bridge over stdin/stdout (JSON-RPC 2.0 NDJSON). The **only** standard inbound write transport for Harness; it is not `libra code --control` and not an MCP server. stdout carries exactly one protocol frame per response; diagnostics go to stderr. Protocol v1: 20-method allowlist, 256 KiB frame cap, 64 in-flight requests, 30 s default deadline. All 20 methods are implemented: the `initialize` handshake; session/event ingress `session.open`, `event.append` (batch ack / idempotent / digest-conflict / server-side redaction), `session.flush`, `session.close`, `evidence.append`, `provenance.append`; the read methods `context.get`, `status.get`, `history.search`, `checkpoint.list`, `checkpoint.show` and `diff.get`; the mutations `checkpoint.create`, `commit.create`, `checkpoint.restore` and `review.run` (each with `operation_id` idempotency, actor binding and approval gating); and workspace lease `workspace.claim` / `workspace.renew` / `workspace.release` (owner derived from the authenticated bridge session). `diff.get` takes a closed `mode` (`worktree` / `staged` / `checkpoint`) plus validated repository-relative `paths` — never a free-form revision or pathspec — and forces `--no-ext-diff` / `--no-textconv` so repository config cannot become process execution. `commit.create` commits the current index only (no `-a`, no pathspec, no amend, no author override) and records its association graph in `agent_bridge_link` rather than in the commit message. `checkpoint.restore` requires an explicit `expected_head` fence plus a clean index/worktree and never moves HEAD. `review.run` starts a read-only review and returns its `run_id`; replaying the same `operation_id` reports that run's state instead of starting a second one. A stale HEAD or dirty worktree is refused with `LBR-AGENT-038` before any write. An ack only means the redacted projection is durable, never that the Harness raw transcript has been migrated. Not a Git command. |
| `bridge --stdio` | Run the repository-scoped DeepSeek Harness bridge over stdin/stdout (JSON-RPC 2.0 NDJSON). The **only** standard inbound write transport for Harness; it is not `libra code --control` and not an MCP server. stdout carries exactly one protocol frame per response; diagnostics go to stderr. Protocol v1.2: 22-method allowlist, 256 KiB frame cap, 64 in-flight requests, 30 s default deadline. All 22 methods are implemented (Episode generation is opt-in): the `initialize` handshake; session/event ingress `session.open`, `event.append` (batch ack / idempotent / digest-conflict / server-side redaction), `session.flush`, `session.close`, `evidence.append`, `provenance.append`; the read methods `context.get`, `memory.recall`, `status.get`, `history.search`, `checkpoint.list`, `checkpoint.show` and `diff.get`; the mutations `checkpoint.create`, `commit.create`, `checkpoint.restore` and `review.run` (each with `operation_id` idempotency, actor binding and approval gating); and workspace lease `workspace.claim` / `workspace.renew` / `workspace.release` (owner derived from the authenticated bridge session). `memory.episode.record` records a completed DSH turn and invokes Libra's Episode compiler; enable it with `LIBRA_DSH_MEMORY_MODEL`. `context.get` remains a parameter-free, side-effect-free workspace summary. `memory.recall` requires a process-active session, derives the `deepseek-harness:<session_id>` Agent principal server-side, applies the fixed 1600-token Project Memory policy, and returns only after its selection receipt is durable. `diff.get` takes a closed `mode` (`worktree` / `staged` / `checkpoint`) plus validated repository-relative `paths` — never a free-form revision or pathspec — and forces `--no-ext-diff` / `--no-textconv` so repository config cannot become process execution. `commit.create` commits the current index only (no `-a`, no pathspec, no amend, no author override) and records its association graph in `agent_bridge_link` rather than in the commit message. `checkpoint.restore` requires an explicit `expected_head` fence plus a clean index/worktree and never moves HEAD. `review.run` starts a read-only review and returns its `run_id`; replaying the same `operation_id` reports that run's state instead of starting a second one. A stale HEAD or dirty worktree is refused with `LBR-AGENT-038` before any write. An ack only means the redacted projection is durable, never that the Harness raw transcript has been migrated. Not a Git command. |

## Common Options

Expand Down
3 changes: 3 additions & 0 deletions docs/commands/branch.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ The `--contains` and `--no-contains` filters (aliased as `--with` and `--without
| | `--no-column` | | Do not lay the branch list out in columns (equivalent to `--column=never`), countermanding an earlier `--column` (last one wins). Branches list one-per-line by default, so on its own this is a no-op. |
| `-v` | `--verbose` | | List each branch with its tip's short sha and commit subject. Repeat (`-vv`) to also show the upstream-tracking segment `[<upstream>: ahead N, behind M]` (counts omitted when the remote-tracking ref has not been fetched; nothing shown for a branch with no configured upstream). Takes precedence over `--column`. |

Libra-owned local-only Memory state is hidden from local, remote, and `--all`
branch listings. Ordinary user branches with similar names remain visible.

### Flag examples

```bash
Expand Down
3 changes: 2 additions & 1 deletion docs/commands/clone.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ repository. Not supported for `libra+cloud://` sources (rejected with
Narrowings vs Git: (1) Git mirrors `refs/*:refs/*` verbatim; Libra mirrors only
what its fetch transfers — every fetched branch is promoted to `refs/heads/*` and
tags are kept, but ref namespaces Libra does not fetch (e.g. `refs/notes/*`) are
not mirrored. (2) Because Libra's fetch collapses `refs/heads/mr/*` and
not mirrored. The repository-local Memory authority is never fetched or
promoted. (2) Because Libra's fetch collapses `refs/heads/mr/*` and
`refs/mr/*` into one tracking namespace, any such refs are mirrored as
`refs/heads/mr/*` (provenance is not preserved). (3) The `mirror=true` marker is
informational — no `+refs/*:refs/*` refspec is recorded and `libra fetch` is not
Expand Down
5 changes: 5 additions & 0 deletions docs/commands/fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ one source ref and may map it to an exact local destination (`<src>:<dst>`). Whe
explicit refspec is given, `remote.<name>.fetch` entries are honored; if none exist,
all advertised branches use the default `refs/remotes/<name>/*` mapping.

The repository-local Memory authority (`refs/heads/libra/memory/repo`) is
excluded from ordinary discovery plans and wildcard expansion. Explicit
refspecs cannot name it as a source or local destination, and a remote HEAD
that points at it is ignored when choosing the default working branch.

Fetch supports SSH, HTTPS, local file, and `git://` transports. Vault-backed SSH keys
are loaded automatically when configured via `vault.ssh.<remote>.privkey`.

Expand Down
133 changes: 133 additions & 0 deletions docs/commands/memory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# `libra memory`

Search and diagnose repository-local development-history Memory compiled from
Libra Intent, Task, Run, session, decision, evidence, and code-version records.

## Synopsis

```bash
libra memory search <query> [filters] [--limit <n>]
libra memory show <note-id> [--revision <oid>] [--evidence]
libra memory status
libra memory rebuild [--dry-run]
```

## What it reads

Each result is a structured Episode: a bounded summary of one Task or Intent
iteration. The Episode stores claims, outcomes, code anchors, and typed evidence
references. Raw sessions and tool output remain in their existing history; they
are resolved only when `show --evidence` requests them.

`search`, `show`, `status`, and `rebuild --dry-run` are read-only. A plain
`rebuild` replaces only SQLite's rebuildable Memory projection. It does not move
the repository Memory ref or modify authoritative Memory objects.

## Search

Search uses SQLite FTS5 with `bm25()` ranking, followed by structured filters
and code-version applicability checks.

| Option | Meaning |
| --- | --- |
| `--limit <1..50>` | Maximum returned Episodes; default `10` |
| `--root-kind task\|intent --root-id <id>` | Match one Episode root; the flags must be used together |
| `--intent <id>` | Match Episodes related to one Intent |
| `--task <id>` | Match Episodes related to one Task |
| `--ended-from <RFC3339>` / `--ended-until <RFC3339>` | Bound the Episode end time |
| `--completion completed\|failed\|cancelled` | Match the recorded outcome |
| `--code-change changed\|unchanged\|unknown` | Match whether code changed |
| `--path <path>` | Match one exact Memory taxonomy path |
| `--path-prefix <prefix>` | Match a Memory taxonomy path prefix |
| `--include-diagnostics` | Include path-changed, diverged, and unknown code applicability states |

Normal search output shows the stable note ID, exact revision object ID,
Task/Intent root, outcome, code-change status, code applicability, evidence
reference count, BM25 score, and summary. By default, only Episodes safe to
inject at the current code version are returned.

## Show

`show` resolves the current confirmed revision unless `--revision` pins a
historical revision. `--evidence` authorizes every typed reference against the
authenticated repository identity before resolving it with the same source
bounds and redaction policy used during compilation. Missing, unauthorized,
corrupt, or over-budget fragments appear as omissions instead of being silently
substituted. Human output keeps the Episode compact: root and outcome, time
range, goal, summary, claim groups, code anchors/paths, and evidence counts.

## Status

`status` reports:

- the repository Memory ref;
- projection state, projected ref, and last event sequence;
- compile-job state, pending generation, active/expired lease, retry, and error counts;
- linked SQLite FTS5 capability;
- repository digest-key availability and the current frozen view hash.

It does not print Episode content, prompts, job lease tokens, or raw evidence.
The command checks the current head manifest and SQLite watermarks, then scans
at most 4,096 compile-job rows. JSON exposes `jobs.scan_limit` and
`jobs.truncated`; when `truncated` is true, the job counters describe only the
bounded sample. Use `rebuild --dry-run` when a full authoritative-history
validation is required.

## Rebuild

`rebuild --dry-run` validates the complete authoritative history and reports the
head, event, note, revision, and last-sequence counts without writing SQLite.
`rebuild` then reconstructs the repository-scoped projection and FTS index from
that same history. Use it when `status` reports `stale` or after projection
tables are damaged or removed. If validation encounters corrupt history, the
error reports a bounded damage point (Memory head OID or event sequence/object
IDs) without printing note or evidence content.

## JSON

Use the global `--json` or `--machine` flag. The command names are
`memory.search`, `memory.show`, `memory.status`, and `memory.rebuild` inside the
standard Libra envelope:

```json
{
"ok": true,
"command": "memory.search",
"data": {
"view_hash": "...",
"selector_version": "episode-fts-bm25-v1",
"items": []
}
}
```

An empty search succeeds with `items: []`. Invalid filters, missing notes,
unavailable FTS5, stale projection, unknown schema, and corrupt history use the
stable `LBR-MEMORY-*` errors documented in
[`docs/error-codes.md`](../error-codes.md). Corruption errors include the same
bounded location as `details.damage_point` in structured output.

Read commands and `rebuild --dry-run` do not migrate SQLite. A regular
`libra memory rebuild` applies known pending migrations before replay. If the
repository schema is newer than the installed Libra build, the command returns
`LBR-MEMORY-002`; upgrade Libra before retrying.

## Examples

```bash
libra memory search "authentication retry"
libra memory search "timeout" --task task-42 --limit 5
libra memory search "parser" --path-prefix episodic.tasks
libra --json memory search "root cause"
libra memory show <note-id>
libra memory show <note-id> --revision <oid> --evidence
libra memory status
libra memory rebuild --dry-run
libra memory rebuild
```

## Scope

The command covers repository-local Task and Intent Episodes. Manual
remember/delete/update operations, Memory revert, consolidation, MCP tools,
team synchronization, and cross-repository search are outside this command.
7 changes: 6 additions & 1 deletion docs/commands/op.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ refs and Libra-owned internal refs (the locked `main`/`intent`/`traces`
branches and the reserved `libra/` namespace, e.g. the AI history branch
`libra/intent`) are never pruned.

New operation snapshots omit the repository-local Memory authority. When an
older snapshot already contains `libra/memory/repo`, restore skips it, reports
the skipped name, and leaves both its current object ID and projection
watermark unchanged.

```bash
libra op restore [--force] [--dry-run] <OP_REF>
```
Expand Down Expand Up @@ -147,4 +152,4 @@ libra op restore @{1} --dry-run
- `op restore --dry-run` does not write a new operation.
- Restore resets HEAD and the branch refs captured in the target view, and
prunes local branches that are absent from that view (the restored HEAD branch
is always kept; remote-tracking refs are left untouched).
is always kept; remote-tracking refs are left untouched).
Loading
Loading