Repository navigation
fix(state): the sqlite3 salvage remedy must survive the shell when pasted - #891
Conversation
CI note: slice 16/16 is RED, and it is INHERITED from #889 — not this PR
Measured, not argued:
Root cause: Incidentally this disproves the "cli.py:17984 is fixed but NOT GATED" finding carried on the parent card: it is gated, just by Filed as The 37 other checks pass, including |
|
Upstream port opened: NousResearch#119604 ( NOT a cherry-pick — re-measured against
The CLASS does, and it is measured: upstream's replacement command still interpolates the path bare — Upstream is pull-only for us; this PR is not a blocker on #891. |
…sted
hermes_state printed a pasteable recovery command with the DB path
interpolated bare at three sites on the DB-corruption path:
... salvage with `sqlite3 {db_path} ".recover"`.
For a HERMES_HOME holding a space (Google Drive's "My Drive", or the Windows
LOCALAPPDATA default under C:/Users/<First Last>/, where a space is the NORM)
the printed remedy splits:
printed : sqlite3 /Users/x/My Drive/hermes/state.db ".recover"
bash argv: ['sqlite3', '/Users/x/My', 'Drive/hermes/state.db', '.recover']
sqlite3 : exit=1 Error: near "Drive": syntax error
Unreachable remedy on the one path where the operator has least slack. Routed
all three through hermes_cli.cli_hint.hint_value, the choke point #889 landed;
no import cycle (hermes_state.py already hard-imports hermes_cli.sqlite_runtime
at module level, and cli_hint's only dependency is shlex).
hermes_state.py:2521 _persistent_repair_exhausted_error
hermes_state.py:2721 _backup_db_file, low-disk guard
hermes_state.py:2736 _backup_db_file, disk-space-unknown guard
Found by Argus as FINDING F3 in the round-2 review of PR #889 (card
t_b649d6d1), non-blocking and deliberately carded as an orthogonal file.
VERIFIED
- Reproduced first, E2E through the real `hermes sessions repair` path with a
real damaged DB under a spaced HERMES_HOME: broken before, one word after.
- 7 new tests drive the REAL print path (sessions_cmd.cmd_sessions), extract
the backticked span from CAPTURED stdout and hand it to a REAL /bin/bash.
No shlex simulation of the paste — that was the F2 tautology round 1 of the
parent card was blocked for. 7 passed.
- Mutation battery, each applied by a mutator that REFUSES to report a no-op,
each reverted and cmp-verified byte-identical:
M1 revert all 3 sites -> 5 failed
M2 revert site 1 only -> 3 failed
M3 revert site 2 only -> 2 failed
M4 revert site 3 only -> 2 failed
M5 hint_value -> passthrough -> 4 failed
Each single-site mutation reds exactly its own test plus the class guard.
- Adjacency, same 8 files on BOTH trees: 210 passed at PR-889 base, 210 passed
here. Identical.
- ruff 0.15.10 clean; git diff --check clean.
Implementation diff is 4 lines plus one import.
a9cc3fa to
1882e84
Compare
…hell Residual of the #889/#891 unreachable-remedy class. Eight sites across six subsystems interpolated a HERMES_HOME-derived path -- or an interpreter or executable path resolved under one -- bare into a backticked span the operator is told to paste. For a home holding a space (Google Drive's "My Drive", or the Windows C:/Users/<First Last> default where a space is the NORM) the printed remedy does something other than what the message says. Measured before the fix, each through its REAL printer under a real spaced HERMES_HOME, with the printed span handed to a REAL /bin/bash: self_repo_guard git clone --shared '<root>' <scratch>/t_123 -> ['git','clone','--shared','<root>', '/tmp/.../My','Drive/hermes/scratch/t_123'] #889 fixed {root} and left {scratch} bare in the SAME span. whatsapp adapter cd <bridge> && <npm> install -> bash rc=127: /tmp/.../My: No such file or directory (refuses outright; the remedy cannot even start) runtime-parity git -C <TREE> log --oneline HEAD...fork/main -> ['git','-C','/tmp/.../My','Drive/.../hermes-agent', ...] doctor / run.py <sys.executable> -m pip install ... -> ['/tmp/.../My','Drive/venv/bin/python','-m','pip', ...] run.py skills hermes skills install official/My Category/demo-skill -> [...,'official/My','Category/demo-skill'] plugins_cmd x2 hermes plugins install <source> --force --ref <sha> -> [...,'file:///tmp/.../My','Drive/.../demo-plugin', ...] Routed each through hermes_cli.cli_hint.hint_value, the choke point #889 established. Import direction was checked per file; five import hermes_cli directly. staging/scripts/runtime-parity-check.py cannot: it deploys STANDALONE to ~/.hermes/scripts/ and runs under /usr/bin/python3, where hermes_cli is not importable (verified), so it carries a verbatim local copy with a test pinning it to the shared implementation over six token shapes. TESTS drive the REAL print path and judge with a REAL shell; no assertion is on the string's shape, and the paste is never simulated with shlex (the tautology the grandparent card was blocked for). The whatsapp span is a COMPOUND command (`cd X && Y install`), not a word list, so printf would execute rather than lex it -- that oracle instead RUNS the span and has the callee report the argv and cwd bash actually handed it. Verified: tests/test_residual_cli_hint_pasteable.py 12 passed mutation: 10 mutants, 10 KILLED -- each of the 8 sites reverted individually reds its OWN assertion; M10 (always-quote) reds the three readable-form guards, proving the over-fix control bites adjacency: 468 passed across test_self_repo_guard, test_terminal_task_cwd, test_plugins_cmd, test_plugin_install_ref, test_doctor, test_voice_command, test_cli_hint, test_whatsapp_send_message_media staging/tests/test_pending_restart_redrive.py green under /usr/bin/python3, confirming the standalone shim does not break the real deploy path ruff 0.15.20 clean; git diff --check clean Stacked on #889 (hint_value lands there); do not merge before it. Card: t_e587758d
…hell Residual of the #889/#891 unreachable-remedy class. Eight sites across six subsystems interpolated a HERMES_HOME-derived path -- or an interpreter or executable path resolved under one -- bare into a backticked span the operator is told to paste. For a home holding a space (Google Drive's "My Drive", or the Windows C:/Users/<First Last> default where a space is the NORM) the printed remedy does something other than what the message says. Measured before the fix, each through its REAL printer under a real spaced HERMES_HOME, with the printed span handed to a REAL /bin/bash: self_repo_guard git clone --shared '<root>' <scratch>/t_123 -> ['git','clone','--shared','<root>', '/tmp/.../My','Drive/hermes/scratch/t_123'] #889 fixed {root} and left {scratch} bare in the SAME span. whatsapp adapter cd <bridge> && <npm> install -> bash rc=127: /tmp/.../My: No such file or directory (refuses outright; the remedy cannot even start) runtime-parity git -C <TREE> log --oneline HEAD...fork/main -> ['git','-C','/tmp/.../My','Drive/.../hermes-agent', ...] doctor / run.py <sys.executable> -m pip install ... -> ['/tmp/.../My','Drive/venv/bin/python','-m','pip', ...] run.py skills hermes skills install official/My Category/demo-skill -> [...,'official/My','Category/demo-skill'] plugins_cmd x2 hermes plugins install <source> --force --ref <sha> -> [...,'file:///tmp/.../My','Drive/.../demo-plugin', ...] Routed each through hermes_cli.cli_hint.hint_value, the choke point #889 established. Import direction was checked per file; five import hermes_cli directly. staging/scripts/runtime-parity-check.py cannot: it deploys STANDALONE to ~/.hermes/scripts/ and runs under /usr/bin/python3, where hermes_cli is not importable (verified), so it carries a verbatim local copy with a test pinning it to the shared implementation over six token shapes. TESTS drive the REAL print path and judge with a REAL shell; no assertion is on the string's shape, and the paste is never simulated with shlex (the tautology the grandparent card was blocked for). The whatsapp span is a COMPOUND command (`cd X && Y install`), not a word list, so printf would execute rather than lex it -- that oracle instead RUNS the span and has the callee report the argv and cwd bash actually handed it. Verified: tests/test_residual_cli_hint_pasteable.py 12 passed mutation: 10 mutants, 10 KILLED -- each of the 8 sites reverted individually reds its OWN assertion; M10 (always-quote) reds the three readable-form guards, proving the over-fix control bites adjacency: 468 passed across test_self_repo_guard, test_terminal_task_cwd, test_plugins_cmd, test_plugin_install_ref, test_doctor, test_voice_command, test_cli_hint, test_whatsapp_send_message_media staging/tests/test_pending_restart_redrive.py green under /usr/bin/python3, confirming the standalone shim does not break the real deploy path ruff 0.15.20 clean; git diff --check clean Stacked on #889 (hint_value lands there); do not merge before it. Card: t_e587758d
|
🤖 merged-by: apollo · lane: landing-stack · gate: BYPASS: FleetReview is DISABLED by operator (Ace, 09:30 PT 'Fleet reviews currently paused'); landing on kanban APPROVAL + green CI. Ace 18:17 PT: 'landing stack 888 and 891, handle that right now'. · why: t_b649d6d1 APPROVED r1 ARTIFACT (sqlite3 .recover remedy word-splits on a HERMES_HOME with a space; 3 sites in hermes_state.py). Was stacked on #889 (now merged); retargeted to main, CI green on the new base. Upstream twin: NousResearch#119604 (t_d19cb3bc). |
Argus FINDING F3 from the round-2 review of #889, carded as
t_b649d6d1. Non-blocking there and deliberately carded as an orthogonal file.Stacked on #889 (
daedalus-opus/t_c9e1a012-hint-shell) — it needshermes_cli/cli_hint.hint_value, which #889 introduces. Retarget tomainonce #889 lands.The bug
hermes_stateprinted a pasteable recovery command with the DB path interpolated bare, at three sites on the DB-corruption recovery path:For a
HERMES_HOMEcontaining a space the printed remedy splits:Reachable:
HERMES_HOMEis an arbitrary user-set env var, Google Drive mounts asMy Driveon macOS, and on Windows the platform default isLOCALAPPDATA/hermesunderC:/Users/<First Last>/where a space is the norm. Unreachable remedy on the one path where the operator has least slack.E2E through the real
hermes sessions repairpath, #889's fixed--sourcespelling printed directly beneath the unfixed one:The fix
All three sites routed through
hermes_cli.cli_hint.hint_value— the choke point #889 landed. 4 lines plus one import.hermes_state.py:2521_persistent_repair_exhausted_error(repair budget exhausted)hermes_state.py:2721_backup_db_file, low-disk guardhermes_state.py:2736_backup_db_file, disk-space-unknown guardNo import cycle:
hermes_state.pyalready hard-importshermes_cli.sqlite_runtimeandhermes_cli.configat module level, andcli_hint's only dependency isshlex. Verified by import, not argued.Verification
Reproduced before fixing — Argus's
argus_r2_e2e_state.pyon this tree:db path survives as ONE word: NO, realsqlite3exit=1. After:YES.7 new tests (
tests/test_state_db_recover_hint_pasteable.py) drive the REAL print path —sessions_cmd.cmd_sessionswith a real damaged DB under a real spacedHERMES_HOME— extract the backticked span from captured stdout, and hand it to a real/bin/bash. The paste is not simulated withshlex; that was exactly the F2 tautology round 1 of the parent card was blocked for. Includes an over-fix guard (an ordinary path must not grow quotes) and a source-shape class guard.Mutation battery — each mutation applied by a mutator that refuses to report a no-op, each reverted and
cmp-verified byte-identical:hint_value→ passthroughEach single-site mutation reds exactly its own test plus the class guard — the tests discriminate per-site, not as a lump.
Adjacency, same 8 repair/hint files on BOTH trees: 210 passed at #889's head, 210 passed here. Identical.
ruff 0.15.10clean on both changed files;git diff --checkclean.Class sweep
Re-ran Argus's
argus_r2_pasteable.py: 75 → 72 sites, and the diff is exactly my three. That probe mechanises only half of the discriminator (a value inside a backticked pasteable span); the other half — the value can hold a shell metacharacter — I mechanised too, partitioning the residual 72 by value provenance rather than asserting dismissals:[a-z0-9_-], provider names from a fixed catalogue, board slugs gated by_BOARD_SLUG_REinkanban_db.py:899, generated cron job ids, git refnames (git forbids whitespace).I then measured the IN-class groups through their real printers rather than trusting the classifier — 6 of 6 break a real paste, including the two the card flagged:
tools/self_repo_guard.py:733{scratch}— #889 fixedrootin this span butscratchis_scratch_dir_hint()= the sameHERMES_HOME, in the same printed command. Splits.whatsapp/adapter.py:612+626cd {bridge_dir} && {_npm_bin} install— bash refuses outrightruntime-parity-check.py:482git -C {TREE} …splitsdoctor.py:835,gateway/run.py:28345{sys.executable}splitsgateway/run.py:4265hermes skills install {install_path}splitsplugins_cmd.py:1106+2855{recorded_source}— bash refuses outrightplugins_cmd.py:3019(which the card flagged) is OUT: the span is a literal`git stash pop`with no interpolation;{target}sits in the surrounding prose, not inside the backticks.These are out of this card's scope (different files and subsystems) and are left for a follow-up — I did not widen the diff.
self_repo_guard:733is the sharpest of them: it is a half-fixed span in a file #889 already touched.Fork-first per the fleet default.
hermes_state.pyexists upstream inNousResearch/main; the upstream PR follows once #889 lands, and this does not wait on it.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.