fix(doctor,docs): the documented path out of a halt must actually end… - #695
Merged
Conversation
… the halt (#693, #694) Two defects, both found by following keel's own instructions during the paper-equities bootstrap, and both of which cost real operator time. #693 -- `doctor`'s `rail.kill_switch` finding offered `keel autonomy on` as the fix. That command cannot clear a kill switch; its own docstring says so. They are separate gates on purpose: autonomy decides who gets ASKED, the kill switch decides whether the agent runs at all. An operator who followed the fix line ended up in the worst of the two states -- a halted agent authorised to trade unattended. The fix line now reads `keel resume`. The old assertion in test_doctor.py pinned `keel autonomy on`, so the defect had a test defending it. It is restated here, with a comment saying what it got wrong. #694 -- the runbook's paper-equities and paper-hourly bootstraps ran `migrate`, seeded rules and fetched candles, then stopped. `migrate` creates schema and never seeds, so a fresh database has no `kill_switch` row and `get_state("kill_switch", default=True)` fails closed. Both profiles logged `skipped: kill_switch` every cycle until someone noticed. Each bootstrap now names the arming step immediately after its own fetch block, deliberately OUTSIDE the copy-pasteable fence -- same gate as `keel autonomy on` and the rail-17 release: a human at a terminal, never a scheduled job. Tests (written first, red before green): tests/commands/test_doctor_fix_lines.py -- 2 tests: every fix line names a real command, and the kill-switch fix names `keel resume` specifically tests/test_bootstrap_arms_the_profile.py -- 3 tests: both bootstrap sections exist, each names the arming step, and the step is NOT inside a copy-pasteable block Mutation-verified, four mutants, all killed: fix line reverted to `autonomy on`; fix line naming a nonexistent command; the equities arming step deleted; the arming step folded into the fence. Closes #693 Closes #694 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NzuKAe2RVrPt9acVAWjRyL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
… the halt (#693, #694)
Two defects, both found by following keel's own instructions during the paper-equities bootstrap, and both of which cost real operator time.
#693 --
doctor'srail.kill_switchfinding offeredkeel autonomy onas the fix. That command cannot clear a kill switch; its own docstring says so. They are separate gates on purpose: autonomy decides who gets ASKED, the kill switch decides whether the agent runs at all. An operator who followed the fix line ended up in the worst of the two states -- a halted agent authorised to trade unattended. The fix line now readskeel resume.The old assertion in test_doctor.py pinned
keel autonomy on, so the defect had a test defending it. It is restated here, with a comment saying what it got wrong.#694 -- the runbook's paper-equities and paper-hourly bootstraps ran
migrate, seeded rules and fetched candles, then stopped.migratecreates schema and never seeds, so a fresh database has nokill_switchrow andget_state("kill_switch", default=True)fails closed. Both profiles loggedskipped: kill_switchevery cycle until someone noticed. Each bootstrap now names the arming step immediately after its own fetch block, deliberately OUTSIDE the copy-pasteable fence -- same gate askeel autonomy onand the rail-17 release: a human at a terminal, never a scheduled job.Tests (written first, red before green):
tests/commands/test_doctor_fix_lines.py -- 2 tests: every fix line names a
real command, and the kill-switch fix names
keel resumespecificallytests/test_bootstrap_arms_the_profile.py -- 3 tests: both bootstrap
sections exist, each names the arming step, and the step is NOT inside a
copy-pasteable block
Mutation-verified, four mutants, all killed: fix line reverted to
autonomy on; fix line naming a nonexistent command; the equities arming step deleted; the arming step folded into the fence.Closes #693
Closes #694
Claude-Session: https://claude.ai/code/session_01NzuKAe2RVrPt9acVAWjRyL
What & why
Tests-first evidence
Gates (all must pass)
uv run ruff checkcleanuv run mypycleanuv run pytest -qgreenScope check
leave checked only if true, and if so: cite the source and open the discussion
BEFORE review (CONTRIBUTING.md, "Governance: rulings vs. machinery").