mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-27 17:58:07 +00:00
lint(desktop): exempt benign ref writes flagged by the new atom-mirror guard
The guard matches any `.current` write inside a `useEffect`, so it also flags refs that are not mirroring a reactive value. Seven such sites landed on main after the rule was written: - wiring.tsx: one-shot request-seen sentinel - billing/plans-view.tsx: previous-confirming tracker for focus return - config-settings.tsx: autosave bookkeeping - gateway-settings.tsx: monotonic request-sequence counters - toolset-config-panel.tsx: mount flag + one-shot provider-choice claim - voice-provider-fields.tsx: one-shot config seed flag None mirrors an atom/prop/state value, so none can produce the one-render-lag stale read the rule exists to prevent. Each gets an eslint-disable with the specific reason rather than widening the rule, which would reopen the hole for real mirrors. Verified the guard still catches the real antipattern: a probe file mirroring `useStore($activeSessionId)` into a ref via useEffect is reported. eslint over apps/desktop/src is 0 errors, and the 24 remaining warnings match the pre-change baseline exactly.
This commit is contained in:
parent
e026fd61d8
commit
751c15f9eb
6 changed files with 7 additions and 0 deletions
|
|
@ -142,6 +142,7 @@ export function ContribWiring({ children }: { children: ReactNode }) {
|
|||
const billingSettingsRequest = useStore($billingSettingsRequest)
|
||||
const currentCwd = useStore($currentCwd)
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax -- one-shot request-seen sentinel, not an atom mirror
|
||||
useEffect(() => {
|
||||
if (billingSettingsRequest === billingSettingsSeenRef.current) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ function PlanCard({ flow, tier }: { flow: DowngradeFlow; tier: BillingPlanTierVi
|
|||
|
||||
// When the confirm panel closes (cancel / scheduled), return focus to this tile
|
||||
// so keyboard focus is never left detached on the removed panel.
|
||||
// eslint-disable-next-line no-restricted-syntax -- tracks previous confirming state for focus return, not an atom mirror
|
||||
useEffect(() => {
|
||||
if (wasConfirming.current && !confirming) {
|
||||
cardRef.current?.focus()
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ export function ConfigSettings({
|
|||
return () => void (cancelled = true)
|
||||
}, [])
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax -- autosave bookkeeping refs, not an atom mirror
|
||||
useEffect(() => {
|
||||
if (!config || saveVersion === 0) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -404,6 +404,7 @@ export function GatewaySettings({ embedded = false }: { embedded?: boolean } = {
|
|||
return () => void (cancelled = true)
|
||||
}, [state.mode])
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax -- monotonic request-sequence counters, not an atom mirror
|
||||
useEffect(() => {
|
||||
contextSeq.current += 1
|
||||
sshTestSeq.current += 1
|
||||
|
|
|
|||
|
|
@ -497,6 +497,7 @@ export function ToolsetConfigPanel({ toolset, onConfiguredChange }: ToolsetConfi
|
|||
// Guard the Nous Portal sign-in poll loop against unmount/state updates.
|
||||
const mountedRef = useRef(true)
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax -- mount flag guarding an async poll loop, not an atom mirror
|
||||
useEffect(() => {
|
||||
mountedRef.current = true
|
||||
|
||||
|
|
@ -538,6 +539,7 @@ export function ToolsetConfigPanel({ toolset, onConfiguredChange }: ToolsetConfi
|
|||
// first fully-configured provider, else the first provider. Without this the
|
||||
// panel highlighted the first keyless provider (e.g. Nous Portal) even when
|
||||
// the user had already selected another (e.g. DuckDuckGo).
|
||||
// eslint-disable-next-line no-restricted-syntax -- one-shot provider-choice claim flag, not an atom mirror
|
||||
useEffect(() => {
|
||||
if (providerChoiceClaimedRef.current || activeProvider || providers.length === 0) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ export function VoiceProviderFields({ section, providerKey }: { section: 'tts' |
|
|||
const [config, setConfig] = useState<HermesConfigRecord | null>(null)
|
||||
const seeded = useRef(false)
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax -- one-shot config seed flag, not an atom mirror
|
||||
useEffect(() => {
|
||||
if (loadedConfig && !seeded.current) {
|
||||
seeded.current = true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue