Skip to content

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-ev oracle;
  • 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:

2. Executive current-state snapshot ​

ItemVerified state
VPS / instancedeploy@poly.grot.app, harvester-engine
Engine containerpm-engine-harvester-engine, running
Engine start2026-08-09T11:18:48.866218325Z
Engine args--engine-db /data/engine.db; no --dry-run, therefore live
Loaded strategyweather-harvester
Loaded configid 1, version 1, SHA-256 255752ec8461585bb6d241b2bd1ab2d66d03fdea16d80af4b47468c59b9a912b
DB latest / publishedversion 2 / version 2
Pending restartyes: loaded 1 differs from published 2
Difference v1 → v2only discovery.presubscribe_lead_seconds: null → 60
Strategy rowsexactly weather-harvester and weather-motion; both enabled
Open fill-checked positions2
Local target protection2/2, one PLACED target SELL per position at 0.99
Capture containerexited code 0 at 2026-08-09T05:31:11Z
Current capture storagecapture root is empty
Sweep readinessblocked: no capture pair exists on the VPS
Entry-pattern OpenSpecvalid, implementation 13/32, not deployed
Capture-catalog OpenSpecvalid 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:

  1. weather-harvester — restored tail strategy and live baseline;
  2. 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=1

3.3 Published weather-harvester v2 ​

Exact important values from the immutable VPS snapshot:

ClassSettingValue
Identitywallet / strategylive / weather-harvester
Discoverytag / type104596 / neg-risk
Discoverybook / universe max age10000 ms / 180 s
Discoveryrediscovery / presubscribe60 s / 60 s
Entryflow / outcomeDirect / No
Entryprobability floor0.65
Entryask band0.65–0.85
Entryprice base / offsetBestAsk / -0.01
Entrypost-only / BUY TTLtrue / 300 s
Entrywindow / anchor90000 s / GstLocalMidnight
Depthminimum / band$20.00 / 0.05
Selectionminimum rank4
Selectionsibling age / concurrency10800 s / 10
Qualityconfirmationshadow, 2 Gamma epochs
LDIminimum / phase / missing0 / Uncertain / blocked
Regimeconfigabsent / disabled
Exittargetabsolute 0.99
Rank exitpolicyenabled V1, exit rank 2
Stopthresholdabsolute 0.50
Stopdebounce / cooldown1 s / 10800 s
Stoptrade confirmationenabled
Stopdeep margin / strong size0.25 / 100 shares
Sizingper-market / total budget$5.00 / $50.00
Sizingminimum size / shares cap5 shares / absent
Budgetreinvest realised PnLtrue
Circuit breakerstops / loss-24h3 / $1.00
DCAenabled / no-progresstrue / 5
Toxic flowstatelog_only=true, active_cancel_enabled=true
Sparse evidenceliquidity profile128 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:

PositionConditionOutcomeEntryInventoryTerminal SELL fill
1410xf9d4b87d4b9900f089a1371c5db5ff5414104cb9c431c75281ad08360d0e1a57No0.796no
1420xddfc5cce7938902b30a257dd3db342832a5c48dd05ce81c4d11f762aecf0e46aNo0.845no

exit-protection --engine --json returned:

text
open_rows=2, protected_local=2, alerts=0,
no_entry_fill=0, no_sellable_inventory=0

Each 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 --json

The 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 stageEnteredBlockedPassedLocal dropGlobal contribution
Input dedup299,5341,506298,0280.50%0.50%
Outcome=No298,028149,069148,95950.02%49.77%
Probability ≥0.65148,95917,549131,41011.78%5.86%
Ask present131,41017,815113,59513.56%5.95%
Ask in 0.65–0.85113,59565,85647,73957.97%21.99%
Bid depth47,7397,80539,93416.35%2.61%
Rank ≥439,93439,9340100.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
RankLatest condition rowsVeto rows
166
23535
32222
430

Rank-predicate-only counterfactual:

Minimum rankCurrent veto rows clearingShare of veto
400%
32234.92%
25790.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:

  1. unchanged baseline;
  2. depth $20 / $17.5 / $15, holding prices and rank fixed;
  3. paired probability/lower band 0.65 / 0.625 / 0.60;
  4. rank 4 / 3 as a separate axis;
  5. keep upper entry 0.85 fixed 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:

  1. 1786214101160-1 failed strict validation because pool-global NewMarket referenced a condition absent from the filtered Gamma sidecar.
  2. The recorder was corrected to admit NewMarket / MarketResolved only when an outcome is in the ordered captured universe; validation was not weakened.
  3. 1786215056338-1 ran 180 seconds with a 1 GiB pair cap and 64 GiB reserve, wrote 280,792 event records plus 8 Gamma pages and validated.
  4. Two replays processed 269,147 frames / 268,959 decisions with digest 06141ade3d65218df05c1be6284bc8337b6207883da64f776212f3916c41c3e4, but emitted zero orders/fills. That proves acceptance/determinism only.
  5. 1786215591756-1 started 2026-08-08T18:59:51Z under the old 12h / 32 GiB pair / 64 GiB reserve profile and stopped cleanly at 2026-08-09T05:31:11Z after about 10.5h and 34,360,835,420 bytes, at the size boundary rather than a full-day boundary.
  6. 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/captures

Read-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 reads

Root cause:

  • GET called count_lines on 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_sessions table.

Заявка 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}.rs
  • crates/pm-engine/src/strategies/directional/strategy.rs
  • crates/pm-engine/src/config/loader.rs
  • crates/pm-engine/src/main.rs
  • crates/pm-engine/tests/it/directional_harvester_outcome_filter.rs

10.3 Required next tasks ​

  1. Task 3.4: disk-fault/slow-writer proof that decisions never change and every loss makes completeness fail.
  2. Task 4.4: absent/enabled byte parity for orders, cancellations and decisions; benchmark duplicate-burst overhead.
  3. Task 4.5: filled-position watch set through OPEN/SELLING to terminal/seal.
  4. Tasks 5.x: authoritative signal/order/fill/position/closure and stop/FSM events; never synthesize lifecycle results.
  5. Tasks 6.x: validator and byte-stable threshold-free export, denominators, no-survivorship and gap/epoch rejection.
  6. Tasks 7.x: strategy/storage/engine/operations SSOT.
  7. Task 8.1: full Rust/frontend/clippy/format/OpenSpec gates.
  8. Task 8.2: first deploy with recording section absent.
  9. 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> --json

Repository 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 ​

  1. Confirm loaded version/hash.
  2. Separate infrastructure absence (no ask, coverage) from strategy gates.
  3. Name the sequential denominator, not only global contribution.
  4. Require raw distribution or same-input sweep for numeric uplift.
  5. Include unchanged baseline in every grid.
  6. Repeat on a second independent forward recording.
  7. Require filled terminal forward outcomes and the Harvester EV oracle for profitability claims.

11.3 Before restart/deploy ​

  1. Re-run positions and exit-protection.
  2. Treat published v2 / loaded v1 as explicit pending-restart state.
  3. Follow controlled restart/recovery; open positions currently exist.
  4. After restart confirm loaded v2 and new hash.
  5. Verify target SELLs or authoritative terminal replacements.
  6. Start a new funnel epoch; never merge v1 and v2 ticks.
  7. 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=0 cannot 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_ask has 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_LOCAL is 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: 07cf609d9e343f8440d80e586a26b50377a71c5b

The 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.

  1. Read this handoff, AGENTS.md, strategy/risk SSOT and both active changes.
  2. Refresh positions/protection immediately; open state is volatile.
  3. Persist a new raw funnel bundle before the ring advances.
  4. Do not restart merely for presubscribe while position protection is unverified. If approved, follow §11.3.
  5. Continue entry-pattern tasks 3.4, 4.4 and 4.5 before lifecycle/export.
  6. Keep tasks.md truthful and test each checked task.
  7. Complete lifecycle truth and validator before production enablement.
  8. Run a short current-binary capture smoke and demand non-zero baseline orders before a 24h recording.
  9. Keep parameter variants offline until terminal forward fills permit EV.
  10. 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 stageEnteredBlockedPassedLocal drop
Input dedup248,5022,739245,7631.10%
Outcome=No245,763122,957122,80650.03%
Probability ≥0.65122,80623,18799,61918.88%
Ask present99,61920,35479,26520.43%
Ask in 0.65–0.8579,26548,21631,04960.83%
Bid depth31,0498,43522,61427.17%
Rank ≥422,61421,77484096.29%
Duplicate active signal840839199.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=4

positions --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 present

Thus 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.