Skip to content

Batch suppression rebuilds and avoid duplicate post-pull repair #153

Description

@c0da-ricon

Problem

Full status-suppression rebuilds launch git update-index once per note path, and notes pull can repeat reconciliation already performed by the post-merge hook. This makes normal merge/repair paths disproportionately expensive on larger note corpora.

Observed while investigating Fold workflow latency with shiv:notes 0.8.19 on 2026-07-17.

Source findings

lib/suppress.sh currently rebuilds suppression by:

  1. clearing assume-unchanged one path at a time for IDs from deobfuscation state;
  2. setting assume-unchanged one path at a time for every current manifest ID;
  3. rebuilding the readable-name exclude block.

A synthetic 437-file Git fixture running the same per-path update-index shape exceeded a 30s hard timeout before completing the serial clear/set cycle. Git supports batched path updates, so hundreds of subprocesses should not be necessary.

The installed post-merge hook runs full notes deobfuscate, which calls rebuild_status_suppression in full mode. .mise/tasks/pull runs git pull and then, when the checkout was deobfuscated, performs its own stale reconciliation and full suppression rebuild after Git returns. A successful pull that invokes the hook can therefore pay for broad reconciliation twice.

Incident context

A recent Fold merge left one tracked opaque note path appearing deleted until notes suppress-refresh repaired local state. The current post-merge hook was installed before the merge and is expected to rebuild suppression automatically. No hook log survives to show whether it failed, was interrupted, or encountered partial dirty-readable state, so the exact incident remains unresolved.

Related lifecycle umbrella: #129.

Desired direction

  • Batch assume-unchanged updates safely instead of launching Git once per path.
  • Give post-merge reconciliation one clear owner so notes pull does not unconditionally repeat successful hook work.
  • Preserve fail-closed dirty-readable and stale-note handling.
  • Make hook failure evidence easier to retain before manual repair.

Acceptance

  • Full suppression rebuild uses bounded/batched Git invocations and scales reasonably to hundreds or thousands of notes.
  • Post-merge, post-checkout, and post-commit behavior remains correct for clean, dirty-readable, renamed, deleted, and newly added notes.
  • notes pull does not duplicate a successful post-merge suppression rebuild.
  • A focused large-corpus performance test or budget protects the interactive path.
  • Failure output identifies whether deobfuscation, stale reconciliation, exclude rebuilding, or index suppression failed.

Current workaround

Do not run notes suppress-refresh routinely. Trust installed hooks, inspect their warnings, and use fast git status --short --branch after Git operations. If opaque note IDs appear deleted, record the failure and then run suppression refresh as an explicit repair.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions