Skip to content

feat: tag management CLI and trait extensions #35

Description

@asvarnon

Summary

Add tag management CLI commands and trait extensions for user-defined and auto-generated entry tags. Enables filtered queries, organized context retrieval, and integration with importance detection category labels.

Note: Tag tables (tags, entry_tags, indexes) are created in #12 (Schema v2 migration). This issue covers the CLI surface, trait extensions, and auto-tagging logic only.

Motivation

Entries currently have kind (Manual, PreCompact, Auto) but no user-defined categorization. As the store grows, users need to:

  • Filter context by project, language, or topic
  • Preserve important entries from eviction
  • Scope SessionStart injection to relevant domains

Importance detection (#49) will auto-generate category tags (corrective, reinforcing, stateful, decisive) — this issue's tag infrastructure supports that.

Scope

In Scope

CLI Surface:

cf save --kind auto --tags "rust,security"      # manual tags at save time
cf query --tags "rust" --format text             # filter to tagged entries
cf query --tags "rust,auth" --tag-match all      # AND logic (default)
cf query --tags "rust,auth" --tag-match any      # OR logic
cf tags list                                     # all tags with entry counts
cf tags rename <old> <new>                       # rename a tag
cf tags delete <tag>                             # remove tag (entries kept)
cf tags merge <tag1> <tag2>                      # combine into one

Trait Extensions:

// ContextStorage additions
fn add_tag(&self, entry_id: &str, tag: &str) -> Result<()>;
fn remove_tag(&self, entry_id: &str, tag: &str) -> Result<()>;
fn get_tags(&self, entry_id: &str) -> Result<Vec<String>>;
fn list_all_tags(&self) -> Result<Vec<TagInfo>>;
fn rename_tag(&self, old: &str, new: &str) -> Result<usize>;

// Searcher addition
fn search_with_tags(&self, query: &str, tags: &[&str], match_all: bool, limit: usize)
    -> Result<Vec<ScoredEntry>>;

Auto-Tagging (Phased):

  • Phase 1 — Metadata-based: auto-tag by entry kind, size-based large for entries >8,000 tokens
  • Phase 2 — TF-IDF keyword extraction: may be superseded by importance detection's recurrence scoring (feat: implement session frequency and recurrence scoring #47)
  • Phase 3 — LLM-generated tags: extension-layer only, out of scope for core

Assembly Integration:

  • Tag filtering applied before BM25 scoring (narrows candidate set)
  • Optional score boost for tag-matched entries (configurable multiplier)
  • New eviction policy: LruPreserveTagged — evict oldest untagged first

ContextEntry Extension:

pub struct ContextEntry {
    // ... existing fields ...
    pub tags: Vec<String>,  // populated on retrieval via JOIN
}

Out of Scope

Acceptance Criteria

  • cf save --tags persists tags on new entries
  • cf query --tags filters results by tag (AND and OR modes)
  • cf tags list/rename/delete/merge subcommands work correctly
  • Trait extensions implemented on SqliteStorage
  • Phase 1 auto-tagging: kind-based and size-based tags applied at save time
  • Tag-filtered search integrates with BM25 scoring
  • Unit tests for all trait methods
  • Integration tests for CLI tag commands

Dependencies

Complexity: Medium

Trait extensions, CLI plumbing, auto-tagging logic. No schema work needed.

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