export-runner: fix new-symbol discovery aborting with a year-0000 backtest

discover_start's stdout is its result channel (read via command
substitution in process_symbol), but the probes inside it stream the
cBot's "[BOT] …" progress on stdout too. That noise leaked into the
captured value, so start_idx parsed to 0 and the resume walk began at
year 0 -> an unparseable "--start=01/01/0" backtest that retried out and
hard-aborted the whole run. Only a brand-new symbol (no files on disk yet)
hits this path, so it stayed invisible until AUDUSD was added.

Redirect every probe call in discover_start to stderr (1>&2) so its
stdout carries only the "YEAR MONTH" result, and document the contract.
Add scripts/test-export-runner.sh: source-level tests that stub probe_run
to emit the same stdout noise and assert a clean result (RED without the
redirect). Make SYMBOL_FILE overridable for scoped runs/tests.
This commit is contained in:
2026-06-25 09:02:10 +02:00
parent 72824cf680
commit ddd8274fad
3 changed files with 106 additions and 3 deletions
+21
View File
@@ -79,3 +79,24 @@ data dir untouched):
yesterday, and left the trusted middle `03` byte-identical.
- **Clean-empty safety**: `run_one` on an empty future window returns rc 3 (skip), never the
rc 2 that would abort the run.
## Post-deploy fix — discovery stdout pollution (year-0000 abort)
The first **new** symbol added after the rewrite (AUDUSD) aborted on the scheduled
2026-06-25 run with `--start=01/01/0 --end=31/01/0000` ("Value for parameter start can't
be parsed"). Root cause: a function-output contract violation, not bad data.
`process_symbol` resolves a brand-new symbol's first month via `sd=$(discover_start …)`
command substitution, so `discover_start`'s **stdout is its result channel**. But the
probes inside it (`probe_run``run_one`) stream the cBot's `[BOT] …` progress on stdout
too. Those lines leaked into `sd`; `start_idx=$(midx ${sd% *} ${sd#* })` then parsed
garbage and collapsed to `0` → the walk started at year 0, month 1 → an unparseable
`01/01/0` backtest. (The abort was correct behaviour: it stopped a ~24 000-iteration walk
from year 0 to now, and nothing was written to the data dir — the scrape failed before any
file op.) Only the no-existing-files branch calls `discover_start`, so only a *new* symbol
could trigger it — invisible until AUDUSD.
**Fix**: every probe call inside `discover_start` is redirected `1>&2`, so its stdout
carries only the result line. A documented CONTRACT comment now guards the function.
Covered by `scripts/test-export-runner.sh` (source-level; stubs `probe_run` to emit the
same stdout noise and asserts a clean `YEAR MONTH` result — RED without the redirect).