# IFVG Desk v1.2.0 — setup audit trail

The audit records why a setup changed state on the bar where that decision happened. Each event saves its gap boundaries, trigger conditions, confluence evidence, risk candidate and reason under a stable Setup ID. The history panel reads saved values rather than reconstructing old explanations from today's checklist.

Recording is enabled by default. The history panel and Pine Logs export are optional and start off. Audit controls do not choose entries or modify the paper rule.

## Identity and time

`setup_id` is `symbol|frame|birth-open-ms|bull/bear`: the full TradingView ticker ID, chart timeframe, opening UTC Unix timestamp in milliseconds of the gap's third/birth candle, and original gap direction. The gap is confirmed only at that candle's close. A bullish birth is a potential short IFVG; a bearish birth is a potential long IFVG. The table's LONG/SHORT side always describes that intended inverted direction, including on the birth event.

All events for that gap reuse the same Setup ID. The existing `zone_id` is the birth candle's opening timestamp; the full Setup ID adds symbol, timeframe and original direction. An `event_id` adds the event candle's close milliseconds and event kind to the Setup ID. Matching IDs identify the same source gap, not necessarily the same settings or data revision: include the report header when comparing separate runs.

The existing accepted-entry JSON alert also includes `setup_id`, so a captured entry alert can be matched to the audit. Its existing `id` field remains separate from the audit's `event_id`.

The JSON includes `bar_open_ms` and `bar_close_ms` as UTC Unix milliseconds. History rows show the event close in New York time. Use the complete timestamp from a tooltip or JSON when reporting an issue; a panel row abbreviates the date and ID.

## Recorded events

| Event | Meaning |
|---|---|
| `gap_detected` | A confirmed three-candle gap passed the size and birth displacement filters. Its original boundaries and birth time are saved. A pattern rejected by those birth filters does not create a setup or an event. |
| `inverted` | A later confirmed close passed strictly through the original gap's opposite edge. Equality and wicks alone do not invert it. |
| `retest_rejected` | In retest mode, a later candle overlapped an eligible IFVG but did not produce its directional rejection close. The inversion candle cannot retest itself. |
| `entry_accepted` | The trigger, required gates and risk checks passed and this setup won selection by newest inversion, then newest birth. Its candidate plan is the accepted paper plan. |
| `entry_skipped` | An entry trigger was observed but an active paper plan, daily cap, same-bar exit, gate, risk check or competing winner prevented entry. The saved reason and detail explain the decision. |
| `invalidated` | An armed IFVG closed strictly through its invalidating edge and became ineligible. |
| `expired` | An active retained zone exceeded the configured maximum age in chart bars. |
| `evicted` | A zone was removed at the retained-zone capacity. This differs from age expiry; an already-open paper plan continues independently. |
| `paper_resolved` | The paper plan ended at its stop, target, timeout or optional session close. Its detail contains the fixed entry plan, exit price, R result and exit-condition flags. |

An overlap without rejection is recorded only while the IFVG remains eligible; a bar that invalidates or expires it records that terminal event. Non-overlapping retest bars and ordinary waiting bars are not logged. This is a decision history, not an OHLC feed or a transcript of every bar.

## What is frozen

Audit events are created only on confirmed bars and immediately serialized. Their stored strings and primitive fields do not reference mutable zone objects. Later bars can update the live dashboard and retire the zone without rewriting the saved event within that calculation.

Each event's JSON carries:

- Script/schema version, Setup ID, event ID, kind, reason, symbol, timeframe, timestamps and OHLC.
- Gap bounds, original and intended directions, birth and inversion timestamps, phase and age at the event.
- Selected trigger mode, inversion-on-this-bar, later-than-flip, overlap and directional-rejection flags.
- Observed session, HTF overlap, sweep, SMT availability/divergence, bias and displacement factors.
- Supporting ATR, middle-candle and earlier-bar values, sweep and daily references, synchronized SMT values, and matching aligned HTF gap bounds/source timestamps.
- A risk candidate at that event's close, including stop, target, distance, quantity and validity; event-specific details add state changes, entry blockers/winner or paper resolution.

The header stores the shared engine settings for the calculation, including enabled gates, input and resolved context frames, sessions, risk rules and audit capacity. Factor truth and gate enablement are separate: an optional factor can fail without blocking entry.

`candidate_plan` describes the hypothetical plan calculated on that event bar. On a later `paper_resolved` event, use `detail` for the original accepted plan and its actual paper result. The resolution bar's candidate is not an amendment to the original stop or target. An `entry_accepted` snapshot is captured at selection, before the zone is marked consumed.

These are **paper-engine events, not broker fills**. They declare `costs_included: false`. Strategy Tester has its own order/fill ledger and Properties; user overrides to commission, slippage or other broker assumptions must be supplied separately.

## Browse and retain

Under **06 · Setup audit trail**, keep **Record setup history** enabled. Under **Audit · setup history**, enable **Show setup history**. The separate panel starts at Bottom Left and avoids occupied visible dashboard/narrative positions. It shows eight events per page in newest-first order. Page numbers beyond the available matches clamp to the last page.

Hover a row for its full ID, unabridged reason, snapshot summary and JSON. Paste the exact full ID into **Setup ID filter · blank = all** to follow one setup; a shortened displayed ID will not match. The filter affects the panel and report only. All setups still record and compete for entries normally.

The event journal is a **global rolling cap**, default 300, minimum 50, maximum 500. Once full, each new event removes the oldest event across all setups and increments the removed-record count. The footer shows retained capacity and older records removed. A filtered setup may therefore start at inversion, entry or resolution because earlier events were dropped. The filter does not reserve capacity, and retained-zone capacity is a separate engine limit.

Immutable within a run does not mean persistent across runs. Reloading the script, changing inputs or chart context, or recalculating against changed/extended data rebuilds history from the loaded bars and settings. Save diagnostic text before changing the reproduction. A higher event cap can retain more during a new calculation but cannot recover data absent from the loaded chart.

## Export a bug report

Use an editable personal copy in Pine Editor. TradingView permits Pine Logs for personal scripts; published scripts cannot generate them. Open the pane through Pine Editor's More menu. [TradingView's debugging documentation](https://www.tradingview.com/pine-script-docs/writing/debugging/) describes this restriction and access path.

Enable **Write bug report to Pine Logs** with recording on. At the last confirmed historical bar, the script writes a report header with settings and retention context, followed by the retained events matching the filter in chronological order. On an open market this historical boundary precedes the live candle; on a closed market it is the last historical candle. Subsequent matching realtime events append when their bars confirm.

The header uses schema `ifvg-desk.report.v1`; event lines use `ifvg-desk.audit.v1`. Header fields include dataset start and report-through timestamps, feed/session information, tick and point values, the exact setup filter, retained/matching/dropped counts, oldest retained close, settings and a reminder to attach broker Properties separately. Those counts describe the historical export boundary; later streamed events do not rewrite that earlier header.

Copy the header and relevant event JSON lines into [the bug report template](bug-report-template.md). Retain the JSON's own bar timestamps: the log pane's prefix for a batch-exported line refers to the export execution, not that earlier event's decision time. If copying prefixes too, preserve the original JSON body so its fields remain readable.

Changing the filter or export input triggers recalculation. That rebuilds the header and retained history for the current chart/settings. The option does not save a permanent file, create an alert, send an external message or submit the report for you. Existing entry-alert controls are separate.

## Evidence scope

The [v1.2.0 verification report](verification-v1.2.md) links current compiler responses, runtime probes, a before/after comparison and a [real history-panel capture](screenshots/v1.2.0/setup-history.png). Older screenshot folders and build/display reports document their earlier releases. Saved diagnostics help reproduce a discrepancy; they do not independently prove live/reload equivalence or a trading advantage.
