Skip to content

P4: categorization + bucket routing (port FxFiles ShelfClassifier) #55

Description

@ehsan6sha

Phase 4 — categorization + bucket routing (fula-mcp)

Pure-logic phase (no network, no crypto). Port FxFiles file classifier + category->bucket mapping to Rust so AI-stored files get the EXACT same ShelfCategory and native v8 bucket as the FxFiles app, enabling later adoption.

Scope

  • category module in crates/fula-mcp/src/:
    • Category enum mirroring Dart ShelfCategory (link, note, screenshot, image, video, audio, document, file, other) with the same order.
    • classify(mime: Option<&str>, filename: &str, text: Option<&str>) -> Category porting ShelfClassifier.classify exactly: text/plain (or no-MIME) + non-empty payload short-circuits to link (single URL) or note; image/* -> screenshot (filename matches /screenshot/i) else image; video/* -> video; audio/* -> audio; application/pdf -> document; text/* -> note; application/* -> file; else other. When MIME absent, derive from the filename extension using the FxFiles isImage/isVideo/isAudio/isDocument lists (dependency-light; no mime crate) so behavior matches the app.
    • native_category_bucket(cat) -> Option<&'static str> returning the FxFiles native v8 content bucket (images->images-v8, videos->videos-v8, audio->audio-v8, documents->documents-v8; document maps to documents-v8). Categories with no native content bucket (link/note/screenshot/file/other) return None. Document the AI-workspace convention: AI writes to its OWN workspace; the category tells FxFiles where to adopt the file later.
  • Wire pub mod category; into lib.rs.

Source of truth (FxFiles, ported verbatim)

  • lib/core/services/shelf_classifier.dart
  • lib/core/models/shelf_item.dart (ShelfCategory enum + order)
  • lib/core/services/bucket_version_resolver.dart (category->bucket, -v8 routing)
  • lib/core/models/fula_object.dart (extension lists for the no-MIME fallback)

Tests

Table-driven (mime, filename, text) -> Category covering every ShelfClassifier branch (each case cites the Dart rule it pins) + native_category_bucket per category + extension-fallback (no-MIME) cases. Offline; cargo test -p fula-mcp green.

Out of scope

No MCP protocol, no network, no crypto, no actual bucket writes (that is P5 fula_store_file). This phase is the pure classifier + bucket-name resolver P5 will call.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions