Isolated settlement decision regression. Existing committed test, in-process decision function. No external access.

Revision 76d418599f; implementation injected from git show; cwd apps/server
Command: PROOF_VARIANT=red vp test run src/orchestration-v2/ThreadSettlementService.test.ts -t defers merge settlement --config /tmp/issue-25160-proof/settlement.config.ts --fsModuleCachePath /tmp/issue-25160-proof/cache-settlement-red --reporter=verbose
note: You are running `vp test` as a Vite+ built-in command. If you meant to run the test npm script, use `vpr test` instead.

 RUN  v5.0.5 /home/ubuntu/wt/issue-25160/apps/server

 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > isAutoSettlementCandidate > settles a thread whose only background work is a command left running
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > isAutoSettlementCandidate > never settles, or keeps snoozed, a thread whose guest is waiting on the owner
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > isAutoSettlementCandidate > keeps snoozed threads parked until a fresh failure or timer wake
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > keeps threads with a PR from inactivity settlement only when asked
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > settles an idle thread with an open persisted link only while retention is off
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > keeps an idle thread whose persisted link was never synced
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > uses the latest activity time when the inactivity window elapses
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > anchors an empty thread's inactivity at its creation time
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > restarts inactivity on a manual snooze wake
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > restarts inactivity on a timer snooze wake
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > settles on merge only after the user's last action and preserves the activity time
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > settles on merge after agent-started runs, but not after the user writes again
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > does not settle on pull requests that were already merged when linked
 × src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > defers merge settlement while the merged pull request is still watched 10ms
   → expected DateTime.Utc(2026-06-10T11:15:00.000Z) to be null
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > autoSettlementSettingsKey > distinguishes a project that inherits the threshold from one that disables it
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles a merged pull request stored only in the thread links
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles an idle thread with an open persisted link on the inactivity sweep
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles only the project opted in while environment settlement is disabled
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > reevaluates immediately after a pull request merge
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles a merged thread when its background work ends, during a slow full sweep
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles a stopped thread while another thread's lookup is slow
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles an unlinked branch thread its agent merged from a shell, past the cache
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles branch threads on a pull request merge without waiting for the next sweep
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > a merge does not settle threads linked to an unrelated pull request
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > keeps the terminals of a thread re-engaged before the event ran
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > runs the settle script in the thread's own worktree
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > skips the settle script for a thread re-engaged while its shells close
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > runs the settle script once when a settlement is re-emitted
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > retries the settle script on a re-emitted settlement after a failed start
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > isSnoozed > keeps a run requested and completed after snoozing parked until the timer

⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯

 FAIL  src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > defers merge settlement while the merged pull request is still watched
AssertionError: expected DateTime.Utc(2026-06-10T11:15:00.000Z) to be null

- Expected:
null

+ Received:
{
  "epochMilliseconds": 1781090100000,
}

 ❯ src/orchestration-v2/ThreadSettlementService.test.ts:479:68
    477|       autoSettleOnMerge: true,
    478|     };
    479|     expect(ThreadSettlementService.resolveAutoSettlementAt(input)).toB…
       |                                                                    ^
    480|     expect(
    481|       ThreadSettlementService.resolveAutoSettlementAt({

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯


 Test Files  1 failed (1)
      Tests  1 failed | 29 skipped (30)
   Start at  01:14:28
   Duration  12.46s (transform 73%, import 26%, setup 1%)

EXIT 1

Revision 223c460512; implementation injected from git show; cwd apps/server
Command: PROOF_VARIANT=green vp test run src/orchestration-v2/ThreadSettlementService.test.ts -t defers merge settlement --config /tmp/issue-25160-proof/settlement.config.ts --fsModuleCachePath /tmp/issue-25160-proof/cache-settlement-green --reporter=verbose
note: You are running `vp test` as a Vite+ built-in command. If you meant to run the test npm script, use `vpr test` instead.

 RUN  v5.0.5 /home/ubuntu/wt/issue-25160/apps/server

 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > isAutoSettlementCandidate > settles a thread whose only background work is a command left running
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > isAutoSettlementCandidate > never settles, or keeps snoozed, a thread whose guest is waiting on the owner
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > isAutoSettlementCandidate > keeps snoozed threads parked until a fresh failure or timer wake
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > keeps threads with a PR from inactivity settlement only when asked
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > settles an idle thread with an open persisted link only while retention is off
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > keeps an idle thread whose persisted link was never synced
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > uses the latest activity time when the inactivity window elapses
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > anchors an empty thread's inactivity at its creation time
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > restarts inactivity on a manual snooze wake
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > restarts inactivity on a timer snooze wake
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > settles on merge only after the user's last action and preserves the activity time
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > settles on merge after agent-started runs, but not after the user writes again
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > does not settle on pull requests that were already merged when linked
 ✓ src/orchestration-v2/ThreadSettlementService.test.ts > resolveAutoSettlementAt > defers merge settlement while the merged pull request is still watched 6ms
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > autoSettlementSettingsKey > distinguishes a project that inherits the threshold from one that disables it
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles a merged pull request stored only in the thread links
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles an idle thread with an open persisted link on the inactivity sweep
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles only the project opted in while environment settlement is disabled
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > reevaluates immediately after a pull request merge
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles a merged thread when its background work ends, during a slow full sweep
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles a stopped thread while another thread's lookup is slow
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles an unlinked branch thread its agent merged from a shell, past the cache
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > settles branch threads on a pull request merge without waiting for the next sweep
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 worker > a merge does not settle threads linked to an unrelated pull request
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > keeps the terminals of a thread re-engaged before the event ran
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > runs the settle script in the thread's own worktree
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > skips the settle script for a thread re-engaged while its shells close
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > runs the settle script once when a settlement is re-emitted
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > ThreadSettlementServiceV2 terminals > retries the settle script on a re-emitted settlement after a failed start
 ↓ src/orchestration-v2/ThreadSettlementService.test.ts > isSnoozed > keeps a run requested and completed after snoozing parked until the timer

 Test Files  1 passed (1)
      Tests  1 passed | 29 skipped (30)
   Start at  01:14:42
   Duration  11.74s (transform 72%, import 27%, setup 1%)

EXIT 0
