TASK: Profit capture — make the trailing stop's activation and trail-distance
      TUNABLE (they are hardcoded 1.0R / 1.0R today), and prove the right pair
      on the recorded tick series of real trades BEFORE it goes live. Default
      stays byte-identical; the evidence grid is the deliverable. ONE family:
      the trail pair. No other policy changes.

## Established context (verified in code 2026-09-07)

- The give-back is proven and consistent: 2026-09-07 position #28 peaked at
  ₹455 (2.1R) and booked ₹195 (0.9R); #25 peaked ₹253 booked ₹66; last week
  the book produced ₹4,621 of MFE and kept none. Cause, in code:
  trailing_stop.py:106-107 _ACTIVATION_MULTIPLE = 1.0 and
  _TRAIL_DISTANCE_MULTIPLE = 1.0 (module constants, imported by v3). At the
  instant profit reaches +1.0R the proposed stop = peak − 1.0R ≈ entry
  (break-even), and a trade must exceed +2.0R to bank +1.0R. Every promotion
  today happened in a 15-20s burst at the peak, then price retraced into the
  freshly-raised (1R-behind) stop. Tightening the trail distance is the
  direct lever.
- H-1 (live since 2026-09-07) gives stop-LEVEL fills. This matters: the
  read-only counterfactual in the 2026-09-06 report showed that at
  production (tick-mark) fills NO activation×trail pair was profitable, but
  at STOP-LEVEL fills early activation (~0.6R) + tight trail (~0.25-0.40R)
  produced the only positive cells. The lever only works now that H-1 is in.
- Two things found and deliberately NOT touched here: break_even.py fires at
  _TRIGGER_MULTIPLE = 1.0 (redundant with the trail at 1R; monotonic, can
  only tighten, so harmless — leave it, note it); partial_exit.v1 SIGNALS
  partial_exit_promote_partial at 1.5R but is observational-only ("downstream
  consumer applies the partial close") and NO consumer executes it — today
  #28 fired the signal and closed full-size 15s later. Record this as a
  finding for a separate prompt; do not wire it here.

## IMPORTANT FINDING — default byte-identical; the pair is chosen from evidence

Ship the MECHANISM (config-driven multiples + the proving grid) with defaults
= 1.0 / 1.0, so production, CI and fresh installs behave EXACTLY as today
until a human sets new values. The deliverable that makes tomorrow different
is the GRID: the before/after P&L of candidate pairs re-priced over the
recorded OBSERVED tick series of every closed position (now including today's
three clean H-1-era fills). Nitin reads the grid and sets the pair — a
one-line config change — with evidence in hand. This is n≈24-27, L2: state
it, show adjacent-cell volatility, and label the recommendation interim,
to be re-confirmed as Phase 0a's excursion corpus grows.

## Verify the premises

1. _ACTIVATION_MULTIPLE / _TRAIL_DISTANCE_MULTIPLE definition site and every
   importer (trailing_stop.py defines; v3 imports — confirm v3 is the live
   registered policy and v1/v2 are shims). The config read must reach the
   code path the production policy actually executes.
2. The config system for thresholds: schema.py DEFAULTS + resolved.py reader
   + the spec/seed lockstep the v2-config-schema-sync gate holds (the same
   three-artifact pattern the atr_derived flip and expiry floor used).
   The keys are floats with a range; default 1.0/1.0.
3. The counterfactual/replay infrastructure to REUSE, not rebuild:
   shadow_mode/forensics.py counterfactual(...), stop_execution_study.py,
   replay_signals.py. Confirm which can re-price a closed position's
   recorded OBSERVED ticks (auto_paper_logs / OBSERVED events carry
   mark_price + stop per tick) under a candidate (activation, trail) pair at
   STOP-LEVEL fills. If none re-prices exits over recorded ticks, the grid
   harness is new code in experiments/ or shadow_mode/ — report which path.
4. Monotonic tightening (v3 §26.6) and the reject-not-clamp guards must
   survive: a tighter trail still only ever raises a long's stop. Confirm the
   promotion repository's "protection can only tighten" rule is unaffected.
5. break_even at 1.0R: with activation below 1.0R, confirm break_even still
   composes safely (both monotonic; the tighter wins). Do NOT change it.

## Do NOT change

The stop model · option_stop_atr_mult (1.25) · runner_target_atr_mult / the
target (separate concern) · break_even.v2 · partial_exit.v1 (record the
no-consumer finding; wire nothing) · spike/session/volatility/manual/hard
policies · the DEFAULT values (stay 1.0/1.0) · any filter or entry logic ·
the monotonic-tightening rule. ONE family changes: the trailing pair, and
only its tunability + evidence — not its live value.

## Implementation

1. Two threshold config keys (e.g. threshold.trail_activation_mult,
   threshold.trail_distance_mult), floats, sane range (e.g. 0.1–3.0),
   DEFAULT 1.0 / 1.0, in schema.py + Spec 05 amendment (dated) + seed SQL,
   lockstep; resolved.py reader with reject-not-clamp (non-finite / ≤0 →
   refuse to boot, per the option_stop invariant precedent).
2. trailing_stop reads the two values from resolved config instead of the
   hardcoded constants; behaviour with 1.0/1.0 is byte-identical (prove it).
3. The PROVING GRID (reuse premise-3 infra where possible): for a grid of
   (activation ∈ {0.3,0.5,0.75,1.0}, trail ∈ {0.25,0.4,0.5,0.75,1.0}),
   re-price every closed position's recorded OBSERVED ticks at STOP-LEVEL
   fills, output a before/after net-P&L table + per-trade capture% for the
   recommended cell. Output to a report doc / file, no new tables.
4. Nothing goes live: defaults stay 1.0/1.0. The report RECOMMENDS a pair
   with its grid evidence; setting it is a separate one-line config act.

## Tests

- Default 1.0/1.0 reproduces today's three exits byte-identical (66.04 /
  the engine's #26 fill / 195.00) — regression lock.
- A fixture pair (e.g. 0.5/0.4) produces a tighter stop and an earlier lock
  on a known tick series; monotonic tightening still holds; reject-not-clamp
  refuses 0 and negatives at boot.
- Grid harness correctness on a synthetic position with a known peak and
  retrace (hand-computed capture for one cell).
- Config sync gate green (three artifacts agree).
Then the FULL suite:

    bash backend/scripts/ci/run_all.sh

All 13 gates green.

## Verification report

A. Files changed  B. Byte-identical proof at 1.0/1.0 (today's 3 exits)
C. The grid table over all recorded positions, at stop-level fills, with n
and per-cell values  D. The recommended pair + its before/after + capture%
and the honest caveat (L2, n≈24-27, adjacent-cell volatility shown)
E. break_even-composition and monotonic-tightening proofs  F. partial_exit
no-consumer finding (for a later prompt)  G. 13 gates  H. Premises that did
not match  I. Unknowns

CRITICAL: The default must not change live behaviour by one paisa — prove it
against today's exits. The pair goes live only after Nitin reads the grid.
If the grid shows the give-back is NOT recoverable at any pair (adjacent
cells all negative even at stop-level fills), that is the finding — report
it, do not pick a cell to look good. One family; break_even, partial and
target are not touched.
