Skip to content

sync --skip-failed should emit structured summary by error code and persist skip manifest #500

@garrytan

Description

@garrytan

Problem

When gbrain sync --skip-failed acknowledges failures and advances the bookmark, it only reports a count (e.g., "Acknowledged 2688 failure(s)"). It does not break down failures by error code or list which files were affected.

This makes it easy to silently skip thousands of files without understanding why they failed. In practice, 2,685 files with SLUG_MISMATCH errors were acknowledged and skipped — the bookmark advanced past them, so they were never retried. The operator had to manually investigate to discover the root cause.

Current behavior

Sync blocked: 2688 file(s) failed to parse. Fix the YAML frontmatter...
# user runs: gbrain sync --skip-failed
Acknowledged 2688 failure(s) and advancing past them.

No breakdown by error code. No manifest of skipped files persisted for later backfill.

Proposed behavior

  1. --skip-failed should emit a summary grouped by error code:

    Acknowledged 2688 failure(s):
      SLUG_MISMATCH: 2685
      YAML_PARSE: 3
    Advancing bookmark past them.
    
  2. Persist a structured skip manifest (e.g., sync-skipped-<commit>.jsonl) alongside sync-failures.jsonl so operators can backfill later:

    {"path":"originals/posterous/garry/2008-03-20-my-friend-mike.md","code":"SLUG_MISMATCH","acknowledged_at":"2026-04-28T14:30:00Z"}
  3. gbrain doctor should surface unresolved skip manifests as a warning, e.g.:

    [WARN] sync_skipped: 2688 files skipped via --skip-failed (2685 SLUG_MISMATCH, 3 YAML_PARSE). Run: gbrain sync --retry-skipped
    
  4. Add --retry-skipped flag that re-attempts files from the skip manifest without requiring a full re-sync.

Context

  • gbrain frontmatter audit already catches these issues — but only if you think to run it
  • The sync's per-file error handling is good (captures errors, gates bookmark advancement)
  • The gap is in the --skip-failed escape hatch: it discards the error detail too aggressively
  • recordSyncFailures() writes to sync-failures.jsonl but acknowledgeSyncFailures() just clears the file

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions