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
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()returningrefusedfalls into the generic failure branchsrc/core/config/action_reconciler.js:340-356.ActionOutcomeis one type shared byperform()andreverse(), so widening it for the terminalrefusedstate also maderefusedexpressible as areverse()return value, even though no in-tree handler'sreverse()produces it today (verified:action_attach.js's is the onlyreverse()in the tree, and it only ever returnsdoneorfailed). If a futurereverse()ever does returnrefused, the reverse gap'selsebranch treats it exactly likefailed: 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 therefusedstatussrc/core/commands/central.js:435. The reconciler's own reverse gap (action_reconciler.js:315-319) andrearmRefusedActionMarkerboth special-caserefusedexplicitly.hyp leave's parallel assetless-marker drop only checksmarker.status === 'failed':An assetless
refusedmarker does not match this condition, so it falls through to the fulldetachClientViaCorepath 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 insidedetachClientViaCore. 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 tocentral.js:435for 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