Skip to content

RFC: absorb safedel trash-store primitives into filekit (no current consumer — deferred) #14

@djdarcy

Description

@djdarcy

RFC: Absorb safedel trash-store primitives into filekit (no current consumer — deferred)

Status: deferred / informational

This issue captures investigation findings for a possible future migration. No work is planned. Filed because:

  1. We (the owners of both repos) want to preserve the design thinking so it isn't lost
  2. If a future consumer emerges who needs recoverable deletes at library level, this issue is the starting point
  3. The investigation was substantial (2 parallel agents, multiple design docs) and shouldn't be re-derived from scratch later

The question

Should filekit absorb dz safedel's trash-store primitives (staging, recovery, listing, link classification, protection zones, time-pattern matching, volume routing) so any filekit consumer can do recoverable deletes in-process without a subprocess call?

TL;DR answer: not now

Reason: no consumer besides safedel itself currently needs this. The only caller who would benefit (dazzlecmd Phase 3.5.A mode switch) can simply subprocess to dz safedel directly, because safedel is part of dazzlecmd core and is guaranteed available wherever dazzlecmd runs.

Filekit's existing layering contract ("primitives layer — stateless, no policy, no workflow orchestration", per docs/preservelib-integration.md) explicitly puts trash-store logic in the higher workflow layer. Moving it into filekit would be a deliberate scope expansion with no justifying consumer.

What the investigation found

Safedel code surface (3,507 LOC across 8 modules in dazzlecmd/projects/core/safedel/):

  • _store.py (568 LOC) — TrashStore class; nearly CLI-free; prime migration candidate
  • _classifier.py (337 LOC) — link-type classification; blocked by unpackaged links tool dependency
  • _zones.py (350 LOC) — 4-tier protection zones; pure policy
  • _platform.py (508 LOC) — staging, EXDEV handling, metadata; partially duplicated in filekit v0.2.4
  • _timepattern.py (390 LOC) — time grammar; pure logic, zero deps
  • _volumes.py (449 LOC) — per-volume trash routing; Windows ctypes + unctools
  • _recover.py (572 LOC) — subcommand implementations; CLI-heavy

Filekit current state (v0.2.4, C:\code\filetoolkit\github\dazzle_filekit\):

  • operations.py, metadata.py, paths.py, platform/windows.py, utils/, verification.py
  • No trash-related code
  • Phase 8 migration (commit d5a56b3, 2026-04-11) already moved primitives FROM safedel INTO filekit: atomic_write_json, copy_tree_preserving_links, metadata module
  • Explicit scope boundary from docs/preservelib-integration.md: "filekit = stateless primitives, no manifest concepts, no workflow orchestration, no tool-specific policy"

Historical context:

  • Safedel was born in dazzlecmd/projects/core/ on 2026-04-08. It was never considered for filekit's codebase.
  • Phase 8 completed the intended primitive-level migration (things that belonged in filekit moved there)
  • What remains in safedel is intentionally workflow and policy — TrashStore lifecycle, zone enforcement, time-pattern grammar, volume registry
  • The 2026-04-10__21-28-00__claude-plan__filekit-v0.2.4-additive-consolidation-restart.md plan explicitly listed "Moving volume serial / SUBST detection (stays in safedel)" under out-of-scope

If we DID do this migration — phased plan (for future reference)

Phase 1 (~150 LOC, cleanup only, no new filekit code): Remove duplicated ADS detection and detect_platform() from safedel's _platform.py; safedel imports from dazzle_filekit.platform.windows and dazzle_filekit.utils.compat directly. Zero-risk cleanup.

Phase 2 (~1,200 LOC into filekit v0.3.x): Move pure-logic modules with no CLI coupling and no links tool dependency:

  • _timepattern.pydazzle_filekit/trash/timepattern.py
  • _zones.pydazzle_filekit/trash/zones.py (config path becomes configurable, not hardcoded ~/.safedel/)
  • Dataclasses from _store.pydazzle_filekit/trash/types.py

Phase 3 (~1,000 LOC into filekit): Staging, TrashStore, volumes, pure recovery logic. Requires links dep resolution (Phase 4 blocker) OR design classifier to accept pre-classified input.

Phase 4 (~340 LOC): Classifier migration; dz safedel tool becomes ~400 LOC CLI wrapper.

Total: ~2,500 LOC migrate from safedel to filekit, with ~2,500 LOC of tests portable. dz safedel the tool shrinks from 3,500 to ~600 LOC.

Architectural tension (the reason for deferral)

From the oracle-agent investigation:

"Upstreaming trash-store logic into filekit would create primitives with no consumer other than safedel itself. No other tool in the ecosystem (claude-session-logger, fixpath, links, github-traffic-tracker, preservelib) has trash-store needs."

The layering contract at docs/preservelib-integration.md would need to be explicitly relaxed ("filekit may host workflow orchestration when justified by multiple consumers"), OR we accept that this migration makes filekit broader-scope on the promise of future consumers.

Blocker for Phase 4 (if migration ever starts)

_classifier.py imports detect_link from projects/core/links/links.py — a sibling dazzlecmd tool that is not a pip-installable package. This blocks classifier migration to filekit cleanly. Options when the time comes:

  1. Package links as standalone dazzle-links library; filekit adds optional dep
  2. Port link-detection logic into filekit itself (duplicates links.py functionality)
  3. Design classifier to accept pluggable link-detector protocol

Sources

  • Senior-engineer audit: 2026-04-16__14-40-26__both_destructive-ops-should-use-filekit-and-safedel.md (dazzlecmd private/claude) — Appendix A
  • Oracle design history: same doc — Appendix B
  • Phase 8 completion: commit d5a56b3 in dazzle-filekit repo
  • Safedel original design: safedelete-tool-design.md in projects/core/safedel/private/claude/
  • Filekit layering contract: docs/preservelib-integration.md

Related

The alternative we chose instead

On 2026-04-16, after this investigation, we chose a different path for dazzlecmd's trash needs: direct Python import of safedel as a library, via a dedicated api.py module in projects/core/safedel/. Rationale:

  • safedel IS part of dazzlecmd core (always present wherever dazzlecmd runs)
  • Python imports are in-process and fast — no subprocess overhead
  • safedel's TrashStore and staging helpers are already library-quality code with structured return values
  • A dedicated api.py gives mode.py a stable import surface decoupled from safedel's private internals
  • Zero scope expansion for filekit; zero new library built with one consumer

That work is tracked in a companion issue on dazzlecmd: "Expose safedel public API (api.py) and adopt from mode.py". This filekit RFC becomes moot for dazzlecmd's needs.

Next steps

None planned. This issue stays open as an informational placeholder documenting the investigation. Close with wontfix if we conclude the migration will never happen; re-prioritize if a real second consumer emerges who needs in-process trash primitives AND can't use safedel directly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions