Skip to content

worklog doctor: environment and connectivity diagnostics #29

Description

@Saber5656

Title

worklog doctor: environment and connectivity diagnostics

Summary

Implement worklog doctor: a check matrix over config, each enabled
source, the LLM endpoint, and the output directory, printing PASS/WARN/FAIL
lines with actionable fixes (notably the zsh EXTENDED_HISTORY guidance) and
exiting non-zero only on FAIL.

Context

The reference machine demonstrates the two onboarding cliffs doctor exists
for: zsh history without timestamps, and an LLM endpoint/model that isn't
running/pulled yet. Doctor turns both from silent degradation into guided
setup.

Scope

  • internal/cli/doctor.go (replace stub) + tests.

Detailed Requirements

  1. Output format (stdout — doctor's report IS its output; stderr only for
    harness errors): one line per check:
    PASS config: loaded (<path>) / WARN zsh: … / FAIL llm: …,
    followed by an indented fix: line for every WARN/FAIL with a concrete
    command or config edit. Final summary line
    doctor: N pass, M warn, K fail. Exit 1 iff K>0, else 0.
  2. Checks (in this order; each isolated — one failure never skips later
    checks):
    • config: load + validate (validation errors → FAIL each, fix
      references the key). Unknown-key warnings → WARN each.
    • zsh (when enabled): file exists+readable (missing → WARN, fix:
      check path/HISTFILE); parse first 2000 entries: ExtendedCount==0 →
      WARN with the exact fix
      echo 'setopt EXTENDED_HISTORY INC_APPEND_HISTORY' >> ~/.zshrc
      (new entries only — note that old entries stay undated); else PASS
      with entry count.
    • git: binary found (ErrGitNotFound → FAIL, fix: install git);
      author identity resolvable (else WARN, fix: set [sources.git] authors or git config --global user.email); each root exists
      (missing → WARN); repos discovered (count in PASS line; zero repos →
      WARN).
    • claude-code / codex (when enabled): dir exists (missing → WARN,
      fix mentions the config key), count of session files with mtime within
      7 days (0 → WARN "no recent sessions").
    • llm (when llm.enabled): endpoint parses + static loopback IP check
      (violation → FAIL with ADR-002 one-liner); Models(ctx, 5s timeout)
      reachable (refused → FAIL, fix: ollama serve or start the server;
      ErrNonLoopbackBlocked → FAIL with the blocked host/IP); configured
      model ∈ returned ids (empty model → FAIL listing first 5 available
      ids as the fix; not-in-list → WARN listing near matches). When
      llm.enabled=false: single line PASS llm: disabled.
    • output (when [output].directory set): exists → writable check via
      os.Stat + unix.Access(W_OK)-equivalent (use
      os.CreateTemp? NO — doctor must not write (I3 applies to doctor
      strictly: it's a diagnostic); use permission-bit heuristic +
      Stat-based ownership check and label it WARN (heuristic) when
      uncertain); missing → WARN "will be created on first --save".
  3. All checks run with a 5s per-check timeout (hung LLM endpoint must not
    hang doctor).
  4. Global flags (DESIGN §4): --config and --verbose are honored;
    --date and --lang parse successfully but are ignored by doctor
    (doctor output is English-only and date-independent; --verbose prints
    a one-line note that they were ignored). --verbose adds detail lines
    (resolved paths, counts) — still stdout.
  5. Testability: checks are small funcs returning
    {Status, Name, Detail, Fix string}; the runner formats. Fake
    providers/clients via the same seams as earlier issues (fixture HOME +
    httptest fake for LLM).

Acceptance Criteria

  • Fixture matrix test: healthy HOME → all PASS, exit 0; each induced
    failure (missing zsh file, simple-format history, git absent from
    PATH via env manipulation, missing model, endpoint down, non-loopback
    IP endpoint) produces its documented line+fix and correct exit code.
  • zsh WARN includes the exact one-line fix command above.
  • LLM FAIL on empty model lists available ids from the fake server.
  • Doctor performs ZERO writes (tree-hash over fixture HOME, including
    the output dir case).
  • Full run with hung LLM (server accepts, never responds) completes in
    < 10s (timeout proven).
  • Output is stable/deterministic (sorted, no timing text) — golden
    test for the healthy case (doctor output is English-only per DESIGN
    §4; --lang parses and is ignored).
  • worklog doctor --date 2026-01-01 --lang en parses and behaves
    identically to a plain run (ignored-flags contract).

Validation

go test -race ./internal/cli/ -run Doctor -v in PR + healthy-case golden
attached. Manual run on the reference machine encouraged; paste is fine
(doctor output contains no personal content beyond paths — verify before
pasting).

Dependencies

07, 09, 11, 14, 15, 23.

Non-goals

Auto-fixing anything (doctor never writes), model pulling, benchmark/latency
measurement.

Design References

  • docs/DESIGN.md §4, §13, §15 (U2/U3), research docs (fix texts)

Source of truth: docs/issues/28-cmd-doctor.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 28 of 33).

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