Skip to content

feat(web): Namespace cluster — placeholder/echo/hot-reload/default polish (single PR) #581

@memtomem

Description

@memtomem

Why

A PR #575 follow-up end-to-end trace surfaced a mental-model gap cluster in namespace handling. The Index-tab input → _resolve_namespace() priority → Search/Sources display looks like one coherent path, but placeholder vs. actually-applied NS vs. default-handling asymmetry breaks in different directions on each leg. A user meeting NS for the first time loses the input → result → rediscovery journey at every seam.

This issue bundles the corrective work into a single PR. Splitting it touches the same function area four separate times, forces the UX writer through four passes, and asks the user to learn "what is a namespace" across four release notes instead of one. (Surfacing the Search NS filter in prod — 4.10a — is on a different decision axis ("NS CRUD model") and lives in #5.2.)

Tasks

  • 4.3 Auto-NS preview echo + honest placeholder
    • New GET /api/index/preview-namespace?path=... (server-side, calls _resolve_namespace(), single round-trip)
    • On namespace input focus, call preview with the current path (300ms debounce) and show the resolved NS as a dynamic hint
    • Add a Namespace row to #index-result echoing the actually-applied NS
    • Replace placeholder text default (auto-ns active) with something honest like auto-determined from path so users don't trust the placeholder as the actual default
  • 4.13 Hot-reload placeholder when Settings change
    • Re-invoke _syncIndexHints() (web/static/settings-config.js) on Settings save success (event bus or STATE.serverConfig update hook)
    • Toggling enable_auto_ns in Settings → Config updates the placeholder without a page reload
  • 4.14 Document the default_namespace == "default" backward-compat asymmetry
    • Add to the Default NS field guide text in settings-config.js: "Leaving this as 'default' results in untagged chunks (backward compatibility)."
  • 4.15 Memory_dir root edge case — no separate work; the 4.3 echo surfaces it automatically.

Decisions made

Why a single PR (cluster)

  1. The cluster framing itself says "the legs disagree" — fixing one leg at a time leaves the disagreement in another shape.
  2. UX writer makes one consistent pass — splitting produces placeholder/toast/helper text in different tones at different times.
  3. Users learn "what NS is" from one release note, not four.
  4. The footprint is the same code area: _syncIndexHints(), _resolve_namespace(), the Default NS helper text, and the #index-result NS row.

Preview default — server-side endpoint

Option A (server /api/index/preview-namespace) vs option B (client-side inference). Option A. Same trust model as #5.1b — the server is source-of-truth for resolution rules; reimplementing rule-glob matching in the client introduces drift on every server change. Throttled (300ms debounce) input-focus calls absorb the round-trip cost.

4.14 helper text default — avoids migration

The code-unification option (have "default" also be a tag) carries a data migration cost:

  • Existing chunks indexed under default_namespace="default" are stored as NS=None.
  • After unification, new chunks get NS="default" → the same user's chunks split across two NS values in search.
  • A backfill SQL (UPDATE chunks SET namespace='default' WHERE namespace IS NULL) or query-time COALESCE(namespace, 'default') is required.

Helper-text path is migration-zero; documenting backward-compat intent is itself the value. Code unification ships in a future PR with its own migration plan.

References

All paths under packages/memtomem/src/memtomem/.

  • IndexEngine namespace resolve: indexing/engine.py: IndexEngine._resolve_namespace() (~474)
  • Index endpoint: web/routes/system.py: trigger_index() (~807)
  • Placeholder hint sync: web/static/settings-config.js: _syncIndexHints() (~125)
  • Index tab markup: web/static/index.html: <div id="tab-index">
  • #index-result table: folder panel in web/static/index.html
  • ADR-0004 (Sources vs Index): docs/adr/0004-*.md

Test plan

  • Unit — _resolve_namespace() covers all four priority cases (explicit / rules / auto / default)
  • Unit — /api/index/preview-namespace returns the documented JSON shape (resolved_namespace)
  • Integration (Playwright) — with enable_auto_ns=true and default_namespace="personal", entering /work/notes shows preview hint notes
  • Integration — toggling enable_auto_ns in Settings updates the placeholder without reload
  • Integration — running an index updates #index-result with the applied NS row
  • i18n parity (en + ko changed in the same commit)

Out of scope

  • 4.10a Surface the Search NS filter dropdown in prod — different decision axis ("NS CRUD model") → docs: post-STM-extraction cleanup + ground-truth count fixes #5.2.
  • 4.10b NS CRUD (color / description / rules editing) prod exposure — auto-create vs. predefine model decision → ADR.
  • 4.14 code-unification option — separate PR + migration plan.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions