create-tradejs 3.1.22 → 3.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +19 -3
  2. package/dist/index.js +36 -5
  3. package/dist/skill-bundle/.codex/skills/ai-train-local-research/SKILL.md +596 -0
  4. package/dist/skill-bundle/.codex/skills/ai-train-local-research/references/gate-ablation.md +324 -0
  5. package/dist/skill-bundle/.codex/skills/ai-train-local-research/references/reporting.md +227 -0
  6. package/dist/skill-bundle/.codex/skills/ai-train-local-research/scripts/ai-gate-ablation.mjs +5082 -0
  7. package/dist/skill-bundle/.codex/skills/ai-train-local-research/scripts/ai-gate-ablation.test.mjs +1170 -0
  8. package/dist/skill-bundle/.codex/skills/backtest-config-redis/SKILL.md +17 -0
  9. package/dist/skill-bundle/.codex/skills/backtest-config-redis/scripts/get_backtest_config.sh +21 -0
  10. package/dist/skill-bundle/.codex/skills/runtime-parity-mismatch-analysis/SKILL.md +146 -0
  11. package/dist/skill-bundle/.codex/skills/save-strategy-config-from-backtest/SKILL.md +58 -0
  12. package/dist/skill-bundle/.codex/skills/save-strategy-config-from-backtest/agents/openai.yaml +4 -0
  13. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/SKILL.md +334 -0
  14. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/references/research-notes.md +247 -0
  15. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/backtest-run-metrics.mjs +647 -0
  16. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/backtest-run-metrics.test.mjs +321 -0
  17. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/fast-ai-export-metrics.mjs +744 -0
  18. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/fast-ai-export-metrics.test.mjs +553 -0
  19. package/dist/skill-bundle/.codex/skills/strategy-backtest-research/scripts/research-notes-check.mjs +125 -0
  20. package/dist/skill-bundle/.codex/skills/strategy-improvement-research/SKILL.md +18 -1
  21. package/dist/skill-bundle/.codex/skills/strategy-release/SKILL.md +22 -0
  22. package/dist/skill-bundle/.codex/skills/strategy-release/agents/openai.yaml +4 -0
  23. package/dist/skill-bundle/.codex/skills/strategy-release/references/diagnose-live.md +126 -0
  24. package/dist/skill-bundle/.codex/skills/strategy-release/references/direction-policy.md +141 -0
  25. package/dist/skill-bundle/.codex/skills/strategy-release/references/directional-parameter-split.md +93 -0
  26. package/dist/skill-bundle/.codex/skills/strategy-release/references/evidence-limitations.md +76 -0
  27. package/dist/skill-bundle/.codex/skills/strategy-release/references/evidence-retention.md +157 -0
  28. package/dist/skill-bundle/.codex/skills/strategy-release/references/historical-hypothesis-audit.md +163 -0
  29. package/dist/skill-bundle/.codex/skills/strategy-release/references/professional-research-loop.md +198 -0
  30. package/dist/skill-bundle/.codex/skills/strategy-release/references/release-workflow.md +755 -0
  31. package/dist/skill-bundle/.codex/skills/strategy-release/references/research-objective.md +255 -0
  32. package/dist/skill-bundle/.codex/skills/strategy-release/references/verdict-contract.md +200 -0
  33. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/direction-policy-checkpoint.mjs +137 -0
  34. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/direction-policy-checkpoint.test.mjs +85 -0
  35. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/directional-parameter-checkpoint.mjs +149 -0
  36. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/directional-parameter-checkpoint.test.mjs +120 -0
  37. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/release-progress-checkpoint.mjs +621 -0
  38. package/dist/skill-bundle/.codex/skills/strategy-release/scripts/release-progress-checkpoint.test.mjs +349 -0
  39. package/dist/skill-bundle/.codex/tradejs-skill-bundle.json +44 -3
  40. package/package.json +1 -1
@@ -0,0 +1,755 @@
1
+ # Release workflow
2
+
3
+ ## Contents
4
+
5
+ 1. Freeze the release question
6
+ 2. Revalidate historical candidates
7
+ 3. Freeze cached coverage
8
+ 4. Capture the control
9
+ 5. Run three causal core rounds and rescue
10
+ 6. Select the finalist or side-qualified handoff
11
+ 7. Tune the deterministic gate
12
+ 8. Confirm robustness and issue the verdict
13
+ 9. Persist the chart and choose an action
14
+
15
+ Use this workflow to evaluate one frozen core plus deterministic AI-gate
16
+ composition and, in `release` mode, carry the selected historically promising
17
+ composition into an exact production micro-forward at `MAX_LOSS_VALUE=1`.
18
+ Historical release claims and prospective evidence collection are separate:
19
+ the latter does not require `READY_FOR_RUNTIME`.
20
+
21
+ Before this workflow, complete
22
+ [historical-hypothesis-audit.md](historical-hypothesis-audit.md). Existing
23
+ evidence and untested strategy commits are inputs to hypothesis selection, not
24
+ optional background reading.
25
+
26
+ Then complete the thesis, opportunity map, hypothesis portfolio, and adaptive
27
+ belief updates from
28
+ [professional-research-loop.md](professional-research-loop.md). These artifacts
29
+ make the three families strategy-specific rather than a generic sweep.
30
+ Read and apply [research-objective.md](research-objective.md) before accepting a
31
+ baseline, ranking a prior result, or freezing the new families.
32
+
33
+ ## Environment boundary
34
+
35
+ Historical research, exports, and backtest configs live on the research
36
+ machine. Desired production deployments and complete strategy configs live in
37
+ TradeJS-Project `tradejs.config.ts`. Account credentials, optional pause
38
+ controls, signals, and trades live on the runtime server. Missing local runtime
39
+ records are not evidence that their production counterparts do not exist.
40
+ Never copy credentials into research evidence.
41
+
42
+ The local output is a portable composition handoff. Research fingerprints and
43
+ checksums validate its inputs locally; production identifies the deployed
44
+ package plus parsed complete config by computed `strategyRevision`, while
45
+ `deploymentCompositionId` binds the target and all strategy selections.
46
+ `ACCOUNT_ID` and `DEPLOYMENT_ID` remain binding fields outside the strategy
47
+ config. API credentials are server secrets: never export, hash, or compare them
48
+ as research identity.
49
+ `ENABLE`, `AI_ENABLED`,
50
+ `AI_MODE`, `MIN_AI_QUALITY`, detector/side policy, interval/universe, fees, and
51
+ execution/context semantics remain parity-critical.
52
+
53
+ Do not create a new release manifest when only runtime `MAX_LOSS_VALUE`
54
+ changes. Preserve the deployed release's existing `compositionId`, record the
55
+ new scale as a separate `L` marker, and normalize monetary runtime evidence
56
+ back to the release risk unit; do not reset the composition's logic history.
57
+
58
+ ## 1. Freeze the release question
59
+
60
+ Create a new immutable lineage id for every release task unless the user
61
+ explicitly names one to continue. Prior work is input evidence; it never counts
62
+ as a round, rescue child, or gate round in the new lineage. Preregister:
63
+
64
+ - strategy and current control composition;
65
+ - the `tradejs-release-objective/v2` artifact and its SHA-256 objective
66
+ fingerprint;
67
+ - the global cross-lineage trial ledger and selection-adjusted Sharpe/PBO
68
+ method;
69
+ - separate historical-readiness and prospective risk-1 acceptance rules, plus
70
+ the diagnostic current-market terminal windows;
71
+ - an evidence-limitation classification and claim ceiling from
72
+ [evidence-limitations.md](evidence-limitations.md); never collapse
73
+ retrospective-universe provenance into causal leakage;
74
+ - the trading thesis, opportunity-map SHA, protected edge, dominant loss
75
+ source, cadence bottleneck, and exploit/repair/explore-or-falsify roles;
76
+ - three causally distinct core hypothesis families;
77
+ - the SHA of the complete historical hypothesis inventory, the bridge table for
78
+ every stronger prior result, and the disposition of each untested behavior;
79
+ - the three-round allocation for every family: one anchor candidate in round 1,
80
+ two child candidates in round 2, and two child candidates in round 3;
81
+ - the deterministic post-round-3 rescue rule: seed ranking, cadence-diversity
82
+ rule, one child per seed, and acceptance/stop criteria;
83
+ - the round-1 resolved configs plus the rule that turns prior metric, matching,
84
+ and trace evidence into the two next-round variants;
85
+ - candidate ranking and tie-break rules;
86
+ - non-target-side invariance or occupancy-spillover rule;
87
+ - the one allowed deterministic gate tuning round;
88
+ - `llmComparison: off | ai-approved`;
89
+ - required evidence and terminal conditions.
90
+
91
+ Treat the common control as a separate frozen reference. The first three rounds
92
+ allow five candidate variants per family and 15 total at most. The mandatory
93
+ rescue board may add exactly one child for each of up to three selected seeds,
94
+ for 18 core candidates total at most. Exact round-2, round-3, and rescue configs
95
+ are intentionally not guessed before their parent evidence exists, but each
96
+ must be preregistered in a new immutable child spec before its run. The
97
+ allocation is not a rolling invitation to add nearby thresholds after seeing
98
+ results. Record every attempted, failed, rejected, and retained cell in the same
99
+ trial ledger.
100
+
101
+ ## 2. Revalidate historical candidates under the frozen objective
102
+
103
+ Complete the candidate revalidation contract from
104
+ [research-objective.md](research-objective.md) before freezing novel families.
105
+ Inventory every deduplicated historical core/gate/direction/rescue candidate,
106
+ including partial and untested behavior records.
107
+
108
+ Recompute compatible retained normalized trades under the new objective. Exact
109
+ reruns of already-tested behavior are required only when a candidate could
110
+ reach the new frontier but its window, universe, costs, execution semantics,
111
+ source behavior, or risk unit is not comparable. Metric-only re-scoring and
112
+ exact bridge reruns do not consume the 18 new causal-candidate slots; every
113
+ distinct behavior remains in the global multiple-testing count.
114
+
115
+ Persist `tradejs-release-candidate-revalidation/v2`, hash it, and reference it
116
+ from the opportunity map and every later spec/handoff. Do not continue to round
117
+ 1 while a reconstructable prior candidate lacks a disposition. Revalidation
118
+ does not satisfy the request for a new research lineage: after it, run the new
119
+ causal core portfolio.
120
+
121
+ ## 3. Freeze cached historical coverage
122
+
123
+ Resolve the intersection of cached candle and required causal context coverage
124
+ for the complete ordered ticker universe. Freeze the maximum common half-open
125
+ window `[start, end)` and its proof. Use that same window, universe, connector,
126
+ interval, fees, slippage, entry delay, and context settings for every historical
127
+ control and candidate comparison.
128
+
129
+ Inside that maximum cached envelope, freeze a timestamp-grouped chronological
130
+ core release tail before round 1. Core improvement and rescue rounds may use
131
+ only the development/tuning interval ending before that tail. Commands must not
132
+ print, rank, or otherwise expose tail economics. After rescue freezes the
133
+ finalist, the isolated-long/final comparison opens the tail exactly once and
134
+ evaluates the complete maximum cached window. This preserves an untouched test
135
+ while still using every available candle in the terminal release matrix.
136
+
137
+ Before accepting the current control, bridge every previously strong result to
138
+ this contract. A result from another duration, ticker cohort, cost model, or
139
+ source/config lineage is not directly comparable, but it is also not disposable.
140
+ Rerun its exact causal config under the current frozen dimensions when it
141
+ dominates or materially challenges the baseline. Do not proceed to novel
142
+ hypotheses until the bridge explains why a prior positive strategy result became
143
+ weaker, or reproduces it as a current candidate.
144
+
145
+ An exact bridge rerun of already-tested behavior belongs in the global
146
+ multiple-testing ledger but does not consume a new causal slot. A historical
147
+ mechanism that was implemented but never economically tested is a new behavior
148
+ trial: prefer it as a round-1 anchor or spend a rescue slot. Recomputing the
149
+ exact frozen control or translating metadata does not count as a candidate.
150
+
151
+ Every historical backtest command must include:
152
+
153
+ ```text
154
+ --startTime <frozen-start> --endTime <frozen-end> -t <frozen-ordered-tickers> --cacheOnly
155
+ ```
156
+
157
+ Use `--fast --ai` only as raw completed-core-trade transport when appropriate;
158
+ state that BACKTEST does not apply the AI quality gate. Never refresh data,
159
+ change membership, or fall back to a shorter available subset. If the common
160
+ window is inadequate, return `INSUFFICIENT_EVIDENCE`.
161
+
162
+ For the final composition, the full-statistics matrix is mandatory:
163
+
164
+ - trailing 1095 days (3y);
165
+ - trailing 1460 days (4y);
166
+ - trailing 1825 days (5y), or the exact maximum available cached coverage when
167
+ it is shorter; record both requested and covered days;
168
+ - 365d, 180d, 90d, 30d, and 7d terminal slices.
169
+
170
+ Each row contains ALL/LONG/SHORT N, PnL, PnL/trade, PF, WR, realized MaxDD,
171
+ cadence, independent events, payoff, probabilistic/deflated Sharpe,
172
+ drawdown/tail/recovery, concentration, and terminal support class. Use the
173
+ permanent metrics tooling from
174
+ `$strategy-backtest-research`; do not reconstruct a favorable subset manually.
175
+ When no composition qualifies, the same matrix remains mandatory for the
176
+ authoritative control, best aggregate candidate, best LONG candidate, best
177
+ SHORT candidate, and every rescue child. A failed verdict is not permission to
178
+ replace the tables with a leaderboard or artifact link.
179
+
180
+ Classify every terminal cohort as `underpowered`, `diagnostic`, or
181
+ `selection_grade` using [research-objective.md](research-objective.md). Keep all
182
+ rows visible, but never reject or retune on an underpowered row. A diagnostic
183
+ row may motivate the one supported causal repair. A selection-grade row may
184
+ limit a historical-readiness claim and candidate rank, but no terminal calendar
185
+ row forces a wait or vetoes an otherwise valid risk-1 prospective test.
186
+
187
+ ## 4. Capture the control
188
+
189
+ Run the frozen control as a complete, run-scoped experiment. Export only after
190
+ the manifest finishes and keep chunks. Reconcile Redis N/W/L/PnL against
191
+ completed-trade rows. Report full-window and preregistered terminal metrics for
192
+ `ALL`, `LONG`, and `SHORT`, including zero-trade cohorts.
193
+
194
+ Do not disable a weak side inside the authoritative raw-core result. Record
195
+ separate control statuses for ALL, LONG, and SHORT so the later deterministic
196
+ AI gate can evaluate side cohorts explicitly. An explicit direction-policy
197
+ candidate may later suppress that side while keeping this raw evidence visible.
198
+
199
+ ## 5. Run and analyze three causal core rounds
200
+
201
+ Audit and infrastructure repairs do not count as a core round. If a parity or
202
+ package-boundary defect is discovered, fix and verify it, rebuild the frozen
203
+ control if necessary, then continue from round 1. Do not present the bug fix as
204
+ the strategy-improvement result.
205
+
206
+ Run every release-core candidate with `--researchTrace`. The compact trace is
207
+ required here because each later round must be derived from observed
208
+ setup/entry/skip transitions, not from a PnL leaderboard. Preserve each
209
+ `configId`; never combine cells into one result. Use isolated cells when the
210
+ strategy's state identity does not prove grid isolation.
211
+
212
+ Use one immutable `stage=screen` research lineage per family and round:
213
+
214
+ 1. **Round 1 — mechanism anchors.** Compare the original frozen control with
215
+ one distinct anchor candidate for each of the three causal families.
216
+ 2. **Round 2 — evidence-driven alternatives.** For every still-viable family,
217
+ carry its round-1 winner as the exact matched control and freeze two child
218
+ candidates: one intervention addressing the primary diagnosed failure and
219
+ one alternative/ablation that can falsify the explanation.
220
+ 3. **Round 3 — refinement plus robustness.** Carry the round-2 winner as the
221
+ exact control and freeze two new child candidates from the combined prior
222
+ evidence: one refinement of the supported mechanism and one robustness
223
+ variant targeting its remaining side/regime/cost/occupancy weakness.
224
+
225
+ Every round-2/round-3 screen spec must use a new `researchId`, name its direct
226
+ `parentResearchIds` both at the spec root and in lineage, keep the same
227
+ hypothesis family, and state the exact parent metric/trace observation that
228
+ motivates each config delta. Run `prepare`, regenerate `research:core index`
229
+ before execution to validate the parent/family chain, then `run`, `verify`, and
230
+ regenerate the index after completion.
231
+
232
+ After **each** round, complete this analysis before writing a child spec:
233
+
234
+ 1. Verify manifest/checkpoint completeness, run-scoped export hashes,
235
+ reconciliation, duplicate/conflict counts, and trace coverage.
236
+ 2. Report fixed ALL/LONG/SHORT N, PnL, PnL/trade, PF, WR, realized MaxDD,
237
+ independent events, cadence, payoff, non-IID-aware probabilistic/deflated
238
+ Sharpe, tail/CVaR, recovery/time-under-water, concentration, and support
239
+ class for the round window, terminal development slices, folds, and months;
240
+ include holding time, loss/month streaks, and equity/DD curves as risk
241
+ diagnostics rather than optimization targets.
242
+ 3. Match stable setup/trade identities and report matched, control-only,
243
+ candidate-only, changed-outcome, and occupancy-spillover cohorts by side.
244
+ 4. Compare the compact trace funnel across signal emission or entry rejection,
245
+ execution, exit, and per-test skip summaries; use deterministic setup
246
+ identities from completed rows for pre-entry matching. Attribute top skip
247
+ deltas and verify the candidate changed the intended transition rather than
248
+ an unrelated lifecycle.
249
+ 5. Break deltas down by causal signal-time regime, symbol/concentration,
250
+ direction, time fold, and cost stress. Review calendar-cluster bootstrap,
251
+ family-aware Holm, DSR/PBO, and no-op/reset contamination warnings.
252
+ 6. Write a causal mechanism verdict — `supported`, `falsified`, or
253
+ `inconclusive` — plus the predicted versus observed trace/metric effect and
254
+ the exact reason each family continues or retires.
255
+
256
+ If a matched one-field comparison has an opposing supported LONG/SHORT effect,
257
+ run `directional-parameter-checkpoint.mjs` before freezing the next children.
258
+ Follow [directional-parameter-split.md](directional-parameter-split.md). A
259
+ target-only override or required detector-state isolation consumes the normal
260
+ child/rescue budget; it does not grant extra trials. Preserve the global field
261
+ as the exact legacy fallback and audit non-target identity or occupancy
262
+ spillover.
263
+
264
+ Persist that conclusion as the round's immutable causal handoff. At minimum it
265
+ contains this machine-readable payload alongside the normal research note:
266
+
267
+ ```json
268
+ {
269
+ "round": 1,
270
+ "researchId": "<immutable id>",
271
+ "parentResearchIds": [],
272
+ "controlVariantId": "<id>",
273
+ "candidateVariantIds": ["<id>"],
274
+ "resultSha256": "<sha256>",
275
+ "traceCoverage": "complete",
276
+ "mechanismVerdict": "supported|falsified|inconclusive",
277
+ "predictedEffect": "<frozen before run>",
278
+ "observedEffect": "<metrics + identities + trace transition>",
279
+ "failureMode": "<remaining causal weakness or null>",
280
+ "familyDecision": "continue|retire|nominate_for_rescue",
281
+ "nextVariants": [
282
+ {
283
+ "role": "primary_fix|falsification|refinement|robustness",
284
+ "configDelta": {},
285
+ "causalClaim": "<why this follows from the parent>",
286
+ "predictedTraceEffect": "<event/skip conversion>",
287
+ "predictedMetricEffect": "<target and guardrails>"
288
+ }
289
+ ]
290
+ }
291
+ ```
292
+
293
+ Round 1 uses one candidate per family and therefore records two frozen
294
+ `nextVariants` when the family continues. Round 2 also records two. Round 3
295
+ records no same-family refinement children; it records only
296
+ `nominate_for_rescue` or `retire`. The cross-family rescue board, not an
297
+ individual round-3 family, chooses the next children and the eventual isolated
298
+ finalist. Hash the payload and cite it in the child research note/spec lineage
299
+ so another Codex run can reconstruct why the child exists without reading an
300
+ informal narrative.
301
+
302
+ Do not derive a child from displayed losers, outcome fields, or the sealed core
303
+ release tail. Do not create “best value ± epsilon” variants without a causal
304
+ transition hypothesis. Complete rounds 2 and 3 for every still-viable family
305
+ even when an earlier candidate is already profitable. A family may retire
306
+ early only when immutable evidence is invalid, the intervention is a no-op,
307
+ the mechanism is falsified, required causal signal-time context is unavailable, or
308
+ no causal signal remains to test. If all families retire, continue to the
309
+ rescue-board decision rather than manufacturing variants or stopping early.
310
+
311
+ Missing effective-dated exchange membership is not the same as missing causal
312
+ signal-time context. Keep the identical retrospective current cohort for
313
+ control/candidate matching, run membership-age/incumbent sensitivity where the
314
+ cache supports it, cap the claim at `micro_forward_only`, and continue. Do not
315
+ retune the symbol cohort after seeing candidate economics.
316
+
317
+ The carried control is the best **eligible** parent under the frozen rule. A
318
+ failed candidate is never relabelled a winner: if its trace supports another
319
+ causal test but its economics fail, retain the preceding control and record the
320
+ failed candidate only as diagnostic parent evidence for the two child variants.
321
+
322
+ When a direction-targeted policy is architecturally isolated, require exact
323
+ non-target identities/N and PnL equality within documented rounding. When
324
+ position occupancy, cooldown, or order lifecycle can affect the opposite side,
325
+ measure added/removed identities and require the preregistered non-regression
326
+ rule instead.
327
+
328
+ ### Mandatory post-round-3 core rescue board
329
+
330
+ Build this board even when no candidate passed the frozen economic rule. Use
331
+ only complete, reconciled, non-no-op development evidence; keep the release tail
332
+ sealed.
333
+
334
+ 1. Build the Pareto frontier from the frozen objective across out-of-sample
335
+ expectancy/risk, PF/payoff, deflated Sharpe, realized MaxDD/tail/recovery,
336
+ walk-forward stability, support, cost stress, Holm-adjusted evidence,
337
+ concentration, and cadence. Do not rank on terminal pass count when a cohort
338
+ is underpowered or diagnostic.
339
+ 2. Select up to three diagnostic seeds while maximizing cadence separation.
340
+ Prefer one seed from each observed cadence tercile; if a tercile is empty,
341
+ fill the slot with the candidate farthest in cadence from already selected
342
+ seeds. For direction-targeted families, form cadence regions from the target
343
+ side and keep ALL cadence as an aggregate guardrail; for whole-strategy
344
+ families, use ALL cadence. When fewer than three valid seeds exist, record why
345
+ every missing slot is impossible.
346
+ 3. For each seed, identify one dominant causal failure using trade identities,
347
+ matched/added/removed outcomes, occupancy, trace skips/conversions, side,
348
+ regime, fold/month, concentration, payoff tail, and cost stress.
349
+ 4. Freeze exactly one rescue child per seed. The child must address that failure
350
+ through a new causal transition or payoff mechanism and state its predicted
351
+ trace and metric effect. An adjacent threshold nudge is invalid unless a
352
+ measured discontinuity makes that threshold causal.
353
+ 5. Run each child against the original frozen authoritative control. Use the
354
+ seed's prior artifact as a diagnostic comparator, not as an eligible carried
355
+ control unless the seed already passed the frozen rule.
356
+
357
+ The rescue board is bounded to three new variants and raises the lineage cap to 18. It is not a fourth unconstrained search round. After its analysis, select a
358
+ finalist only if it passes the original frozen rule. `STOP_RESEARCH` is allowed
359
+ only when all rescue slots have completed or are impossible for recorded hard
360
+ reasons and the historical inventory contains no stronger unbridged result that
361
+ could occupy a slot. A remaining reconstructable historical backlog after the
362
+ 18-variant cap yields incomplete evidence, not a claim that no strategy edge
363
+ exists.
364
+
365
+ Here, `valid seed` means only complete, reconciled, behavior-changing, and
366
+ non-no-op. It does **not** mean release-eligible. Low support/cadence, failed
367
+ Holm, negative terminals, or negative PnL are measured rescue failure modes,
368
+ not reasons to leave a slot empty. A slot may be impossible only when there is
369
+ no such candidate in a distinct cadence region or no causal point-in-time child
370
+ can address its diagnosed failure.
371
+
372
+ Decision regression: suppose one dense candidate has 244 target-side trades but
373
+ negative PnL/PF, one sparse candidate has 80 target-side trades and positive
374
+ PnL/PF but fails support/terminals/Holm, and a prior higher-cadence positive
375
+ configuration was tested on a different universe. The correct action is not
376
+ `STOP_RESEARCH`. Put the dense and sparse candidates on the diagnostic frontier,
377
+ bridge the prior configuration to the frozen contract, choose up to three
378
+ cadence-diverse seeds, and spend one causal rescue child per selected seed. Only
379
+ the children that pass the original rule can become finalists.
380
+
381
+ ### Mandatory direction-policy checkpoint
382
+
383
+ After the rescue board, read and apply
384
+ [direction-policy.md](direction-policy.md). Do this before concluding that no
385
+ composition finalist exists.
386
+
387
+ If one raw side passes the preregistered useful-side rule while the other side
388
+ is the dominant aggregate loss, nominate the best complete side-qualified core
389
+ handoff even when raw ALL failed. The handoff is not an eligible raw-core winner
390
+ and must remain labelled as such; it exists so the single gate round can test
391
+ whether an explicit direction policy salvages the composition. The same rule
392
+ applies when the current gate hides a useful raw side.
393
+
394
+ Persist the checkpoint for all three outcomes:
395
+
396
+ - `losing_side_contamination`;
397
+ - `profitable_side_hidden`;
398
+ - `no_side_salvage`.
399
+
400
+ Neither `UNSUITABLE_FOR_CURRENT_MARKET` nor `STOP_RESEARCH` is valid while a
401
+ triggered checkpoint is absent. A useful retained side that later fails
402
+ terminal or cost rules is a legitimate rejection; skipping its policy test is
403
+ not.
404
+
405
+ ## 6. Select one isolated-long finalist or side-qualified handoff
406
+
407
+ After the rescue board and direction-policy checkpoint, select at most one raw
408
+ core finalist across all families using the frozen rule. When none qualifies,
409
+ the checkpoint may instead select at most one complete side-qualified handoff
410
+ whose useful side passed the frozen useful-side rule. Do not relabel it a core
411
+ winner. If neither exists, use the authoritative control as the diagnostic
412
+ handoff so the required full report and chart still have an exact lineage.
413
+
414
+ Rerun the chosen cell alone over the complete maximum common cached window and
415
+ frozen universe, opening the chronological core release tail for the first and
416
+ only time. This is the only isolated-long/handoff run allowed in the lineage.
417
+
418
+ Require complete run/export reconciliation and agreement with the screened
419
+ cell within the preregistered reset/grid tolerance. Investigate any difference
420
+ as state/reset contamination; do not choose the more favorable run.
421
+
422
+ The isolated-long result may confirm or reject the frozen finalist or quantify
423
+ the side-qualified handoff. It may not generate a fourth core-improvement
424
+ round. Any new hypothesis after the tail is opened starts a new release lineage
425
+ with a future unexposed tail.
426
+
427
+ ## 7. Use one gate tuning round
428
+
429
+ Freeze the isolated finalist's raw-core export and the current deterministic
430
+ gate as control. Use one time-grouped, time-ordered train/tuning/test design.
431
+ Audit existing gate rules, run pocket discovery/ablation without outcome or
432
+ execution leakage, and preregister rounded thresholds before opening the test.
433
+ `ai-pocket-search` must reserve the test with `--sealTest`; its discovery report
434
+ may contain only sealed test counts/bounds, never test economics. Store the
435
+ complete five-variant spec before the fixed ablation opens that tail once.
436
+
437
+ Select one deterministic gate candidate, or retain the frozen current gate if
438
+ no candidate passes. Do not perform a second search after viewing the held-out
439
+ test. The release unit is then exactly one core snapshot plus one deterministic
440
+ gate fingerprint.
441
+
442
+ ### Mandatory side recovery and containment checkpoint
443
+
444
+ Before freezing the five gate variants, build this coverage table for raw core
445
+ and current qN+ approvals in every full/terminal window:
446
+
447
+ ```text
448
+ ALL/LONG/SHORT: raw N, PnL, PnL/trade, PF, WR, MaxDD, cadence
449
+ ALL/LONG/SHORT: gate-approved N, approval share, same economics
450
+ ```
451
+
452
+ A side requires recovery analysis when its raw cohort is positive or passes the
453
+ preregistered side edge rule while the current gate approves zero/negligible
454
+ support, or when removing that side materially destroys aggregate edge. A side
455
+ requires containment analysis when it is the dominant loss while the opposite
456
+ raw side passes the useful-side rule. Do not call the strategy unsuitable
457
+ merely because the current gate discarded a useful side or because raw ALL
458
+ mixed it with a losing side.
459
+
460
+ For recovery, freeze exactly five gate variants before looking at tuning/test
461
+ outcomes:
462
+
463
+ 1. current deterministic gate control;
464
+ 2. current gate plus raw pass-through for the target side;
465
+ 3. current gate plus one rounded causal target-side pocket found on train only;
466
+ 4. current gate plus the target-side pocket and one preregistered protective
467
+ exclusion;
468
+ 5. direction-aware replacement: best preregistered policy per side, including
469
+ raw pass-through where it is the frozen candidate.
470
+
471
+ For containment, use the five variants and semantics frozen in
472
+ [direction-policy.md](direction-policy.md): current gate, failing-side hard
473
+ block, retained-side pass-through plus block, causal failing-side repair, and
474
+ direction-aware replacement. Prefer the explicit gate block over mutating the
475
+ raw core side toggle. If a core-toggle equivalence candidate is tested, keep it
476
+ separate and require entry-identity equivalence.
477
+
478
+ Use the permanent direction-aware ablation syntax rather than a proxy feature:
479
+
480
+ ```text
481
+ short-pass-through::add@4[SHORT]::true
482
+ short-pocket::add@4[SHORT]::<rounded causal expression>
483
+ direction-aware::replace@4::(derived.direction == LONG && <long rule>) || (derived.direction == SHORT && <short rule>)
484
+ ```
485
+
486
+ Run pocket discovery separately for `LONG` and `SHORT`. Select variants using
487
+ train and tuning only, then open the one chronological test tail once. Require:
488
+
489
+ - no outcome/execution leakage;
490
+ - minimum independent events and cadence in the target side;
491
+ - target-side PnL and PnL/trade improvement with PF/WR/MaxDD guardrails;
492
+ - explicit aggregate portfolio guardrails;
493
+ - explicit non-target identity or occupancy-spillover comparison;
494
+ - full/180d/90d/30d/7d tables, retaining zero rows.
495
+
496
+ Apply the terminal support classes independently to ALL/LONG/SHORT. A sparse
497
+ negative or empty window is not a gate failure; compare its cadence with the
498
+ frozen event-arrival distribution and retain it as `n/a`. Do not wait for it to
499
+ reach selection-grade support before starting the risk-1 prospective test.
500
+
501
+ If the sealed test was opened during discovery, intentionally or by an older
502
+ tool version, it is exposed forever for that lineage. Finish and record the
503
+ fixed comparison as diagnostic evidence, but do not retune on it, relabel it as
504
+ untouched, or use it to justify `READY_FOR_RUNTIME`. The candidate may enter a
505
+ new post-cutoff forward incubation lineage.
506
+
507
+ ### One bounded recent-direction repair
508
+
509
+ After the one gate round, a failing terminal direction may receive exactly one
510
+ repair round only when all are true:
511
+
512
+ - the failed window is at least `diagnostic` with 20 independent target-side
513
+ closed events;
514
+ - a causal signal-time mechanism was preregistered from train/tuning and regime
515
+ diagnostics, not inferred by filtering the displayed losers;
516
+ - the evaluation tail was not exposed;
517
+ - no earlier terminal repair round was used.
518
+
519
+ Freeze five repair variants and preserve non-target/aggregate guardrails. When
520
+ support is below 20, the tail is exposed, or the mechanism is unknown, do not
521
+ fit another condition. A four-trade SHORT loss or a zero-trade 7d window is a
522
+ forward-monitoring/cadence question, not a new threshold or a rejection.
523
+ Preserve the profitable long-window side and proceed to the post-verdict action.
524
+
525
+ Raw pass-through is a candidate, never an automatic promotion. If it wins the
526
+ historical comparison but the terminal tail was exposed, retain it as one
527
+ immutable forward candidate. A selection-grade frozen terminal failure may
528
+ prevent `READY_FOR_RUNTIME` and lower the candidate rank, but does not by itself
529
+ prevent the exact risk-1 forward handoff. Never use a zero-approval side as a
530
+ silent substitute for completing this checkpoint.
531
+
532
+ If `llmComparison=ai-approved`, compare LLM output only on rows approved by the
533
+ final deterministic gate. Record provider/model/prompt lineage and cost. Treat
534
+ the comparison as advisory; never use it to tune, approve, reject, or promote
535
+ the composition.
536
+
537
+ ## 8. Confirm robustness and issue the verdict
538
+
539
+ Report the final composition on the frozen full window and required terminal
540
+ windows, plus standalone cold-start/reset checks when the strategy is stateful.
541
+ Keep continuous-run terminal slices distinct from standalone horizons. When no
542
+ composition qualifies, report the authoritative control and best
543
+ aggregate/LONG/SHORT/direction-policy attempts with the same matrix before
544
+ issuing a negative verdict.
545
+
546
+ Then apply the complete chat/report contract from
547
+ `$ai-train-local-research/references/reporting.md`: outcome/tail risk, cadence
548
+ and fan-out, risk-adjusted metrics, quality and direction, runtime execution
549
+ bridge, validation, acceptance checks, reject reasons, and conclusion. Use
550
+ explicit `n/a` values for unavailable fields; do not omit the sections because
551
+ the composition was rejected.
552
+
553
+ Apply [verdict-contract.md](verdict-contract.md). Write the immutable evidence
554
+ bundle before returning the verdict. The verdict classifies historical
555
+ evidence. In `release` mode, the invocation separately authorizes the selected
556
+ composition's exact `MAX_LOSS_VALUE=1` rollout unless the request explicitly
557
+ forbids runtime changes.
558
+
559
+ Before creating the release manifest, generate the finalist monitoring profile
560
+ from its normalized `trades.jsonl`. Freeze daily-stepped equal-length historical
561
+ drawdown envelopes for the prospective diagnostic horizons, the minimum closed-
562
+ trade sample, minimum runtime parity ratio, maximum order-failure rate, raw-core
563
+ expectancy, gate expectancy, and overfit estimate. Do not calculate these bounds
564
+ from the later live sample. Also freeze the minimum causal-regime coverage needed
565
+ to attribute a breached envelope.
566
+
567
+ Reference core, gate, runtime-parity, and execution-calibration artifacts in a
568
+ release draft with their expected SHA-256 checksums. `strategy:release create`
569
+ reads, hashes, validates, and derives release gate assertions from the files
570
+ itself; draft `verified` and gate booleans are never trusted as authority.
571
+ Reconciled final core evidence, complete robustness, support-conditioned
572
+ deterministic-gate terminal evidence, exact parity, and measured execution
573
+ residual are mandatory for `READY_FOR_RUNTIME`.
574
+ The core evidence reference must point to `result.json` inside its completed
575
+ core-research bundle. Release verification rehashes every artifact named by the
576
+ adjacent completed manifest; an isolated result JSON is not release evidence.
577
+ The draft freezes separate canonical core-config and core-export SHA-256 values,
578
+ deterministic-gate config/context fingerprints, and effective runtime
579
+ config/context fingerprints. The command derives these identities from the
580
+ evidence and rejects any cross-lineage artifact; do not copy one fingerprint
581
+ into another field merely because both describe the same conceptual strategy.
582
+ Incomplete evidence must produce `INSUFFICIENT_EVIDENCE`, even when the partial
583
+ economics look unsuitable.
584
+
585
+ Before deciding, persist `tradejs-release-selected-composition/v2` with the
586
+ strategy, lineage id, candidate id, composition fingerprint, objective
587
+ fingerprint, historical-matrix hash, chart hash, and gate/core fingerprints.
588
+ The final progress artifact, selected-composition artifact, chart, and
589
+ `strategy-release decide` input must name the same candidate and composition.
590
+ Any mismatch is incomplete evidence, never a reason to decide against a
591
+ different control.
592
+
593
+ ## 9. Persist the full-period chart and choose an action
594
+
595
+ The last research computation is mandatory and uses the exact final gate over
596
+ the full frozen export. If no gate candidate qualifies, use the frozen current
597
+ gate over the authoritative control or selected side-qualified handoff and
598
+ label the output `diagnostic-only`; the command and full report are still
599
+ required:
600
+
601
+ ```bash
602
+ yarn ai-train --strategy <Strategy> --file <merged-export-part1.jsonl> \
603
+ --localOnly --chart --json --output <full-period-ai-train.json> \
604
+ -n 0 --minQuality 4 --directionPolicy <policy> \
605
+ --terminalWindows=1460,1095,365,180,90,30,7
606
+ ```
607
+
608
+ The command must scan the full dataset (`-n 0`), persist the UI chart snapshot,
609
+ and write structured output. Record the dataset/export SHA, gate/context
610
+ fingerprints, selected time bounds, output SHA, and chart persistence result in
611
+ immutable evidence. A chart from another gate/config lineage is not acceptable.
612
+
613
+ Then write the final historical/forward decision input and run:
614
+
615
+ ```bash
616
+ yarn strategy:release decide --input <decision-input.json> \
617
+ --out <decision.json>
618
+ ```
619
+
620
+ Reference the progress decision as `progressArtifact`, the selected candidate
621
+ as `selectedCompositionArtifact`, and the report as `chartArtifact`, each with
622
+ `{ path, sha256 }`. The command hashes and parses those exact files, requires a
623
+ v2 completed progress decision, verifies the same strategy/objective/candidate/
624
+ composition/chart lineage, and requires a persisted chart, zero evaluation
625
+ errors, `local-deterministic` mode, `recent=0`, no explicit date narrowing, and
626
+ a non-empty full-export scan. Never copy a plausible hash into the input
627
+ without the file. Likewise, `forwardTest.runtimeTarget` is
628
+ either null or the exact `{ userName, deploymentId, accountId, strategyName,
629
+ strategyRevision, deploymentCompositionId }`; do not substitute a
630
+ self-declared “resolved” boolean.
631
+ Null on the research machine yields `MICRO_FORWARD_READY` with
632
+ `requiresRuntimeBinding=true`, not failed evidence. Commit the secret-free
633
+ handoff and deployment/account binding in Project, validate its computed
634
+ revisions, deploy that image, then rerun `decide` against it.
635
+
636
+ For a normal `release` invocation set `forwardTest.authorized=true` and
637
+ `maxLossValue=1`; use `authorized=false` only for an explicitly research-only or
638
+ no-runtime request.
639
+
640
+ Case handling is deterministic:
641
+
642
+ 1. Positive maximum-covered aggregate expectancy plus every active approved
643
+ side under the frozen objective, robust walk-forward/risk/cost evidence,
644
+ long-window context present, an explicit zero row for any policy-suppressed
645
+ side, candidate implemented, chart present: micro-forward at risk 1.
646
+ Nested long windows and recent calendar rows remain diagnostics and cannot
647
+ turn this into `STOP_RESEARCH` by themselves.
648
+ 2. Supported causal recent direction failure with an untouched tail: one repair
649
+ round, then rerun the full matrix and chart.
650
+ 3. Profitable raw side hidden by the current gate: complete the five side-rescue
651
+ variants; pass-through is allowed but must pass chronological guardrails.
652
+ 4. Useful raw side mixed with a losing side: complete the five direction-policy
653
+ variants. The losing raw side stays visible, while a tested `long_only` or
654
+ `short_only` gate may become the composition policy if the retained side and
655
+ aggregate approved stream pass every guardrail.
656
+ 5. Positive aggregate hiding a failed active side: do not hide the side; repair
657
+ it or test an explicit direction policy. Recent side evidence affects the
658
+ historical claim and ranking according to support, not permission to collect
659
+ prospective evidence for the final active-side composition.
660
+ 6. Incomplete 3y/4y/max coverage, reconciliation, chart, or implementation:
661
+ return the explicit blocker rather than “wait”. A server-owned target that
662
+ is unavailable locally produces a ready handoff, not a blocker.
663
+ 7. Risk-only changes: keep the same logic lineage and add immutable loss-scale
664
+ evidence; never discard earlier logic history.
665
+
666
+ For `MICRO_FORWARD_READY` in normal `release` mode, commit and push every
667
+ strategy-owned source/gate change for the exact candidate, wait for its verified
668
+ beta and protected stable promotion, then update the exact dependency and
669
+ lockfile in TradeJS-Project. In that same Project commit, materialize the full
670
+ candidate config, remove mode/secret fields, retain `MAX_LOSS_VALUE=1`, and run
671
+ strict Project checks to compute `strategyRevision` and
672
+ `deploymentCompositionId`. Run `yarn runtime-control verify` and dry-run
673
+ `signals`, then push the source commit. Explicitly dispatch the SHA-tagged image
674
+ publication as part of the authorized release-mode rollout. Keep unrelated
675
+ changes out of both commits.
676
+
677
+ Do not return at `MICRO_FORWARD_READY`, request another approval message, or
678
+ wait for a 7d/30d/180d result. Bind the exact Git-owned runtime target, complete
679
+ the rollout, and rerun `decide` for `START_MICRO_FORWARD`. Only an explicit
680
+ research-only/no-runtime request changes this into a portable handoff.
681
+
682
+ Production Redis is not a rollout phase and must never receive strategy config,
683
+ deployment documents, or version pointers. For an existing strategy, an
684
+ optional manual pause may guard the image replacement; after verifying
685
+ `/app/runtime-package-manifest.json`, `runtime-control inspect`, `decide`, and a
686
+ dry-run, resume entries after `START_MICRO_FORWARD`. Resume removes the override.
687
+ A newly declared enabled strategy starts with the deployed image. Do not
688
+ increase risk, change unrelated strategy declarations, or manually place
689
+ orders. Runtime records and UI use computed `strategyRevision` and
690
+ `deploymentCompositionId`; research artifacts keep their own internal checksums
691
+ but are not a production server/UI dependency.
692
+
693
+ ## Command shapes
694
+
695
+ Use exact project commands and record the resolved versions:
696
+
697
+ ```bash
698
+ yarn backtest -c <Config> --ai --startTime <start-ms> --endTime <end-ms> \
699
+ -t "$FROZEN_TICKERS" --cacheOnly --fast -p <safe-parallelism> -g 1000
700
+
701
+ yarn ai-export --strategy <Strategy> --runId <completed-run-id> --keepChunks
702
+
703
+ yarn node -r dotenv/config \
704
+ .codex/skills/strategy-backtest-research/scripts/fast-ai-export-metrics.mjs \
705
+ --file <merged-export.jsonl> --run <completed-run-id> --json
706
+
707
+ yarn ai-train --strategy <Strategy> --file <merged-export-part1.jsonl> \
708
+ --localOnly --chart --json --output <full-period-ai-train.json> -n 0 \
709
+ --directionPolicy <both|long_only|short_only|direction_aware> \
710
+ --terminalWindows=1460,1095,365,180,90,30,7
711
+
712
+ yarn ai-pocket-search --strategy <Strategy> \
713
+ --file <merged-export-part1.jsonl> -n 0 --validationSplit 0.2 \
714
+ --testSplit 0.2 --sealTest --maxDepth 2 --minSupport 25
715
+
716
+ yarn strategy:release profile --input <trades.jsonl> --variant <finalist-id> \
717
+ --startTime <start-ms> --endTime <end-ms> --days 7,30,90 \
718
+ --out <monitoring-profile.json>
719
+
720
+ yarn strategy:release create --input <release-draft.json> \
721
+ --root data/strategy-release
722
+
723
+ yarn strategy:release verify \
724
+ --input data/strategy-release/releases/<Strategy>/<release-id>.json
725
+
726
+ yarn strategy:release decide --input <decision-input.json> \
727
+ --out <decision.json>
728
+
729
+ # Local forward-test preparation after explicit user authorization.
730
+ git -C <strategy-source-root> status --short
731
+ git -C <strategy-source-root> add <strategy-owned-candidate-files>
732
+ git -C <strategy-source-root> commit -m "<strategy>: prepare micro-forward candidate"
733
+ git -C <strategy-source-root> push
734
+ # Beta and stable releases are published by protected workflows.
735
+
736
+ npm view <strategy-package>@beta version
737
+ npm view <strategy-package>@latest version
738
+ git -C <TradeJS-Project> add package.json yarn.lock tradejs.config.ts
739
+ git -C <TradeJS-Project> commit -m "Update <Strategy> runtime package"
740
+ git -C <TradeJS-Project> push
741
+ yarn runtime-control verify --user <user> --deployment <deploymentId>
742
+ yarn signals --user <user> --deployment <deploymentId> --timeframe <interval> \
743
+ --skipScreenshots --showSkipStats
744
+
745
+ # Optional guarded cutover for an already declared strategy.
746
+ yarn runtime-control pause --user <user> --strategy <Strategy> \
747
+ --deployment <deploymentId>
748
+ yarn runtime-control inspect --user <user> --deployment <deploymentId>
749
+ yarn runtime-control resume --user <user> --strategy <Strategy> \
750
+ --deployment <deploymentId>
751
+ ```
752
+
753
+ Use `ai-gate-ablation.mjs` for the fixed gate candidate and its held-out
754
+ comparison. Do not use temporary parsers when permanent research tooling covers
755
+ the analysis.