Files
pulse/docs/release-control
rcourtman a9f23501eb Remove test-only Patrol autonomy save helpers (#2740)
Stacked on #2695 (branch contains its head 32fad38aa4). Once #2695
merges, this PR's diff is the single commit 776c2774ba.

## What

`resolvePatrolAutonomyLevelForSave` and
`resolvePatrolAutonomySettingsForSave` in
`features/patrol/usePatrolIntelligenceState.ts` had no production
caller. Only their own unit tests imported them. Patrol mode saves go
through `handleAutonomyChange` and `acknowledgeAndActivateAutopilot`,
whose payload type `PatrolAutonomyUpdate` has no `full_mode_unlocked`
field, and both reconcile from `GET /api/ai/patrol/autonomy`. This PR
deletes both helpers and their tests.

Contract prose in patrol-intelligence, api-contracts,
frontend-primitives and ai-runtime described the helpers' model rather
than the live path: the browser clearing stale full-mode unlock state
before a monitor-only save, sending `full_mode_unlocked:false` when
locked, and sending `full_mode_unlocked:true` for Autopilot. The API
does that work. `HandleUpdatePatrolAutonomyMonitorOnly` and the paid
handler's `SaveAutonomySettings` adapter clear the unlock and Autopilot
activation on every save below Autopilot, and `GatePatrolAutonomyUpdate`
derives the compatibility flag from a recorded acknowledgement. The
prose now says what the header, the state owner and the API each do.
Three neighbouring api-contracts sentences about the same save were also
corrected:
- a `full` request without a current acknowledgement is refused by the
gate before any licence check;
- the "Patrol mode dialog" (removed in 27ba85ddc6) is now the header's
`Mode and automation` disclosure, with the same wording as #2691;
- the lock is checked "when a save starts", not "never submits", because
the Autopilot flow checks it only at entry.

The deleted helper tests are replaced by tests of the live locked path.
A page test loads stale paid state (Safe auto-fix plus the compatibility
unlock) under a runtime lock. It checks that Watch only is presented,
that the paid choices are disabled and save nothing, and that Watch only
sends exactly `autonomy_level`, `investigation_budget` and
`investigation_timeout_sec`. A source pin keeps the state owner's own
lock guards.

## Verification

- Production build: parent and this change produce byte-identical dists
(187 files), because Rollup had already dropped both helpers.
- Browser pass on pulse-dev, before and after, one DEMO_MODE stack at a
time, 1440x900 and 390x844. Covered paid saves (Ask first, Watch only,
Autopilot through the acknowledgement dialog) and the runtime lock with
and without the demo presentation override. 6 sessions and 80 recorded
fields, with 0 differences between before and after. No PUT ever carried
`full_mode_unlocked`. Receipt
`frontend-modern/browser-verification/994121d9684bd9f0.json`.
- `tsc --noEmit` and the Patrol hook, page, header, workspace,
commercial-boundary and resource-boundary suites pass (84 tests).
- Negative controls, each failing the intended test:
  - header showing the stale paid mode while locked;
  - payload carrying `full_mode_unlocked`;
  - hook lock guard removed;
  - paid choices enabled while locked.
2026-10-08 03:41:42 +01:00
..