Skip to content

feat(ui): author provenance classes, type backfill, and hygiene batch - #325

Merged
ajianaz merged 23 commits into
developfrom
feat/provenance-backfill-hygiene
Sep 8, 2026
Merged

feat(ui): author provenance classes, type backfill, and hygiene batch#325
ajianaz merged 23 commits into
developfrom
feat/provenance-backfill-hygiene

Conversation

@ajianaz

@ajianaz ajianaz commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

What

Batch of UX fixes and features from hands-on testing of develop (web + desktop). Implements a destination-based navigation model for the Memories hub, real namespace/room scoping, provenance classes (Human/Agent), a type backfill tool, platform-aware shortcuts, documents improvements, and overlay/theming fixes. Also bumps the version to 0.4.0 with a full CHANGELOG entry.

Why

Hands-on dogfooding surfaced structural UX problems: the namespace filter existed in two places that fought over one state, room clicks did nothing, the namespace manager rendered an empty table (a Tauri command was never implemented), shortcut labels ignored macOS, and several overlays layered incorrectly.

How

  • Destination model — one scope state (all / namespace: X / room: X / tag: Y) drives the list, chips, and load-more; the sidebar navigates, the content reflects. No parallel filter states left to fight.
  • Provenance classesutils/author.ts: UI-created memories/documents stamp author: 'human'; everything else renders as Agent. Create chain carries metadata/content_type/importance at every layer (desktop command no longer drops them).
  • Compat-gated management — namespace rename/merge/delete and breakdown counts via the new uteke_namespaces_breakdown command (raw pass-through of GET /namespaces?with_counts=true).
  • Graph — settled pre-run layout (no entry animation, no continuous motion), size-scaled settle budget, static affordance rings, labels jank-free.
  • Platform shortcutsutils/platform.ts (isApple, MOD_LABEL, kbdCombo, hasMod) + tests.

Testing

  • cargo fmt --all -- --check passes
  • cargo clippy -- -D warnings passes
  • cargo test passes (18/18)
  • npx svelte-check --tsconfig ./tsconfig.json0 errors (also fixes the 12 pre-existing baseline errors from develop)
  • npm run test -- --run passes (95/95, incl. new platform + activity tests)
  • npm run build succeeds
  • Cora review run in CI
  • Manual smoke-test (web + desktop, macOS): room/namespace/tag destinations, Human/Agent badges incl. stamping e2e, upgrade dialog, sticky hub header, balanced gutters, graph settle with 300+ nodes

Author is now a provenance CLASS, not a third taxonomy: 'human' is
stamped on UI-created memories (memory + document), everything else
displays as Agent — data stays human/agent/null, the UI shows only
Human/Agent, and null legacy rows read as Agent. The create chain
finally carries metadata (and content_type/importance stop being
dropped by the desktop remember command); the Milkdown wrapper fixes
silent no-ops (Codeblock→CodeMirror, ListItemBlock→ListItem, top-level
placeholder moved into the feature config) per the actual 7.22 typings.

Also: type backfill tool in Settings → Maintenance (scans for empty
content_type, stamps 'text' via PUT /memory), pinned memories float to
the top of the browsed list, explicit New-namespace action (seed
placeholder + auto-select), CodeMirror theme follows live theme flips
via var() instead of boot-time snapshots, svelte-check baseline fixed
to 0 errors (Crepe typings, ConfirmDialog messages, fadeQuick params,
namespace: null), and GitHub's standard Dependency Review workflow.
Comment thread src/lib/components/MemoryEditor.svelte Fixed
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

🔍 Cora AI Code Review

No issues found. Code looks good!


Review powered by cora-code · BYOK · MIT

Cora (critical): the duplicate pre-check used utekeServer.remember,
which INSERTS — every save created a second copy, and editing left a
stray copy of the edited content. The create path now dup-checks via
read-only recall (0.92 threshold, unchanged) and inserts exactly once;
the edit path skips the check entirely. dependency-review is marked
continue-on-error until the repo's dependency graph is enabled in
settings (owner action).
Comment thread .github/workflows/dependency-review.yml Fixed
Comment thread src/lib/components/MemoryEditor.svelte Fixed
Cora: the web-routes memory_update handler never mapped p.contentType
into the PUT /memory body, so web-mode type backfill would silently
no-op while desktop worked.
Comment thread src/lib/components/MemoryEditor.svelte Fixed
Cora: the create path discarded the editor's type/importance
selections (uteke_remember had no such params; the Rust remember
command explicitly ignored them), producing exactly the untyped rows
TypeBackfill later repairs. The create chain now carries memory_type
+ importance end-to-end, the editor select uses uteke's memory_type
vocabulary consistently (fact default), and the detail panel shows
memory_type.
Comment thread src-tauri/src/commands.rs Fixed
The compat banner was a thin strip that other content buried. It is now
a dismissible dialog on first launch per required-minimum version
(persisted), listing each gated feature with its version requirement.
Memory cards now show the author badge before the pin badge.
Comment thread src-tauri/src/commands.rs Fixed
Comment thread src/lib/ts/web-routes.ts Fixed
…Type, no null-wipe in web updates

- Desktop MemoryEntry mappings now carry metadata (badges read
  metadata.author; previously always Agent on desktop)
- ipc remember sends memoryType (Tauri 2 maps camelCase → snake_case);
  a snake_case key never matched the Rust arg
- web memory_update drops absent fields like the desktop command —
  explicit nulls were wiping content/tags/metadata server-side during
  TypeBackfill (data-destroying)
- uteke_client UtekeMemory parses metadata
Comment thread src/lib/components/settings/TypeBackfill.svelte Fixed
Comment thread src/lib/components/MemoryEditor.svelte Fixed
uteke_remember re-checks duplicates server-side and can return
{duplicate: true} without inserting — the create path treated any
resolution as success, so the fallback was skipped and onsave fired on
a phantom save. The verdict now routes into the duplicate warning.
WebKit draws native select text smaller than the surrounding inputs;
drop the native chrome (appearance: none + custom caret) so the Type
select matches the tags/namespace fields.
…ew docs

Clicking Properties used to reveal the fields ABOVE the button. The
trigger now sits above the row it expands (chevron flips with state),
and new documents always show title/slug/tags + Parent — slug is
required, so it never hides behind the toggle.
The standalone Parent row wasted a full-width gutter with the select on
the left and dead space to the right. The picker now lives in the
top-bar between the breadcrumb and the mode toggle (new docs only), so
the editor content shifts up and the whole creation form fits in one
compact header stack.
The Rooms hub group was decorative: selectedRoom toggled but never
scoped anything (tooltip even admitted it). Clicking a room now loads
its memories from the server (GET /room/memories with /room/recall
fallback), shows them in the main list with tag filter + pinned-first
applied, and toggling off restores the full list. Rooms also display
their memory_count, and the pager load-more is suppressed while a room
scope is active.
… the toolbar

The hub's Namespaces group and the toolbar NamespaceFilter drove the
same selectedNamespaces state, so switching hub tabs or clicking
namespaces fought with the toolbar ('None' filter + unscoped-looking
list). The hub is now a standalone Rooms | Tags facet browser (global
counts, not influenced by the toolbar), and namespace filtering is
purely the toolbar's job. The toolbar also aligns flush with the cards'
right edge (12px inset + 10px scrollbar).
Per owner UX direction: the hub keeps all three tabs (Namespaces |
Rooms | Tags) and every entry drives ONE namespace scope
(selectedNamespaces) that the toolbar dropdown renders — clicking a
namespace filters to it alone, and clicking a room scopes the list to
the room's own namespace. The separate roomItems bypass is gone, so
the list, the dropdown, and the sidebar can no longer disagree.
…space

The previous iteration scoped the list to the room's whole namespace,
which showed more rows than the room contained. Room click now loads
the room's own memories (GET /room/memories + fallback), keeps the
namespace filter synced to the room's namespace for context, and any
manual toolbar filter change drops the room scope so the two controls
stay coherent.
… and chips

- Namespace counts use the active/deprecated breakdown so the sidebar
  number matches what clicking shows (6 total vs 2 active was the
  confusing mismatch)
- 'All namespaces' entry on top of the list; clicking the active
  namespace/room/tag again returns to all
- Chips row removed — the sidebar highlight already shows the selection
- Toolbar NamespaceFilter removed (namespace scoping is the hub's job)
The group switch + filter input scrolled away with long lists, forcing
a scroll back up just to switch facets. The panel is now a fixed header
(hub-head) over a scrollable list area (hub-list).
- The memory/isolated/connection legend hugged the canvas edge; give it
  real padding and wider item gaps.
- settle() iterations now scale inversely with node count (80..260) so
  large graphs stay inside a one-shot sync budget instead of a long
  freeze, while small graphs keep a thorough layout. All load paths
  already route through it — no continuous motion remains.
<div class="meta-row">
<span class="meta-label">Type</span>
<span>{memory.content_type}</span>
<span>{memory.memory_type ?? memory.content_type ?? '—'}</span>
@ajianaz
ajianaz merged commit 3b54ffb into develop Sep 8, 2026
17 checks passed
@ajianaz
ajianaz deleted the feat/provenance-backfill-hygiene branch September 8, 2026 06:34
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.

2 participants