firstsun-dev_git-files-sync/session-handoff.md
ClaudiaFang 671ce93371 chore: update harness state files (progress, handoff, feature list)
Records this session's completed work (#33, #36, #31, #39 consolidated
onto PR #51 alongside the prior session's #40/#41/#42/#48) and the
paused state of feat-009 (#38 i18n), which is blocked on a scope
decision from the user before any code is written.
2026-07-13 14:08:36 +00:00

5.9 KiB

Session Handoff

Current Objective

  • Goal: Work through open issues one at a time, all consolidated into a single PR (user explicitly asked for fewer PRs, not one per issue).
  • Current status: 6 issues done and pushed (#33, #36, #31, #39, plus #40/#41/#42/#48 from an earlier session), all on one branch/PR. Issue #38 (i18n) was scoped but paused before any code was written — waiting on the user's answer to a scope question.
  • Branch / commit: claude/fix-directory-symlink-pull-260713 @ 4eebebcPR #51 (open, all CI checks green as of last check)

Completed This Session

  • #31 - fix: surface a clear error when requestUrl() itself rejects with HTML content — some Obsidian versions eagerly JSON-parse inside requestUrl(), so a login/proxy HTML page rejected the whole call with a raw SyntaxError, bypassing the existing parseJson() HTML-detection wrapper. Added the same detection to safeRequest's outer catch.
  • #33 - fix: symlinked directories no longer break pull discovery — a directory symlink is a single git blob, not a real tree; local scanning recursed into it as if it were, causing bogus remote .gitignore 404s and a permanently-stuck "remote only" status. Also fixed createLocalSymlink's missing Windows symlinkSync type hint.
  • #36 - perf(refresh): use tree blob SHAs to avoid per-file content fetches — refresh now compares a locally-computed git blob SHA against each tree entry's SHA instead of one getFile network call per file; diff content is fetched on demand via a new getBlob(sha, path) per service. Symlink-aware hashing (real/follow/skip modes) per the issue's follow-up design.
  • #39 - feat: show new feature tips after update — new src/changelog.ts (hand-curated, separate from the auto-generated CHANGELOG.md) with a notable flag per entry, a WhatsNewModal, and a lastSeenVersion setting so the tip shows once per upgrade only.
  • Consolidated everything (this session's 4 issues + the prior session's #40/#41/#42/#48) onto one branch/PR (#51) per the user's explicit request to reduce PR count — closed/merged the now-redundant PRs #49/#50/#52/#53.
  • #38 (i18n) - paused, not started. Counted scope (~47 strings in settings.ts, ~24 in SyncStatusView.ts, 37 Notice() call sites across 4 files) and asked the user how deep to scope it; the question prompt was dismissed without an answer before they ran /firstsun-harness. No src/i18n/* files exist yet — don't assume a design, ask again first.

Verification Evidence

Check Command Result Notes
Lint npx eslint . 0 errors Repo-wide, no exceptions
Type check + compat npm run build Pass Includes typecheck-compat.mjs against Obsidian 1.11.0
Tests npx vitest run 302/302 passed 22 test files
Duplication npx jscpd --min-lines 5 --min-tokens 50 src 14 clones, all pre-existing Checked after every commit — SonarCloud's gate is 3% on new code, learned this the hard way earlier (PR #49 failed at 8.3%)
Manual (in Obsidian) Not done No Obsidian instance available in this environment

Files Changed (this session, cumulative across the 4 issues)

  • src/services/git-service-base.ts, git-service-interface.ts, github-service.ts, gitlab-service.ts, gitea-service.ts — tree-entry sha, getBlob(), HTML-error detection in safeRequest
  • src/logic/gitignore-manager.ts, src/ui/SyncStatusView.ts — symlink-directory recursion guard, SHA-based status refresh, lazy diff loading
  • src/utils/symlink.ts — Windows symlinkSync type hint
  • src/utils/git-blob-sha.ts, src/utils/version.ts (new) — SHA-1 blob hashing, numeric version compare
  • src/changelog.ts, src/ui/WhatsNewModal.ts (new) — what's-new modal + data
  • src/ui/components/DiffPanel.ts, FileListItem.ts — on-demand diff fetch
  • src/settings.ts, src/main.tslastSeenVersion field, update-check wiring
  • Corresponding test files under tests/ for all of the above (302 tests total)

Decisions Made

  • One PR, not one-per-issue: user said "不要那麼多pr merge" (don't want so many PRs). All further issue work goes directly onto claude/fix-directory-symlink-pull-260713 — do not create a new branch/PR for the next issue.
  • src/changelog.ts is hand-curated, separate from CHANGELOG.md: the auto-generated changelog (via semantic-release) isn't shipped in release assets and is too commit-log-granular for an end-user popup anyway.
  • Deduped two accidental code-duplication regressions mid-session (test mocks, getBlob bodies) before they could trip SonarCloud's new-code gate again.

Blockers / Risks

  • #38 (i18n) needs a scope answer from the user before any code is written. Options put to them: (a) build the i18n mechanism + fully migrate settings.ts only, Notices later; (b) fully migrate settings.ts and all 37 Notice call sites now; (c) build just the t()/detection/fallback mechanism with a couple of sample keys, defer actual string migration. Don't guess — the wrong choice means redoing a large diff.
  • PR #51 is now fairly large (6 issues). Consider flagging to the user that it may be worth reviewing/merging before more commits pile on.

Next Session Startup

  1. Read CLAUDE.md, feature_list.json, progress.md, then this file.
  2. Run ./init.sh before editing.
  3. Ask the user for #38's scope decision (see "Blockers / Risks") before touching any i18n code.
  4. All new commits go on claude/fix-directory-symlink-pull-260713 (PR #51) unless told otherwise.
  • Get the #38 scope decision, implement it, then move to #37 (Bitbucket provider) per the previously agreed order (39→38→37, all done).