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:
- clearing assume-unchanged one path at a time for IDs from deobfuscation state;
- setting assume-unchanged one path at a time for every current manifest ID;
- 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.
Problem
Full status-suppression rebuilds launch
git update-indexonce per note path, andnotes pullcan 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:notes0.8.19 on 2026-07-17.Source findings
lib/suppress.shcurrently rebuilds suppression by:A synthetic 437-file Git fixture running the same per-path
update-indexshape 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 callsrebuild_status_suppressionin full mode..mise/tasks/pullrunsgit pulland 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-refreshrepaired 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
notes pulldoes not unconditionally repeat successful hook work.Acceptance
notes pulldoes not duplicate a successful post-merge suppression rebuild.Current workaround
Do not run
notes suppress-refreshroutinely. Trust installed hooks, inspect their warnings, and use fastgit status --short --branchafter Git operations. If opaque note IDs appear deleted, record the failure and then run suppression refresh as an explicit repair.