Follow-up to the push-all batching work: batch-deleting remote-only
files via the sync status panel's checkbox multi-select was still N
separate commits (SyncStatusView.performRemoteDeletion looped
gitService.deleteFile once per file).
- Add optional GitServiceInterface.deleteBatch, mirroring pushBatch.
GitHub/Gitea implement it via the git blob->tree->commit->ref Data
API, reusing resolveGitHubStyleBaseTree/resolveBaseTree and
commitGitHubStyleTree (widened its tree-item sha type to
string | null -- a null sha removes that path from the resulting
tree, GitHub's way of expressing a delete at the tree level).
GitLab implements it via the same Commits API endpoint pushBatch
already uses, with action: 'delete' entries.
- SyncStatusView.performRemoteDeletion now calls deleteBatch once per
chunk (MAX_BATCH_PUSH_SIZE, reused from the push work) when the
provider supports it; a failed chunk marks every path in it as
failed rather than dropping results silently. The original per-file
loop is preserved verbatim as performRemoteDeletionSequential, the
fallback for providers without deleteBatch.
Local deletion is unaffected -- it's a local vault operation, not a
git commit.
Evidence: npx eslint . -> 0 errors; npm run build -> clean;
npx vitest run -> 339/339 passed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Push-all was up to 3N sequential HTTP calls and N separate commits for
N files (getFile check -> pushFile PUT -> optional extra getFile),
plus two redundant full remote-tree fetches per run (one discarded in
main.ts, one inside GitignoreManager).
- Add optional GitServiceInterface.pushBatch. GitHub/Gitea implement it
via the git blob->tree->commit->ref Data API, generalizing
pushSymlink's existing pattern into shared
resolveGitHubStyleBaseTree/commitGitHubStyleTree helpers in
git-service-base.ts. GitLab implements it via its native multi-file
Commits API (actions array), with a follow-up listFilesDetailed call
to recover each file's new blob sha since that endpoint doesn't
return them. Symlinks stay on the existing per-file pushSymlink path.
- sync-manager.ts's push-all flow now classifies each file by comparing
a locally-computed git blob sha (utils/git-blob-sha.ts, already used
by the feat-006 status refresh) against a pre-fetched remote tree's
per-entry sha, eliminating the per-file getFile call for the common
case. Queued files are committed in one grouped pushBatch call,
chunked at MAX_BATCH_PUSH_SIZE=200; a failed chunk marks every file
in it as failed rather than dropping results silently. Providers
without pushBatch fall back to the original sequential path.
- main.ts fetches the remote tree once per push/pull-all run and
threads it into both GitignoreManager.loadGitignores(tree) and
SyncManager.pushAllFiles(files, onProgress, tree), replacing the
previously-discarded listFiles() call and gitignore-manager's
separate fetch with one shared call.
Rename detection and the pull-all path are unchanged (out of scope).
Evidence: npx eslint . -> 0 errors; npm run build -> clean;
npx vitest run -> 330/330 passed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Adds the missing harness subsystems so future agent sessions can start,
stay in scope, verify work, and resume reliably:
- feature_list.json: local mirror of active/next-up work (GitHub Issues
on Project #6 remains the source of truth for the full backlog)
- progress.md / session-handoff.md / archive/2026-07.md: session state,
restart point, and monthly archive of finished work
- init.sh: install + lint + test + build verification entrypoint
- AGENTS.md: added Startup Workflow, Definition of Done, Stay in Scope,
and End of Session sections (existing agent-tier content kept as-is)
- CLAUDE.md: added a short Agent Workflow section routing to the above
Validated with the firstsun-harness audit script: 100/100 across all
five subsystems (instructions, state, verification, scope, lifecycle).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYCTyZw7gUmJ7oh1VTmAqh