Pitch
Backlog item #9. Sometimes a scratch matters more than its TTL implies, but it doesn't deserve the working tree yet (sp promote). Today the only way to keep it is an absurd --ttl 9999d. Add a first-class pin so a scratch is exempt from sp reap without lying about its lifespan.
Behavior
sp pin <id> — mark a scratch as pinned. Pinned scratches are never moved to the morgue by sp reap, regardless of expiry.
sp unpin <id> — clear the pin; normal TTL rules resume.
sp ls shows a pin marker (e.g. 📌 in TTY, PIN in plain/--json) and pinned scratches sort/display as such.
sp reap (and --dry-run) skips pinned scratches and reports how many were skipped for being pinned.
- Pin state persists in the index (
Scratch.Pinned bool, omitempty).
Acceptance criteria
Pitch
Backlog item #9. Sometimes a scratch matters more than its TTL implies, but it doesn't deserve the working tree yet (
sp promote). Today the only way to keep it is an absurd--ttl 9999d. Add a first-class pin so a scratch is exempt fromsp reapwithout lying about its lifespan.Behavior
sp pin <id>— mark a scratch as pinned. Pinned scratches are never moved to the morgue bysp reap, regardless of expiry.sp unpin <id>— clear the pin; normal TTL rules resume.sp lsshows a pin marker (e.g.📌in TTY,PINin plain/--json) and pinned scratches sort/display as such.sp reap(and--dry-run) skips pinned scratches and reports how many were skipped for being pinned.Scratch.Pinned bool, omitempty).Acceptance criteria
Scratchmodel gains aPinnedfield (JSONomitempty), backward-compatible with existing indexes.sp pin <id>/sp unpin <id>commands registered on root, with tombstone-flavored confirmations.sp reapandsp reap --dry-runexclude pinned scratches and note the skip count.sp ls(table, plain, and--json) surfaces pin state.