Skip to content

zsh source provider: resolution, filtering, warnings #11

Description

@Saber5656

Title

zsh source provider: resolution, filtering, warnings

Summary

Wrap the zsh parser (09) in a source.Provider: resolve the history file
path, open it read-only, filter entries to the report range, apply
exclude_patterns, and emit Events and the documented warnings
(DESIGN.md §7.1).

Context

This provider is where the "simple-format history cannot be date-filtered"
reality becomes a clean user-facing behavior: zero events + a
zsh_no_timestamps warning that doctor (28) later explains.

Scope

  • internal/source/zsh/provider.go + tests.

Detailed Requirements

  1. New(cfg config.SourcesZsh, resolve func() string) *Providerresolve
    is the already-config-aware path resolver from 05
    (config.ZshHistoryFile()); provider stores the resolved path lazily at
    Collect time (HISTFILE may differ between construction and run in tests).
  2. ID() returns model.SourceZsh.
  3. Collect:
    • Missing file → warning zsh_history_missing (message includes the
      resolved path), zero events, nil error.
    • Open os.Open (read-only); never create/lock. Parse via
      ParseReader with default caps.
    • Stats.Truncated → warning zsh_file_truncated.
    • Stats.Oversized > 0 || Stats.Malformed > 0 → warning
      zsh_lines_skipped with both counts in the message (surfaces the
      parser's skip-and-count so degradation is never silent).
    • If ExtendedCount == 0 && SimpleCount > 0 → warning
      zsh_no_timestamps (message: entry count + one-line fix hint), return
      zero events.
    • Range filter: keep entries with HasTimestamp && rng.Contains(Start).
    • exclude_patterns (pre-compiled at construction; compile errors were
      already rejected by config validation): a match on the raw command
      drops the entry silently (privacy feature — no per-entry warning, no
      count leak; document in code comment).
    • Event mapping per DESIGN §7.1: Kind=KindCommand, Start, End = Start + Duration when Duration > 0, Project="", Title = first 200
      runes of the command's first line (raw; sanitize/redact happen in the
      18 pipeline stage), Meta = {"duration_s": <int>} when Duration > 0.
    • Respect ctx: check ctx.Err() at least every 1000 entries; on
      cancellation return what was collected so far with nil error (collector
      already adds the timeout warning).
  4. No sorting here (collector sorts globally).

Acceptance Criteria

  • Extended fixture + range covering only day D → exactly the day-D
    entries become Events with correct Start/End and duration Meta.
  • Simple fixture → 0 events + zsh_no_timestamps warning (and no
    others).
  • Missing path → zsh_history_missing, nil error.
  • exclude_patterns=["^secretcmd"] drops matching entries; count
    difference asserted; no warning emitted for drops.
  • Fixture with one oversized and one malformed line → single
    zsh_lines_skipped warning whose message contains both counts;
    clean fixture → no such warning.
  • Range boundaries: entry at exactly 00:00 included, at 24:00 excluded
    (half-open contract).
  • Title capped at 200 runes; multiline command flattened to first line
    in Title (assert with the multiline fixture).
  • Read-only proof: fixture file mtime + content hash identical
    before/after Collect (test helper asserts).
  • -race clean; provider satisfies source.Provider (compile-time
    var _ source.Provider = (*Provider)(nil)).

Validation

go test -race -cover ./internal/source/zsh/ in PR.

Dependencies

08, 09.

Non-goals

doctor formatting of the fix hint (28), aggregation grouping (18),
redaction (16–18).

Design References

  • docs/DESIGN.md §7.1, §13
  • docs/research/zsh-history-format.md

Source of truth: docs/issues/10-zsh-provider.md (PR #1, branch docs/v1-design). If this issue and the repo docs disagree, the docs win. Execution order and dependencies: docs/ISSUE_PLAN.md (this is issue 10 of 33).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions