Repository navigation
[Feature]: Prevent pinned threads from auto-settling #11711
Description
Activity
Triage
Sidebar pin (
pinnedAt) is an explicit keep-active signal, but the server still auto-settles pinned threads (inactivity and merged/closed PR) andthread.auto-settleemits a companionthread.unpinned, dropping the pin. Current docs say pinning does not prevent automatic settlement.This is real and matches
main. It is an enhancement (documented, intentional today), not a defect.Code
isAutoSettlementCandidateinapps/server/src/orchestration/ThreadSettlementPolicy.tsnever checkspinnedAt, so pinned threads are swept for both inactivity and PR settlement. The reactor filters on that helper before PR lookups.decider.tsthread.auto-settleguardssettledOverrideonly. The shared settle path always unpins.- The policy test named “blocks pins, …” only covers
settledOverride: 'active'(transient keep-active), not sidebarpinnedAt. - Web/mobile already bucket
settledOverride === "settled"before pin. If the server never auto-settles a pinned thread, it stays in Pinned with no client change. Manual settle still unpins and lands in Settled.
settledOverride: 'active'and sidebarpinnedAtare different primitives. Activity clears the former; the latter is durable until unpin or settle.Related
- Companion PR (same author,
Fixes #11711): feat(settings): pinned threads stay active unless auto-settle pinned threads is on #11712 — do not open another. - [Feature]: Durable per-thread "never settle" pin — the existing "active" override is cleared by activity, so no thread can be kept permanently active #5575 (converted to [Feature]: Durable per-thread "never settle" pin — the existing "active" override is cleared by activity, so no thread can be kept permanently active #6898) asked for a dedicated durable never-settle. Not a duplicate; this proposal reuses the existing sidebar pin.
- fix(clients): move settled pinned threads into the settled section #7969 moved auto-settled pinned threads into Settled on clients. This reverses auto-settle for pinned threads only; manual settle still unpins.
Next step
Review/merge #11712. Policy + decider + reactor tests and docs match the acceptance list. Unpinning re-arms auto-settle by clearing
pinnedAt(no extra work). Pinning a settled thread already un-settles it, so treating pin as keep-active is consistent with pin-as-promotion.Not a duplicate of #5575. No second implementation PR needed.
- addedenhancementRequested improvement or new capability.Requested improvement or new capability.acceptedfeature request acceptedfeature request acceptedvia-triageFiled through npx t3 triageFiled through npx t3 triage
on Sep 14, 2026 - added a commit that references this issue
on Sep 14, 2026 - added 2 commits that reference this issue
on Sep 17, 2026
Problem
A sidebar pin (
pinnedAt) is an explicit keep-active signal, but the server currently auto-settles pinned threads anyway:isAutoSettlementCandidateinapps/server/src/orchestration/ThreadSettlementPolicy.tsnever checkspinnedAt, so pinned threads are swept for both inactivity and merged/closed-PR settlement.decider.tsthread.auto-settlehas no pinned guard — it even emits a companionthread.unpinnedevent, silently dropping the user's pin.docs/user/thread-sidebar.md) state: "Pinning does not prevent automatic settlement."The existing
ThreadSettlementPolicy.test.tscase is even named "blocks pins, ..." but only coverssettledOverride: 'active'(the transient keep-active override), not the sidebar pin.Related:
settledOverridevs sidebarpinnedAt)Proposal
isAutoSettlementCandidatereturns false whenpinnedAt != null(covers inactivity + PR paths, skips PR lookups).thread.auto-settledecider rejects whenpinnedAt != null(stale-sweep race: pin landed after the snapshot), whilethread.settle(manual) still succeeds and clears the pin.Acceptance