molecule-core/workspace-server/internal
Hongming Wang f0f4d0e761 feat(memory): redesign Memory tab for v2 plugin
Replaces the v1 LOCAL/TEAM/GLOBAL tab trio (mapped to the deprecated
shared_context model) with a v2 plugin-driven UI. Without this,
canvas Memory tab was reading the frozen agent_memories table while
all post-cutover agent writes went to the plugin's memory_records —
the tab silently displayed stale data.

## Backend (workspace-server)

New routes under wsAuth, all behind the existing per-tenant token:

  GET    /workspaces/:id/v2/namespaces      → readable + writable lists
  GET    /workspaces/:id/v2/memories        → plugin search proxy
  DELETE /workspaces/:id/v2/memories/:mid   → plugin forget proxy

memories_v2.go — slim handler:
  - Server-side ACL: every search request is intersected with the
    resolver's readable-namespaces set (canvas-supplied namespace
    that the workspace can't read returns [] not 403, matches v1
    existence-non-inferring shape).
  - Returns 503 with "set MEMORY_PLUGIN_URL" hint when plugin
    isn't wired (canvas surfaces a banner).
  - Maps plugin not_found → 404, other plugin errors → 502.
  - View shaping: NamespaceView.label rendered server-side
    ("Workspace (abc-1234)", "Team (t-99)", "Org (acme)", custom)
    so canvas doesn't parse namespace names. MemoryView surfaces
    pin/expires_at/score/source_workspace_id from Propagation.

memories_v2_test.go — 100% line + 100% function coverage:
  - 503 path on every endpoint when unwired
  - Namespaces success + readable/writable error paths
  - Search: empty intersection, full-path query/kind/limit
    propagation, namespace=/no-namespace branches, propagation
    map missing/wrong-type, intersect error, plugin error
  - Forget: success, plugin not_found→404, other plugin
    errors→502, missing memoryId→400
  - Helpers: namespaceLabel for all 4 kinds + truncation,
    parseLimit edge cases (default/0/negative/over-cap/non-num),
    memoryToView field round-trip, indexOfColon, shortID

## Frontend (canvas)

MemoryInspectorPanel rewritten for v2:
  - Drop LOCAL/TEAM/GLOBAL trio. Namespace dropdown driven by
    GET /v2/namespaces.readable, "All namespaces" default.
  - New per-row badges: kind (F/S/C), source (agent/runtime/user),
    pin (📌), TTL countdown (12h / "expired"), score% on
    semantic search, source-workspace ⇡ws-pee for propagated.
  - Drop Edit button — v2 plugin contract has no PATCH; the
    model is forget + recommit. Forget stays.
  - Plugin-unavailable banner with operator hint when /v2/*
    returns 503.
  - Bug fix surfaced by test: rollback-on-failed-delete order
    of operations (loadEntries() called setError(null) AFTER
    we set the failure message, wiping it). Reload first, then
    set the error.

MemoryEditorDialog deleted — Add was POST /memories which v2
doesn't support from canvas (writes go via MCP). The legacy
Edit-flow tests go with it.

## Test results

Backend: `go test ./internal/handlers/` — all pass
Backend coverage on memories_v2.go: 100% lines, 100% functions
Canvas: `vitest run` — 91 files, 1273 tests pass (26 new)
Canvas coverage on MemoryInspectorPanel.tsx: 100% lines,
  100% functions, 96.7% statements, 84.7% branches
  (uncovered branches are defensive `?? fallback` for
   contract-impossible kind/source values)

## Migration note

The legacy v1 GET/POST/PATCH/DELETE on /workspaces/:id/memories
remains in place for the back-compat MCP shim (mcp_tools_memory_v2's
legacy routing) and admin export/import. PR-9 (#283) drops
agent_memories along with the v1 endpoints once the cutover
verification window closes.
2026-05-05 15:53:28 -07:00
..
artifacts
buildinfo feat(deploy): verify each tenant /buildinfo matches published SHA after redeploy 2026-04-30 10:55:08 -07:00
bundle fix(bundle): markFailed sets last_sample_error + AST gate 2026-05-04 21:08:08 -07:00
channels
crypto
db fix(bundle): markFailed sets last_sample_error + AST gate 2026-05-04 21:08:08 -07:00
envx
events
handlers feat(memory): redesign Memory tab for v2 plugin 2026-05-05 15:53:28 -07:00
imagewatch
memory fix(memory v2): warn at boot when cutover env half-configured 2026-05-04 17:24:11 -07:00
metrics feat(rfc): poll-mode chat upload — phase 3 GC sweep + observability 2026-05-05 05:00:13 -07:00
middleware fix(tenant-guard): allowlist /buildinfo so redeploy verifier can reach it 2026-04-30 12:54:51 -07:00
models refactor(models): consolidate per-runtime model defaults to SSOT (RFC #2873 iter 1) 2026-05-05 04:12:37 -07:00
orgtoken
pendinguploads Merge pull request #2907 from Molecule-AI/feat/poll-mode-chat-upload-phase5a 2026-05-05 11:16:56 -07:00
plugins
provisioner feat(workspace-server): structured logging at provisioning boundaries 2026-05-05 12:30:11 -07:00
provlog feat(workspace-server): structured logging at provisioning boundaries 2026-05-05 12:30:11 -07:00
registry fix(orphan-sweeper): exclude runtime='external' from stale-token revoke 2026-05-03 00:49:37 -07:00
router feat(memory): redesign Memory tab for v2 plugin 2026-05-05 15:53:28 -07:00
scheduler feat(metrics): add molecule_phantom_busy_resets_total counter (#2865) 2026-05-05 04:45:24 -07:00
supervised
ws
wsauth perf(wsauth): in-process cache for platform_inbound_secret reads 2026-05-03 00:04:38 -07:00