Skip to content

feat(recall): add bounded atomic memory manifest - #2192

Open
Tech-Circle-48 wants to merge 12 commits into
oceanbase:masterfrom
Tech-Circle-48:s3
Open

Tech-Circle-48 wants to merge 12 commits into
oceanbase:masterfrom
Tech-Circle-48:s3

Conversation

@Tech-Circle-48

@Tech-Circle-48 Tech-Circle-48 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Which issue or RFC does this PR close?

Closes #1864

Rationale for this change

Agents currently need to retrieve memory content before deciding which entries are useful. A bounded, metadata-only manifest provides a cheaper first step, allowing agents to select entries before fetching their full content.

What changes are included in this PR?

  • Add a paginated Atomic Memory recall manifest through HTTP, MCP, and the Python client.
  • Store descriptions with memory revisions and their current search projections.
  • Generate descriptions alongside text during extraction and reconciliation.
  • Preserve model-free explicit writes by storing a bounded, single-line text preview when no description is supplied.
  • Update integration bindings, migration compatibility, documentation, and regression tests.

Are there any user-facing changes?

  • Add POST /v1/recall/manifest and get_recall_manifest.
  • This initial implementation covers active Atomic Memory only.
  • Callers may supply an optional description. Omitting it does not require an LLM.
  • Manifest reads return metadata without reading memory bodies or invoking models.
  • Historical memories without descriptions remain readable; their manifest descriptions may be null.
  • Manifest pagination defaults to 50 entries, with a maximum of 100.

How was this change tested?

  • make check
  • Python and JavaScript API generation consistency checks.
  • HTTP/MCP contract tests.
  • Non-Desktop Python regression suite: 6,175 passed, with 10 working-directory-dependent tests passing on rerun from the repository root; 593 skipped.
  • Dify and OpenDAL integration checks.
  • DSH unit and end-to-end tests, plus build reproducibility verification.
  • Manual Postman verification of memory writes and manifest responses.

AI usage statement

@hidb4ai hidb4ai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tagged manifest path rejects valid input, and the Desktop and skill-validation contracts need to be synchronized. Details inline.

Comment thread src/powercontext/server/atomic_memory.py
* Read a bounded metadata-only recall manifest
* @description Lists active Atomic Memory metadata only. Empty inventory never proves the Scope has no context or authorizes skipping prepare_context. Fetch selected exact refs with get_artifact_revision. Pagination is live keyset order, not a cross-request snapshot.
*/
post: operations["get_recall_manifest"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Regenerate the complete Desktop contract

The Desktop contract outputs are out of sync with this OpenAPI change. Both ui/src/generated/operations.ts and src-tauri/src/transport/operations.json still carry the base contract hash, so tests/test_desktop_contract.py fails. Windows CI also stops at generate:check with a drift error for src-tauri/src/transport/wire.rs. Please run pnpm --dir desktop generate and commit all affected outputs together so Desktop validation and builds succeed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more symptom in the same file set: api.d.ts was regenerated from a stale draft, not just left without a new hash.

Both AtomicMemoryWriteContent and RememberMemoryRequest.description carry this doc string at the PR head (desktop/ui/src/generated/api.d.ts:2375 and :4465):

"Optional supplied single-line summary. When omitted, the Server generates it before writing; without a generation model the write fails with inference_unavailable."

That sentence appears nowhere in openapi/powercontext.yaml. The contract says the opposite at :5461 and :11058 - a whitespace-collapsed prefix of the final text, and "Explicit writes do not invoke a generation model". default_description in builtin/artifacts/atomic_memory/summary.py implements the model-free prefix.

So this file is currently worse than absent: it documents behavior the implementation does not have, and it is the artifact Desktop and integration consumers read. Regenerating the whole Desktop output set from the current contract fixes both this and the identity drift.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked at 080b2d29: this is still reproducible. wire.rs and the description docs have been updated, but ui/src/generated/operations.ts and src-tauri/src/transport/operations.json still carry the base hash a6758fd3…, whereas the current OpenAPI hash starts with d183fce0…. Both assertions in tests/test_desktop_contract.py still fail, and the current Windows job stops with Contract drift: ui/src/generated/operations.ts. Please regenerate and commit the complete Desktop outputs from the current contract before resolving this thread.

Comment thread src/powercontext/server/mcp.py
Comment thread src/powercontext/builtin/runtime/composition.py Outdated
Comment thread src/powercontext/builtin/artifacts/atomic_memory/extraction.py Outdated
@Tech-Circle-48
Tech-Circle-48 requested a review from frf12 as a code owner October 22, 2026 10:10

@hidb4ai hidb4ai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked at 080b2d2. The tag conversion and skill catalog fixes pass. A manifest pagination issue remains below; the Desktop contract mismatch is still reproducible and is followed up in its original thread.

"scope_id": self.scope_id,
"subject": self.application.security.subject(context),
"kind": kind,
"tags": None if tag_filter is None else list(tag_filter.keys),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Keep returned manifest cursors within the accepted request limit

The cursor embeds the complete UTF-8 tag filter before base64 encoding, while RecallManifestRequest.cursor is capped at 4096 characters. With tags ["界" * 63 + chr(97 + i) for i in range(16)] (all within the supported limits), two active memories tagged with the first label, tag_match: "any", and limit: 1, the first HTTP request returns 200 with a 4458-character next_cursor. Passing that cursor unchanged to page two returns 422; the Python request model also rejects it as string_too_long. A short-tag control paginates successfully. Please ensure every cursor produced for accepted filters can be used in the next-page request.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(recall): add a manifest read path for two-stage bounded recall

3 participants