Repository navigation
docs: document recover --confirm-scope-gone for a refused resume - #1880
Conversation
The operations guide still told an operator whose pod was OOM-killed to relaunch with --resume-from, and described `hyperloom recover` only as a breakdown rebuild. A resume in a new pod is refused until the lost pod's owner scope is confirmed gone, so the runbook led straight into the refusal with no way out. Scenario A now covers the refused resume: what the refusal prints, when to run `hyperloom recover --confirm-scope-gone OWNER_SCOPE --confirmation-reason TEXT` instead of --confirm-stopped, what it changes, and every case in which it refuses. The crash-recovery row, the recover exit codes, operator-scripts.md, and the recover help text (top-level summary and subcommand description) say the same. Docs and help text only; no behaviour change. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: chaojhou <chaojhou@amd.com>
… is best effort --confirm-scope-gone refuses only a ledger that predates the owner_scope column. Migrated legacy leases carry an empty scope, which the option skips: it reports nothing to confirm and exits 0. Say so, and that the pod_history.jsonl append can fail with only a warning. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: chaojhou <chaojhou@amd.com>
Code metrics gate: PASSEDJudged: the 9 files this change touches. Files it does not touch never fail it; anything found there is listed under Outside this change for information.
Module length warning: over 800 lines, within the 1200-line failure limit (not failing): 1
Already over at the base (backlog, not this change's): 1
96 findings in files this change does not touchOutside this change (informational): 96
...and 71 more; the job log lists every row.
Thresholds and sources: |
The code-metrics gate fails any growth of _build_parser. Move the recover subcommand's help and description into constants beside the other recover options so the parser function keeps its length. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: chaojhou <chaojhou@amd.com>
Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: chaojhou <chaojhou@amd.com>
chaojhou
left a comment
There was a problem hiding this comment.
PR #1880 -- docs: document recover --confirm-scope-gone for a refused resume
What it does: Since #1859, a --resume-from in a new pod is refused (exit 2) until the lost pod's owner scope is confirmed gone with hyperloom recover --confirm-scope-gone, yet the disaster-recovery runbook ended at that refusal and the docs and help described recover only as a breakdown rebuild. This PR adds the step to operations.md Scenario A (what the refusal prints, the command, what the confirmation changes, when it refuses, and when --confirm-stopped applies instead), updates the crash-recovery lifecycle row, the recover exit codes and operator-scripts.md, and extends the top-level and recover subcommand help, keeping the subcommand help and description as constants in cli/recover.py so _build_parser does not grow.
Blocking issues: 1
- [X3] The optimization-loop doc still says
recoveronly reconstructs artifacts [verified]
Problem: this PR corrects therecovercontract in the Scenario A summary ("recover= rebuild the breakdown artifact, or, with--confirm-scope-gone/--confirm-stopped, record a cleanup confirmation that lets a refused resume proceed"), inoperator-scripts.md:190-196and in the help, but leaves its duplicate atdocs/conceptual/optimization-loop.md:498-499-- "recoveronly reconstructs artifacts offline" -- unchanged. At this head,recoverwith either confirmation option cancels the unfinished tasks and releases their execution and GPU leases instead of rebuilding anything (cli/recover.py:146-150->session/resume_guard.py:380-405). docs/reference/operations.md:330
Impact: after merge the docs disagree about whatrecoverdoes. A reader of the optimization-loop page, whichAGENTS.mdlists as the doc for the loop, is toldrecovercannot help with the refused resume this PR documents.
Action: rewordoptimization-loop.md:498-499to sayrecoverreconstructs artifacts offline or, with--confirm-scope-gone/--confirm-stopped, records the cleanup confirmation a refused resume asks for, and link Scenario A.
SKIPPED: V4 -- PARTIAL overlap for #1032, #1154, #1276, #1675, #1869 (each cut at its first 100 files), overlap there unchecked
Checked: every operational claim in the added docs and help against the head code -- cli/recover.py (_run_cleanup_confirmation, _run_recover_session), session/resume_guard.py (ensure_resume_safe, _other_scopes, _label, confirm_scope_gone, _confirm_scope_gone_in_transaction, _confirm_task_stopped_in_transaction, _task_leases, _holder_runs_here, _in_locked_ledger), session/lock.py (SessionLock.acquire), common/owner_scope.py, cli/__init__.py:2060-2070 and main, cli.py, parser.py:152-163 and :1166-1183; the four places the #1874 card named (operations.md:144, :214-215, Scenario A, the recover subcommand help), now all correct; commit 3 as a pure move of the commit-1 help strings; tree-wide sweeps at head for RECOVER_HELP / RECOVER_DESCRIPTION, the replaced help literals, the three confirmation flags and every recover mention in docs/**, **/SKILL.md and prompts; #1874's docs commit against this head | Ran: git show / git grep sweeps at base and head; git diff of the #1874 and #1880 docs commits; gh run list --commit 1b03a28a (latest run per workflow: 10 success, 2 label-gated E2E skipped); gh pr view 1880 --json mergeable (MERGEABLE); claims traced statically (no direct call or c901.py run on this host; the diff adds no def or branch and the code-metrics job reports cyclomatic +0) | Base: d755931 | Head: 1b03a28
…oc and SKILL.md The optimization-loop page and the inference-optimizer SKILL.md still described recover as artifact reconstruction only. With --confirm-scope-gone / --confirm-stopped it records the cleanup confirmation a refused resume asks for; say so and point at Scenario A. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: chaojhou <chaojhou@amd.com>
|
Thanks for the review. Addressed in 9f4ffa4. 1. [X3] optimization-loop.md still says
CI at 9f4ffa4: every lane passes (label-gated E2E skipped). |
chaojhou
left a comment
There was a problem hiding this comment.
PR #1880 -- docs: document recover --confirm-scope-gone for a refused resume
What it does: A --resume-from in a new pod is refused (exit 2) until the lost pod's ownership is confirmed. This PR documents that step. In operations.md Scenario A it covers the refusal output, hyperloom recover --confirm-scope-gone, what the confirmation changes, when it refuses, and when --confirm-stopped applies. It also updates the lifecycle row, the recover exit codes, operator-scripts.md, optimization-loop.md, SKILL.md, and the top-level and recover help. The help strings are kept as constants in cli/recover.py. The previous card's item (optimization-loop.md still saying recover only reconstructs artifacts) is fixed at this head, along with the same stale line in SKILL.md.
Blocking issues: 1
- [free:confirm-stopped-scope] The runbook says scope-less ownership comes only from earlier versions, but the current code creates running tasks with no lease [verified]
Problem: Scenario A says to confirm "once for the whole scope, then relaunch" (docs/reference/operations.md:279). It limits--confirm-stoppedto ownership recorded without an owner scope "by earlier versions" (:313). At head, CLOSE-phase tasks are created withrequires_lanes=[](phases/close.py:594, :923), and the dispatcher takes a lease only whentask.requires_lanesis non-empty (loop/dispatcher.py:847), yet the task is still moved torunning. A pod lost during CLOSE therefore leaves a running task that_scan_tasksblocks with holderunknownand no scope.--confirm-scope-gonecannot reach it, because_confirm_scope_gone_in_transactionselects targets only from leases under the named scope.--confirm-stoppeddoes work for it. docs/reference/operations.md:313
Impact: an operator whose pod was lost during CLOSE follows the runbook: confirms the scope (exit 0), relaunches, and is refused again. The runbook then tells them the remaining tool is only for records from earlier versions.
Action: describe--confirm-stoppedby what the operator sees rather than by version: use it for each blocked task the refusal lists without an owner scope. Drop "by earlier versions". Add one sentence to Scenario A: if the relaunch is still refused after the scope confirmation for tasks that name no scope, confirm each with--confirm-stopped.
SKIPPED: V4 -- open PRs #1032, #1154, #1276, #1675, #1869 were compared on their first 100 files only
Checked: every added sentence against cli/recover.py (_run_cleanup_confirmation, _run_recover_session, RECOVER_HELP, RECOVER_DESCRIPTION), session/resume_guard.py (ensure_resume_safe message, _scan_tasks, _other_scopes, _label, _confirm_scope_gone_in_transaction, _confirm_task_stopped_in_transaction, _task_leases, _in_locked_ledger), session/lock.py, common/owner_scope.py, loop/dispatcher.py, phases/close.py, sub_agent_runner.py, resource_lock.py, cli/init.py exit handling; tree-wide sweep of docs/**, **/SKILL.md and prompts for recover mentions | Ran: git diff 1b03a28a8 9f4ffa47e; git show/git grep at base and head; two independent refutation passes per finding; confirm_scope_gone traced statically (it needs fcntl, unavailable on this host) | Base: d755931 | Head: 9f4ffa4
…rsion CLOSE-phase tasks are created with requires_lanes=[], so the dispatcher takes no lease for them, yet they still run. A pod lost during CLOSE leaves such a task running with no owner scope: --confirm-scope-gone cannot reach it and the relaunch is refused again. The runbook, the recover help, SKILL.md and the refusal message itself said empty-scope ownership came only from earlier versions. The refusal names owner scopes on a separate line, not per task, so the guidance says to let --confirm-stopped check: it refuses, changing nothing, a task recorded under an owner scope. The refusal message gives the scope step first and then the scope-less one, Scenario A gains the follow-up step, and a test pins the CLOSE shape: scope confirmation, still refused for the lane-less task, --confirm-stopped, resume allowed. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: chaojhou <chaojhou@amd.com>
|
Thanks for the review. Addressed in cbca632. 1. [free:confirm-stopped-scope] the runbook says scope-less ownership comes only from earlier versions -- fixed.
Ran: the recover/resume test files (282 passed), CI at cbca632: every lane passes (33 pass; label-gated E2E and the other conditional lanes skipped). |
chaojhou
left a comment
There was a problem hiding this comment.
PR #1880 -- docs: document recover --confirm-scope-gone for a refused resume
What it does: A --resume-from in a new pod is refused (exit 2) until the lost pod's ownership is confirmed. This PR documents that step in operations.md Scenario A, the lifecycle row, the recover exit codes, operator-scripts.md, optimization-loop.md, SKILL.md and the recover help, and -- since cbca632 -- rewrites the refusal message ensure_resume_safe prints so it gives the scope step first and then --confirm-stopped for a listed task that names no owner scope (such as a lane-less CLOSE-phase step), with a test that runs that runbook path. The previous card's item is fixed at this head: --confirm-stopped is no longer described as being for "earlier versions", and Scenario A now says what to do when the relaunch is still refused after the scope confirmation.
Blocking issues: 1
- [X2] The description still says the PR is docs and help text only, with no behaviour change, but the head changes the runtime refusal message [verified]
Problem: since cbca632 the PR changesensure_resume_safe's refusal text (src/hyperloom/inference_optimizer/session/resume_guard.py:228-234), which every operator whose resume is refused reads, and addstest_lane_less_close_task_needs_confirm_stopped_after_the_scope_is_confirmedtotest_resume_scope_gone.py. The description was not updated: its Tests line says "docs and help text only, no behaviour change", the size line says "about 60 lines of docs and help text", the Description still calls--confirm-stopped TASK_ID"one task recorded without an owner scope" -- the framing this commit replaced -- and the Observable effect line mentions only the runbook andrecover --help. AGENTS.md: "Every change states its observable effect in its own PR description." src/hyperloom/inference_optimizer/session/resume_guard.py:229
Impact: the release notes are built from PR descriptions, so the changed refusal message -- the text an operator sees at the moment the runbook exists for -- would ship unannounced, and a reader of the description is told nothing at runtime changed.
Action: update the description: state that the refusal message now names the scope step first and routes a listed task that names no owner scope to--confirm-stopped, describe--confirm-stoppedas the head does, drop "no behaviour change" and "docs and help text only", and name the new test.
Checked: the cbca632 delta in operations.md, operator-scripts.md, SKILL.md, cli/recover.py RECOVER_DESCRIPTION and session/resume_guard.py (ensure_resume_safe message, _scan_tasks, _scan_leases, _other_scopes, _label, _task_leases, confirm_task_stopped, _confirm_task_stopped_in_transaction, _confirm_scope_gone_in_transaction); phases/close.py and dispatcher.py for the lane-less CLOSE steps; the new test; the description and the author's reply; tree-wide grep at head for the replaced "legacy empty-scope" text | Ran: git diff 9f4ffa47e cbca632dc; CI at cbca632 (33 pass, 7 label-gated skipped); confirm_scope_gone traced statically (it needs fcntl, unavailable on this host) | Base: d755931 | Head: cbca632
|
@chaojhou [X2] fixed — the description now matches the head: it states that the refusal message |
There was a problem hiding this comment.
PR #1880 -- docs: document recover --confirm-scope-gone for a refused resume
What it does: documents hyperloom recover --confirm-scope-gone in the disaster-recovery runbook, the lifecycle row, the recover exit codes and help, operator-scripts.md, optimization-loop.md and SKILL.md, and changes the refusal message ensure_resume_safe prints so it names the scope confirmation first and sends a listed task that names no owner scope to --confirm-stopped. The previous card's item is fixed: the description now states the changed refusal message, describes --confirm-stopped as the head does, drops "docs and help text only, no behaviour change" and names the new test.
Blocking issues: none
Checked: the description as edited at 2026-10-16T14:35Z against the head diff (session/resume_guard.py message and docstring, test_resume_scope_gone.py, the cli/recover.py help constants); head unchanged since the previous card | Ran: gh api for the description, checks and reviews; diff of resume_guard.py | Base: d755931 | Head: cbca632
hyperloom recover --confirm-scope-gonein the operator docs and in therecoverhelp text.docs/reference/operations.mdScenario A told an operator whose pod was OOM-killed to relaunch with--resume-fromand describedrecoveronly as a breakdown rebuild, but a resume in a new pod is refused until the lost pod's owner scope is confirmed gone. Scenario A now covers the refused resume: what it prints, when to runhyperloom recover --session-dir S --confirm-scope-gone OWNER_SCOPE --confirmation-reason TEXT(a whole execution environment that no longer exists) and, when the relaunch is still refused after that,--confirm-stopped TASK_IDfor each listed task that names no owner scope (such as a lane-less CLOSE-phase step), what the confirmation changes, and each case in which it refuses. The crash-recovery lifecycle row, therecoverexit codes,operator-scripts.md, the top-levelhyperloomcommand summary and therecoversubcommand help/description say the same. Therecoverhelp and description strings live as constants incli/recover.py, beside the other recover options, so_build_parserdoes not grow (the code-metrics gate fails any growth of it). The refusal messageensure_resume_safeprints (session/resume_guard.py) now gives the same order: the scope confirmation first, then--confirm-stoppedfor a listed task that names no owner scope. This is the main-branch counterpart of the documentation change requested on release/v1.1.4: cherry-pick resume fixes (#1859, #1870, #1871, #1879) and round server teardown (partial #1606) #1874 (release/v1.1.4).test_lane_less_close_task_needs_confirm_stopped_after_the_scope_is_confirmedintest_resume_scope_gone.py, which follows the runbook path (confirm the scope, relaunch still refused by a lane-less CLOSE task,--confirm-stoppedit, relaunch admitted). Rantest_hyperloom_cli.py,test_resume_scope_gone.py,test_setup_cli.pyand the recover/resume tests (282 passed),scripts/check_cli_references.py(clean),ruff check/ruff format --checkat the pinned v0.16.2, and checkedpython -m hyperloom recover --help._build_parserkeeps its length.hyperloom recover --helpexplains the confirmation mode and exit codes, and the refusal message a refused--resume-fromprints now names the scope confirmation first and sends a listed task that names no owner scope to--confirm-stopped. Before, the runbook ended at the refusal and the message pointed only at--confirm-stoppedfor legacy empty-scope ownership.🤖 Generated with Claude Code