Skip to content

Follow-up: deferred review findings from PR #622 #627

Description

@philcunliffe

Neutral triage on PR #622 (head 4fd8b70b799e463e7ff649172168685a82b481c9, the reconciler-refused-marker change set, LLP 0184/0186/0187, Fixes #601) confirmed round 2's fix (rearmRefusedActionMarker) is complete and found no production-risk blockers. Two items round 2 recorded as deliberate deferrals are worth tracking so they do not silently rot:

1. reverse() returning refused falls into the generic failure branch

src/core/config/action_reconciler.js:340-356. ActionOutcome is one type shared by perform() and reverse(), so widening it for the terminal refused state also made refused expressible as a reverse() return value, even though no in-tree handler's reverse() produces it today (verified: action_attach.js's is the only reverse() in the tree, and it only ever returns done or failed). If a future reverse() ever does return refused, the reverse gap's else branch treats it exactly like failed: keep the marker, retry forever. That is documented as the deliberately safe half of a genuine open design question (LLP 0186 Explicitly out of scope, referencing LLP 0138#refusal-is-not-failure vs LLP 0212) rather than an oversight, and today it is dead code. Follow-up: when a real reverse-refusal need shows up, settle terminal-undo semantics explicitly (a new LLP) rather than let the fallback keep standing in by accident.

2. hyp leave's reverse gate was not migrated to the refused status

src/core/commands/central.js:435. The reconciler's own reverse gap (action_reconciler.js:315-319) and rearmRefusedActionMarker both special-case refused explicitly. hyp leave's parallel assetless-marker drop only checks marker.status === 'failed':

if (!marker || (marker.status === 'failed' && installedAssets.length === 0)) {

An assetless refused marker does not match this condition, so it falls through to the full detachClientViaCore path instead of being dropped directly the way the reconciler's reverse gap drops it. Verified this is safe today: detachClientFromDisk (src/core/config/client_detach_disk.js) no-ops ({ changed: false }) when there is nothing on disk to reverse (a refusal never wrote the client's settings), and the marker still gets cleared afterward inside detachClientViaCore. So this is not data loss, just an inconsistency between the three marker-reading gates (reconciler reverse gap, hyp detach, hyp leave) that costs an unnecessary disk probe and diverges from the pattern the other two gates now follow. Follow-up: add the || marker.status === 'refused' branch to central.js:435 for consistency, and to avoid future drift if a fourth marker status is ever added and only two of the three gates get updated for it.

Neither item blocks PR #622; both are pre-existing, deliberate deferrals from round 2's review, recorded here so they don't get lost.

Backlink: #622

Metadata

Metadata

Assignees

No one assigned

    Labels

    neutral:fixDelegate this issue to neutral for an autonomous fix attempt (reproduce -> fix -> PR)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions