Тема
Weather Harvester — live analysis handoff, 2026-08-09
ИСТОРИЧЕСКОЕ ДОКАЗАТЕЛЬСТВО. Capture/replay/sweep команды и рекомендации ниже сняты 2026-08-22 и не являются текущей процедурой. Фактические live наблюдения сохранены как датированный снимок; новый анализ использует только телеметрию реальных сессий, включая order trace.
Operational evidence snapshot as of 2026-08-09T16:47:06Z (
2026-08-09 20:47 +04). This is a dated handoff, not a replacement for normative strategy, risk, storage, capture or deployment SSOT. When runtime disagrees with this snapshot, re-measure and add a newer dated record.
1. Purpose and authority boundary
The active investigation is to increase the useful candidate population that reaches the Harvester probability-rank gate while preserving a positive-EV risk model. The operator's target is to grow a roughly $1,000 trading budget toward $3,000–$5,000 monthly income, but that target is not evidence that the return is achievable. No profitability conclusion has been established from the current forward cohort.
Rules that remain mandatory:
- strategy parameters and all three risk limits come only from
config.db; - a position row is not a fill: BUY and SELL facts must be checked through
scripts/analysis/forensics.sh; - +EV claims require real post-fix filled outcomes, no survivorship, actual stop fills and the Harvester Yield Calculator /
harvester-evoracle; - capture-only contains market traffic, not live decisions, fills or realised position truth;
- deploy only through
scripts/deploy-vps.sh; - the working tree is heavily dirty with concurrent changes; never reset, discard, bulk-stage or commit unrelated files.
Primary references:
docs/strategies/directional-harvester.mddocs/target/risk-and-emergency.mdscripts/analysis/README.md- удалённый
docs/operations/capture-runbook.md— исторический runbook записи потока рынков; его команды и ссылки из этого датированного разбора недействительны docs/operations/runbook.md
2. Executive current-state snapshot
| Item | Verified state |
|---|---|
| VPS / instance | deploy@poly.grot.app, harvester-engine |
| Engine container | pm-engine-harvester-engine, running |
| Engine start | 2026-08-09T11:18:48.866218325Z |
| Engine args | --engine-db /data/engine.db; no --dry-run, therefore live |
| Loaded strategy | weather-harvester |
| Loaded config | id 1, version 1, SHA-256 255752ec8461585bb6d241b2bd1ab2d66d03fdea16d80af4b47468c59b9a912b |
| DB latest / published | version 2 / version 2 |
| Pending restart | yes: loaded 1 differs from published 2 |
| Difference v1 → v2 | only discovery.presubscribe_lead_seconds: null → 60 |
| Strategy rows | exactly weather-harvester and weather-motion; both enabled |
| Open fill-checked positions | 2 |
| Local target protection | 2/2, one PLACED target SELL per position at 0.99 |
| Capture container | exited code 0 at 2026-08-09T05:31:11Z |
| Current capture storage | capture root is empty |
| Sweep readiness | blocked: no capture pair exists on the VPS |
| Entry-pattern OpenSpec | valid, implementation 13/32, not deployed |
| Capture-catalog OpenSpec | valid proposal/design, implementation 0/65 |
No live configuration, process, order or capture was changed during the latest analysis. All VPS operations were read-only.
3. Strategy restoration and config history
3.1 Agreed identities and baseline
Only two strategy identities are intended:
weather-harvester— restored tail strategy and live baseline;weather-motion— separate experimental small-piece motion strategy.
Names such as harvester-engine-v2, harvester-motion-v1 and harvester-tail-20260807 mixed identity with version and must not return. Version is now a DB property.
The operator rejected earlier reconstructions based on 0.65–0.95, 0.45/0.55–0.97 and the later 0.05–0.75 motion-like profile. The approved Harvester baseline is the older 0.65–0.85 tail strategy combined with the probability-rank mechanism. The historical description “this was +EV” is operator context, not a current post-fix EV verdict.
3.2 Versioning already implemented
Archived change 2026-08-09-version-strategy-config-history implemented:
- immutable snapshots in
strategy_config_versions; - monotonic latest and published DB versions;
- retention of the latest 20 versions, with published pinned;
- draft versus explicit publication and CAS conflicts;
- copy-forward restore instead of history mutation;
- version-pinned replay/sweep provenance;
- loaded/published/latest runtime reporting;
- no hot reload: publication needs a controlled restart.
Production read-only SQL confirmed:
text
weather-harvester | enabled=1 | latest=2 | published=2
weather-motion | enabled=1 | latest=1 | published=13.3 Published weather-harvester v2
Exact important values from the immutable VPS snapshot:
| Class | Setting | Value |
|---|---|---|
| Identity | wallet / strategy | live / weather-harvester |
| Discovery | tag / type | 104596 / neg-risk |
| Discovery | book / universe max age | 10000 ms / 180 s |
| Discovery | rediscovery / presubscribe | 60 s / 60 s |
| Entry | flow / outcome | Direct / No |
| Entry | probability floor | 0.65 |
| Entry | ask band | 0.65–0.85 |
| Entry | price base / offset | BestAsk / -0.01 |
| Entry | post-only / BUY TTL | true / 300 s |
| Entry | window / anchor | 90000 s / GstLocalMidnight |
| Depth | minimum / band | $20.00 / 0.05 |
| Selection | minimum rank | 4 |
| Selection | sibling age / concurrency | 10800 s / 10 |
| Quality | confirmation | shadow, 2 Gamma epochs |
| LDI | minimum / phase / missing | 0 / Uncertain / blocked |
| Regime | config | absent / disabled |
| Exit | target | absolute 0.99 |
| Rank exit | policy | enabled V1, exit rank 2 |
| Stop | threshold | absolute 0.50 |
| Stop | debounce / cooldown | 1 s / 10800 s |
| Stop | trade confirmation | enabled |
| Stop | deep margin / strong size | 0.25 / 100 shares |
| Sizing | per-market / total budget | $5.00 / $50.00 |
| Sizing | minimum size / shares cap | 5 shares / absent |
| Budget | reinvest realised PnL | true |
| Circuit breaker | stops / loss-24h | 3 / $1.00 |
| DCA | enabled / no-progress | true / 5 |
| Toxic flow | state | log_only=true, active_cancel_enabled=true |
| Sparse evidence | liquidity profile | 128 levels, 48h |
Version 1 has identical trading and risk values. Only presubscribe is null. Loading v2 can change book readiness and no_ask, not admission thresholds. Because real positions are open, do not restart casually: follow the recovery runbook and re-run exit-protection after an approved restart.
4. Current positions and protection
forensics.sh positions confirmed each BUY against a real filled order:
| Position | Condition | Outcome | Entry | Inventory | Terminal SELL fill |
|---|---|---|---|---|---|
| 141 | 0xf9d4b87d4b9900f089a1371c5db5ff5414104cb9c431c75281ad08360d0e1a57 | No | 0.79 | 6 | no |
| 142 | 0xddfc5cce7938902b30a257dd3db342832a5c48dd05ce81c4d11f762aecf0e46a | No | 0.84 | 5 | no |
exit-protection --engine --json returned:
text
open_rows=2, protected_local=2, alerts=0,
no_entry_fill=0, no_sellable_inventory=0Each has exactly one ordinary_target SELL, PLACED, exchange ID present, full remaining coverage at 0.99: 6/6 and 5/5 shares respectively.
This proves durable local state, not an independent authenticated CLOB open-orders snapshot. There are no terminal forward outcomes yet, so no honest win rate, stop efficiency or Harvester edge_margin exists.
5. Entry funnel evidence
5.1 Semantics
Canonical command:
bash
scripts/analysis/forensics.sh funnel-window --engine \
--instance harvester-engine --window-secs 300 --jsonThe dashboard retains only 300 one-second ticks. A call is not a daily archive. The command reports sequential local denominators, fixes session/config identity and validates survivors == entry_emitted. It does not retain each rejected price/probability/depth value, so percentages cannot answer numeric threshold counterfactuals.
5.2 Latest fully identified window
text
2026-08-09T16:34:59.245Z .. 2026-08-09T16:39:58.245Z
299,534 evaluations, 300 ticks
input_sha256=b3f2ef71007ffd1f4677c5d93afdc5eecc1a535591efac19b14794282d608b55
coverage=876/1,136=77.1127%; mean revisit=469 ms; not saturated| Sequential stage | Entered | Blocked | Passed | Local drop | Global contribution |
|---|---|---|---|---|---|
| Input dedup | 299,534 | 1,506 | 298,028 | 0.50% | 0.50% |
Outcome=No | 298,028 | 149,069 | 148,959 | 50.02% | 49.77% |
| Probability ≥0.65 | 148,959 | 17,549 | 131,410 | 11.78% | 5.86% |
| Ask present | 131,410 | 17,815 | 113,595 | 13.56% | 5.95% |
| Ask in 0.65–0.85 | 113,595 | 65,856 | 47,739 | 57.97% | 21.99% |
| Bid depth | 47,739 | 7,805 | 39,934 | 16.35% | 2.61% |
| Rank ≥4 | 39,934 | 39,934 | 0 | 100.00% | 13.33% |
All other gates were zero in this interval. Funnel parity converged with zero survivors and zero entry emissions in this particular five minutes.
An earlier unpersisted five-minute observation showed approximately 279,349 evaluations, 78.016% coverage, band 22.947%, no-ask 10.387%, probability 6.406%, depth 1.642%, rank 8.139%, entries 0. Its tick bundle/timestamp were not saved. Do not merge it or use it as a reproducible trend; it only proves why durable interval collection is necessary.
6. Rank evidence
The unbounded rank call correctly failed on three mixed config digests. The loaded-session window 2026-08-09T11:18:49Z .. 16:39:58Z produced:
text
input_sha256=bd0ab1d5d7436983fedb4ad896d03570fdb80560a83da1522b333a9cc57dc6bb
selection=66, instrumented=66, emitted=3, veto=63, integrity violations=0| Rank | Latest condition rows | Veto rows |
|---|---|---|
| 1 | 6 | 6 |
| 2 | 35 | 35 |
| 3 | 22 | 22 |
| 4 | 3 | 0 |
Rank-predicate-only counterfactual:
| Minimum rank | Current veto rows clearing | Share of veto |
|---|---|---|
| 4 | 0 | 0% |
| 3 | 22 | 34.92% |
| 2 | 57 | 90.48% |
The three emitted selection rows had rank 4 and asks 0.80, 0.85, 0.84. “Emitted” is trace state, not fill or profit proof. selection_signals upserts on condition_id; this population is latest state, not event history. Never subtract two rank snapshots as interval counts.
7. Safe parameter boundary
The first justified operational intervention is loading v2 presubscribe=60, because it addresses no_ask/coverage without changing trading thresholds. It has not been executed and still requires a controlled restart.
Keep these live values fixed until stronger evidence exists:
- outcome=
No: definition of the restored tail strategy; - upper ask
0.85: widening raises price and required win rate; - probability
0.65: lowering changes the candidate distribution; - depth
$20/0.05: removing it would add at most 7,805 / 39,934 = 19.55% in the latest window but weakens stop-side executability; - rank
4: rank 3 clears 22 current veto rows but proves no EV.
The lower ask boundary overlaps the probability floor. Since probability runs first, lowering only the band floor is unlikely to be an independent lever and may select pathological spread states.
Candidate offline grid after valid raw data exists:
- unchanged baseline;
- depth
$20 / $17.5 / $15, holding prices and rank fixed; - paired probability/lower band
0.65 / 0.625 / 0.60; - rank
4 / 3as a separate axis; - keep upper entry
0.85fixed in the first safety sweep.
Any winner must repeat on a second independent recording and then be checked against real post-deploy terminal fills. Replay alone cannot prove live +EV.
8. Capture/replay/sweep history and current status
8.1 What previous recordings established
The chronology is in docs/analysis/capture-smoke-2026-08-08.md:
1786214101160-1failed strict validation because pool-globalNewMarketreferenced a condition absent from the filtered Gamma sidecar.- The recorder was corrected to admit
NewMarket/MarketResolvedonly when an outcome is in the ordered captured universe; validation was not weakened. 1786215056338-1ran 180 seconds with a 1 GiB pair cap and 64 GiB reserve, wrote 280,792 event records plus 8 Gamma pages and validated.- Two replays processed 269,147 frames / 268,959 decisions with digest
06141ade3d65218df05c1be6284bc8337b6207883da64f776212f3916c41c3e4, but emitted zero orders/fills. That proves acceptance/determinism only. 1786215591756-1started2026-08-08T18:59:51Zunder the old 12h / 32 GiB pair / 64 GiB reserve profile and stopped cleanly at2026-08-09T05:31:11Zafter about 10.5h and 34,360,835,420 bytes, at the size boundary rather than a full-day boundary.- The governed profile was then changed to 24h / 64 GiB pair / 64 GiB reserve. Configuration is not proof that such a run completed.
8.2 Current storage truth
The capture container is exited with code 0. Its mounted root is:
text
/home/deploy/pm-backtest/instances/harvester-engine/data/capturesRead-only inspection showed only the root directory and no artifacts. The user had authorised deletion of obsolete recordings, but no audit evidence assigns a particular deletion to an actor. The safe statement is that the root is empty now.
Consequences:
- no current pair exists for sweep;
- the old 10.5h pair is no longer retrievable from this path;
- a new governed recording is required;
- begin with a short bounded current-binary smoke, validate it and assert a non-zero expected baseline order count before spending 24 hours.
Capture remains market/Gamma input only. It can support same-input replay sensitivity, but not live fills, stop execution or EV. The entry-pattern dataset is needed to join decisions and lifecycle truth.
9. Slow /api/backtest/captures
Evidence before artifact deletion:
text
response=901 bytes; latency=92.83 s
10 JSONL artifacts; 132,581,168,810 bytes (123.48 GiB)
metadata-only walk≈3 ms; dashboard accumulated≈17 TB block readsRoot cause:
- GET called
count_lineson every engine-events artifact on every request; - fixed 30-second frontend polling had no single-flight and overlapped scans;
- multi-stem directories were listed by first suffix match while replay rejected the ambiguity;
- handler referenced an undeclared optional
capture_sessionstable.
Заявка optimize-backtest-capture-catalog ОТМЕНЕНА 2026-08-21: маршрут GET /api/backtest/captures снят вместе со страницей бэктеста, поэтому дефект ушёл с самим маршрутом, а не был починен. Раздел сохранён как замер стоимости перечисления записей (92.83 с и 132.58 ГБ чтения на ответ в 901 байт при опросе раз в 30 с) — он остаётся уроком о цене обхода артефактов на каждый запрос.
10. Directional entry-pattern dataset
Change: openspec/changes/directional-entry-pattern-dataset/
Purpose: capture the exact forward population before admission, both local books, rank/cohort evidence, first blocker, decision values and actual lifecycle facts without blocking or altering trading.
10.1 Completed: 13/32 tasks
- strict optional config with explicit depth, heartbeat, queue, segment and free-space values;
- infrastructure-only
PM_ENGINE_ENTRY_PATTERN_DATASET_DIR, read only when the strategy section is present; - versioned session/candidate/decision/lifecycle/gap/seal models and stable join IDs;
- independent traded/complement books preserving missing, empty, stale, truncation and tail states;
- deterministic book/cohort fingerprints, duplicate counts and heartbeat;
- stop-evidence/FSM record shapes;
- separate SQLite WAL/FULL writer, migrations and indexes;
- bounded non-blocking
try_send, sticky gaps and writer metrics; - segment/free-space stop, accepted-row drain and no auto-deletion;
- pre-admission hook before all directional gates;
- same-condition complement read only from local
MarketStateStore; - first terminal blocker even when no signal exists;
- Direct summary copied from actual computations: rank, resolved price, canonical size/cost, liquidation support and confirmation epochs.
Feature-off performs no path read, complement lookup, projection, fingerprint or recorder-lock acquisition.
10.2 Verification run
The focused evidence is: 29 entry-pattern unit tests passed; one real DirectionalStrategy integration-hook test passed; strict OpenSpec validation and git diff --check passed.
The integration test proves a pre-admission outcome-blocked candidate, explicit missing local complement, observation/decision join and no order. This is not full verification: workspace tests, clippy, frontend gates, parity benchmark and deployment remain incomplete.
Key files:
crates/pm-engine/src/strategies/directional/entry_pattern/{mod,observer,sink,writer}.rscrates/pm-engine/src/strategies/directional/strategy.rscrates/pm-engine/src/config/loader.rscrates/pm-engine/src/main.rscrates/pm-engine/tests/it/directional_harvester_outcome_filter.rs
10.3 Required next tasks
- Task 3.4: disk-fault/slow-writer proof that decisions never change and every loss makes completeness fail.
- Task 4.4: absent/enabled byte parity for orders, cancellations and decisions; benchmark duplicate-burst overhead.
- Task 4.5: filled-position watch set through OPEN/SELLING to terminal/seal.
- Tasks 5.x: authoritative signal/order/fill/position/closure and stop/FSM events; never synthesize lifecycle results.
- Tasks 6.x: validator and byte-stable threshold-free export, denominators, no-survivorship and gap/epoch rejection.
- Tasks 7.x: strategy/storage/engine/operations SSOT.
- Task 8.1: full Rust/frontend/clippy/format/OpenSpec gates.
- Task 8.2: first deploy with recording section absent.
- Only after explicit operator capacity values: publish/restart to enable and validate the first production session.
Do not invent rollout heartbeat/depth/queue/segment/reserve values.
11. Safe continuation procedure
11.1 Monitoring commands
Use the canonical surface, not new ad-hoc trading SQL:
bash
scripts/analysis/forensics.sh positions --instance harvester-engine
scripts/analysis/forensics.sh exit-protection \
--engine --instance harvester-engine --json
scripts/analysis/forensics.sh funnel-window \
--engine --instance harvester-engine --window-secs 300 --json
scripts/analysis/forensics.sh rank-window \
--engine --instance harvester-engine \
--since <loaded-session-start-UTC> --until <window-end-UTC> --jsonRepository instructions prefer the trade-forensics skill. It was unavailable in this Codex session, so the canonical backend script was used directly. Use the skill when available.
For longitudinal analysis, persist funnel-window --raw bundles before the 300-tick ring advances and read them with FORENSICS_FUNNEL_DATA=<dir>. Keep different session/config epochs separate.
11.2 Before recommending a config value
- Confirm loaded version/hash.
- Separate infrastructure absence (
no ask, coverage) from strategy gates. - Name the sequential denominator, not only global contribution.
- Require raw distribution or same-input sweep for numeric uplift.
- Include unchanged baseline in every grid.
- Repeat on a second independent forward recording.
- Require filled terminal forward outcomes and the Harvester EV oracle for profitability claims.
11.3 Before restart/deploy
- Re-run
positionsandexit-protection. - Treat published v2 / loaded v1 as explicit pending-restart state.
- Follow controlled restart/recovery; open positions currently exist.
- After restart confirm loaded v2 and new hash.
- Verify target SELLs or authoritative terminal replacements.
- Start a new funnel epoch; never merge v1 and v2 ticks.
- Deploy only through
scripts/deploy-vps.sh.
12. Traps already encountered
- Sealed capture, full validation and non-zero expected orders are distinct gates.
- Deterministic
orders=0cannot tune a strategy. - Pre-fix captures/backups are diagnostic-only for EV.
- Rank latest rows are not interval counts.
- Funnel percentages do not reveal rejected-value distributions.
no_askhas no strategy threshold; inspect subscription readiness first.- Lowering depth from counts alone weakens stop executability without proof.
- Raising upper entry price raises break-even win rate.
PROTECTED_LOCALis not independent exchange ground truth.- Empty-tree capture API latency does not prove the scan bug fixed.
- Published config is not loaded config; publication is not hot reload.
- Both rows enabled does not mean one engine runs both strategies.
- Never put versions back into strategy labels.
- Never put strategy knobs or budget in env.
- Never hand-deploy or run standalone pm-analytics on the VPS.
13. Worktree handoff
text
branch: main
HEAD: 07cf609d9e343f8440d80e586a26b50377a71c5bThe tree contains many pre-existing modified/untracked files across config versioning, capture validation, backtest jobs, dashboard, frontend, deploy docs and entry-pattern work. Assume they belong to the operator or another task.
Do not use destructive Git cleanup, stage the whole tree, claim a focused commit without inspecting its exact diff, or overwrite overlapping changes. Full workspace verification has not been rerun after the latest entry-pattern edits.
14. Recommended next-agent order
- Read this handoff,
AGENTS.md, strategy/risk SSOT and both active changes. - Refresh positions/protection immediately; open state is volatile.
- Persist a new raw funnel bundle before the ring advances.
- Do not restart merely for presubscribe while position protection is unverified. If approved, follow §11.3.
- Continue entry-pattern tasks 3.4, 4.4 and 4.5 before lifecycle/export.
- Keep
tasks.mdtruthful and test each checked task. - Complete lifecycle truth and validator before production enablement.
- Run a short current-binary capture smoke and demand non-zero baseline orders before a 24h recording.
- Keep parameter variants offline until terminal forward fills permit EV.
- Record UTC window, loaded version/hash and input digest for every future interval so later agents do not repeat the same investigation.
15. Post-handoff interval update — 2026-08-09T16:49:58Z
This interval was measured after the initial document snapshot and uses the same loaded engine session/config v1:
text
window=2026-08-09T16:49:58.245Z..2026-08-09T16:54:57.245Z
evaluations=248,502; ticks=300
input_sha256=e8a6e23399215e3a7fbe38f83f62811479f07791d40aa739915b503975b722b8
coverage=1,112/1,136=97.8873%; mean revisit=1,024 ms; not saturated| Sequential stage | Entered | Blocked | Passed | Local drop |
|---|---|---|---|---|
| Input dedup | 248,502 | 2,739 | 245,763 | 1.10% |
Outcome=No | 245,763 | 122,957 | 122,806 | 50.03% |
| Probability ≥0.65 | 122,806 | 23,187 | 99,619 | 18.88% |
| Ask present | 99,619 | 20,354 | 79,265 | 20.43% |
| Ask in 0.65–0.85 | 79,265 | 48,216 | 31,049 | 60.83% |
| Bid depth | 31,049 | 8,435 | 22,614 | 27.17% |
| Rank ≥4 | 22,614 | 21,774 | 840 | 96.29% |
| Duplicate active signal | 840 | 839 | 1 | 99.88% |
Funnel parity converged: one survivor and one entry emission. This disproves the interpretation that the preceding 100% rank-veto window meant a broken or permanently closed rank path. The 840 passed evaluations mostly referred to one already-active signal and were correctly deduplicated.
The epoch-scoped latest-state rank snapshot then became:
text
input_sha256=7c5f3d681456f2ecbe2959385dac0c1618b56c039675ba68cd6075bc1dc4761c
selection=67; emitted=4; veto=63; integrity violations=0
ranks: rank1=7, rank2=35, rank3=21, rank4=4
rank3 counterfactual=21/63=33.33%
rank2 counterfactual=56/63=88.89%The new rank-4 trace was:
text
condition_id=0x92b28c279a5995cee1d05e0788fbe92b1412eea1532d9240a3ee337036dfa5fe
event=highest-temperature-in-wuhan-on-august-10-2026
trace best ask=0.85; own NO price=0.845; rank=4positions --cid returned no position. Because no canonical forensics subcommand exposes orders without a position, one narrow read-only query to the authoritative orders table was used to disambiguate the lifecycle:
text
side=BUY; order price=0.84; size=5 shares
status=CANCELLED; reject_reason=expired; filled=0
exchange id presentThus this was a valid rank emission and real exchange-addressed order, but an unfilled expiry. It must be counted in emitted/unfilled denominators and never as a position, win or loss.
The two prior fill-checked positions remained OPEN and unchanged. The repeated exit-protection result retained the same digest 1e9bd3f20c041b20fc436622f321a19c353dcbb99ca2a75857710f2e09fffa52: 2 open, 2 PROTECTED_LOCAL, 0 alerts.