Skip to content

fix(doctor,docs): the documented path out of a halt must actually end… - #695

Merged
eaitbrahim merged 1 commit into
mainfrom
fix-693-694-documented-path
Sep 2, 2026
Merged

fix(doctor,docs): the documented path out of a halt must actually end…#695
eaitbrahim merged 1 commit into
mainfrom
fix-693-694-documented-path

Conversation

@eaitbrahim

Copy link
Copy Markdown
Contributor

… 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

Claude-Session: https://claude.ai/code/session_01NzuKAe2RVrPt9acVAWjRyL

What & why

Tests-first evidence

  • Tests written first, seen failing for the right reason

Gates (all must pass)

  • uv run ruff check clean
  • uv run mypy clean
  • uv run pytest -q green

Scope check

  • This PR touches a rail or a default classification — checked means it DOES;
    leave checked only if true, and if so: cite the source and open the discussion
    BEFORE review (CONTRIBUTING.md, "Governance: rulings vs. machinery").
  • New dependency added (needs discussion first)

… 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
@eaitbrahim
eaitbrahim merged commit f827370 into main Sep 2, 2026
4 checks passed
@eaitbrahim
eaitbrahim deleted the fix-693-694-documented-path branch September 2, 2026 23:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant