ICT Engine Maintenance Loop
Core rule
Every ict-engine commit, completed factor-training run, gate-schema change, or runtime-field behavior change must ask: did this run teach a durable reusable lesson or invalidate existing skill wording? If yes, update the right skill/reference before or in the same commit. If no, record why in the final evidence.
For training work specifically: every time factor training, factor-research, factor-autoresearch, mutation scoring, provider-backed Auto-Quant, or CatBoost/path-ranking work leaves reusable experience, that experience must be landed in a skill/reference. Do not leave it only in chat, terminal scrollback, or throwaway run artifacts.
For gate/readback work specifically: if code removes, renames, demotes, or marks a field non-blocking, patch every active skill that treats that field as a hard gate before using the old language again. Historical references may keep old artifact values, but active SKILL.md rules must describe the current source/schema contract.
Use this for provider readiness, shell/Python path repairs, TradingViewRemix/TVR, IBKR, Hubble, Kraken/yfinance provider matrix, repo hygiene, routing, and commit discipline.
Commit gate
For public release mirror README-only syncs, use references/release-mirror-readme-only-sync.md: identify the mirror repo, apply the upstream README patch only, prove byte-for-byte parity, handle non-fast-forward by shallow fetch + rebase, push main, and do not touch tags or the dirty development worktree.
Before git commit in ~/projects-ict-engine/ict-engine:
- Run
git status --short; do not stage unrelated agent work. - If inheriting abandoned multi-agent Board A/B work, follow
references/board-ab-handoff-audit.mdbefore staging. - For large evidence trees and multi-agent residue, follow
references/commit-slice-hygiene.md: stage by explicit path, prove excluded run trees are not staged, and preserve unrelated untracked work. - Identify the durable lesson:
- provider/runtime repair -> this skill or
ict-engine-runtimereference - factor/regime pipeline pitfall ->
ict-engine-runtimereference - factor-training / mutation / autoresearch lesson ->
ict-engi-fact-rese-mutaor its reference - routing trigger miss -> router + index
- gate/readback field drift -> active
SKILL.mdwording plus any referenced current-gate docs - Hermes skill/routing governance ->
skill-routing-gov
- provider/runtime repair -> this skill or
- Patch the skill first when the lesson will recur or when a code/schema change makes old skill wording stale.
- Add Chinese trigger keywords and index entries when future routing should auto-load it.
- Commit only the coherent slice; include evidence path and verification command.
If no skill update is needed, final/summary must say skill_update=not_needed and give the reason. If a code/gate/readback change happened, skill_update=not_needed is only valid after checking current active skills for stale field names.
Provider-runtime repair checklist
- Verify focused provider first:
provider-status --provider <id> --agent. - Verify full matrix:
provider-status --compact. - Provider-ready is only a prerequisite. For data claims, run concrete fetch and record row count.
- After repeated IBKR historical ladders return zero rows/timeouts, do not launch another same-shape IBKR stock Gate 1 lane just because
provider-statusis green. Classify withsupport/scripts/auto_quant_external/ibkr_provider_guard.py; whencooldown_recommended=true, repair/probe the IBKR historical path or switch to a non-IBKR real-provider cell before new factor work. - Auto-Quant/backtest provider and realtime advice provider must name the same exchange family when the user asks for practical trading use. For crypto public lanes, pair
binance_publicwithbinance_public_runtime, orbybit_publicwithbybit_public_runtime; do not silently train on one exchange and advise from another. - Binance and Bybit public crypto OHLCV are no-key, zero-config lanes in ict-engine; do not classify them as missing just because the Python
fetch_external.pyoptional dependency set is incomplete. - IBKR on this host needs zsh to prefer
~/.local/bin/python3withredis,ib_async,pandasimportable. - For TOMAC clean-AQ reruns, do not assume removing
--max-rowson the same root will widen the history window. If a prior bounded clean bundle/AQ workspace already exists on that root, the rerun may reuse it and preserve the bounded window. Use a fresh root when the user asks for a true max-window exact rerun. - For TOMAC prep wrappers that claim to stage a full-window exact rerun, default command generation must omit
--max-rowsunless the operator explicitly asks for a bounded diagnostic replay. A hardcoded--max-rows 300000in the wrapper contract silently converts multi-year retained-history work into a 2021-only slice and can create falseno_survivororzero_tradeterminalizations. Preserve bounded replay as an explicit--max-rows <N>option, and pair the true full-window relaunch with a fresh root. - For TOMAC wrappers that launch broad source scanners such as
tomac_fast_daily_scan.pywithout a native--familiesselector, do not trust the raw top rows as branch truth. The wrapper must post-filterscan_results.json/leaderboard.csvback to the exact rooted branch (for example byfactor_idprefix or target regime) before claiming branch-specific readback or terminal decisions. - For local AQ wrappers derived from
run_tomac_nq_local_autoquant_loop_v1.py, do not point non-NQ Databento-style futures CSVs such asYMstraight atstage_exact_source_data()without checking the schema. That staging owner expectsts_event,open_adj,high_adj,low_adj,close_adj,volume; raw Databento exports with onlyopen,high,low,closemust be normalized first or routed through a clean-bundle staging path, otherwise the launch fails before round 0 with pandasUsecols do not match columns. - TradingViewRemix remote HTTP can be 429; prefer local stdio for OHLCV:
ICT_ENGINE_TRADINGVIEW_MCP_CMD=uvICT_ENGINE_TRADINGVIEW_MCP_ARGS='--directory $HOME/tradingview-mcp/tradingview-mcp run tradingview-mcp'
- Hubble provider-status needs
ICT_ENGINE_HUBBLE_BASE_URL; still validate actual Hubble fetch before using rows as evidence.
Evidence packet pattern
Create transient lane evidence under /tmp/ict-engine-.../<timestamp>-<owner>-<topic>/.
Repo admission is allowed only for typed product surfaces, tests, reviewed
support examples, or explicit structured evidence packages outside
support/docs.
Minimum files:
checks/provider_status_compact.txtor command output- focused provider JSON outputs when relevant
summaries/terminal_decision_summary.md- See
references/auto-quant-closure-evidence-packages.mdfor the recurring auto-quant import / apply / parity closure shape. - See
references/pa-agent-intake-consumer-docs-map.mdas historical intake context only; current external material should land as embedded defaults, opt-in source/profile fixtures, compactartifact_index.json, privacy scan, and observation-onlytrade_usable=falseboundaries outsidesupport/docs. - For coordinated objective snapshots, prefer reusing a current heavy done-definition packet with
objective_closure_snapshot.py --done-definition-proof <done_definition_audit.json>instead of rerunning heavy gates every lightweight refresh. This proof is valid only when the referenced packet hascompletion_ready=true, no skipped gates, the same selectedheadas the live child done-definition audit, and the sametracked_worktree_fingerprintwhen the live child reports one; with--output-dir, the snapshot stages it asdone_definition_proof.compact.jsonso the evidence packet is self-contained. Partial/skipped/no-head/stale-head/fingerprintless-or-mismatched proof must remain fail-closed and cannot suppress done-definition blockers. - When a valid heavy done-definition proof is applied, the parent done-definition surface must take
pass_count,fail_count,skip_count, andtotal_gatesfrom the proof while preserving the current light child source-debt/quarantine surfaces. Mixed proof status with light-child gate counts is misleading evidence and needs a regression before repair. - For coordinated objective snapshots that are used as release/completion evidence, run with
--check-remotes. A snapshot without remote checks must fail closed asrelease_remote_checks_not_runwhenrelease_readiness_audit.pyskipsremote_readbackorrelease_version_tag_available; otherwise the parent packet can hide source-origin drift or reused release tags behind a surface-green local release audit. - For coordinated objective snapshots from a dirty shared tree, a clean selected-export release audit may be reused with
objective_closure_snapshot.py --release-readiness-proof <release_readiness_audit.json>only when the parent snapshot itself uses--check-remotes, the proof was remote-checked, has no skipped gates, and provesworktree_clean_for_release=pass. If the proof comes from the release mirror clone, it may have a different commit hash than the development checkout; accept it only when the proofhead, proofrelease_mirror_main, and current remoterelease_mirror_mainare identical and the proof summary ispass. Do not require or recommend pushing the sourcegivenup-ict-engineorigin for mirror-only release closure. Partial/no-remote/stale-mirror proof remains fail-closed. - For heavy done-definition smoke evidence in a shared worktree, distinguish a real zero-config CLI hang from cargo lock/build contention. If
support/scripts/smoke_acceptance.shtimes out with empty command stdout/stderr while many cargo processes are active, reproduce the same smoke/update path with an already-built binary by settingICT_ENGINE_BIN=/path/to/ict-engine. The smoke harness supports this binary-reuse mode while preserving the default consumer-facingcargo runpath. - For coordinated objective snapshots, do not treat a compact done-definition child as clean just because a source-surface gate reports
status=pass.practical_admission_source_surfaceandawait_launch_source_surfacecan pass for tracked release hygiene while still reporting untracked wrapper debt. Objective closure must preserve/readuntracked_violation_count; practical-admission debt blocks onpractical_admission_source_debtuntil unsafe scratch wrappers are retired, quarantined, or explicitly tracked, and await-launch debt blocks onawait_launch_source_debtuntil wrappers that can launch with active/fresh claims present are retired, quarantined, or explicitly guarded. - For repo-local factor-training hygiene,
done_definition_audit.pyincludesrepo_training_scratch_surface. Non-promoted factor-training scratch docs/scripts, repo-local state/model output, and untracked evidence-run residue must live under/tmp; repo paths are allowed only when tracked or force-added as a durable evidence packet or product surface. A clean worktree with no live-usable factor is not a reason to preserve ignored training residue in the repo. - When an objective-level blocker is driven by many source-scan violations, samples are not enough. The child audit should write a full manifest and
objective_closure_snapshot.py --output-dirshould stage it into the packet, for examplepractical_admission_source_debt_manifest.json, so the next agent can retire or quarantine every violating wrapper instead of chasing the first 10 examples. - For reusable factor candidate packs, keep provenance clone-safe and self-describing. A pack directory should carry
pack_manifest.json,factor_expression.json,factor_eval_grid_summary.json, andtransfer_score.json; generated manifest fields such assource_artifactmust not preserve caller-local absolute paths. Product-visible candidate selection remains explicit through the registry/preset layer, not implicit directory scanning. - Do not commit loose, one-off factor wrappers as product-ready work. If stale agent residue contains useful factor logic, convert or quarantine it into the repo's reusable structured format first, such as a candidate pack with
pack_manifest.jsonplus expression/evaluation/transfer artifacts or another established manifest-backed surface. Otherwise leave the loose script unstaged and record the packaging blocker in the handoff.
Do not commit home dotfiles in the repo. Record their paths and exact env keys in the evidence summary.
Red flags
- Committing ict-engine after a repair but leaving the maintenance lesson only in chat.
- Saying
8/8 readywithout naming which provider was missing. - Treating
provider-status readyas a successful data fetch. - Updating router files but not
skill-index.json/skill-index.md. - Staging broad dirty Board A/B files from other agents.
- Using
.gitignoreas proof that a run tree is excluded. Already tracked files still appear as modified; provegit diff --cached --name-onlyhas no run-tree paths. - Running
git add .in ict-engine when evidence runs, local docs, or agent skill drafts are present. - Committing generated evidence run trees before checking untracked file count and byte size.
- Claiming Board A achieved universal 95% regime confidence when the artifacts only prove a runnable evidence scaffold.
- In Board B rooted-branch handoffs, treating a synthetic regime-bundle branch score as equivalent to a real history/runtime-scored branch. If runtime reuse mode is
prefer_history, verify the exactregime_profit_branch_pathremains the selected workflow/execution-tree path and thatpath_ranker_runtime_sourceis a real source such ashistory_path, not only a synthetic score. - Treating visible/observation/cache/history ranker evidence as execution-permitted. Execution consumers must distinguish
visible=truefromused=true, require production validation plusexecution_gate_status=passfor execution-gate use, and keep observation/cache/handoff evidence asobserveorfail_closeduntil cost/slippage/provider/sample gates pass. For the profitability lifecycle, legacy ranker values such asexecution_gate_status=pass|ready|execution_ready|admissibleare not live-trade usability;promotion_allowed,trade_usable, andupdate_goalrequire an explicit live plane (live_trade_ready/live_trade_usable) or same-root closed-loop admission withstatus=admitted,live_trade_status=ready, and all three practical flags true after the current consumer revalidates branch shape.wait_for_reversionis observe-only in the current live plane; onlyfill_viablemay materialize same-root live execution. Policy-training lifecycle ready strings such aspaper_ready,live_trade_ready, orlive_trade_usablemust also have mature training evidence (maturity_mask, calibrated label, positivetraining_weight) before counting readiness. Diagnostic-only tools must not reuse those practical field names for interesting-signal telemetry; use diagnostic names such asdiagnostic_candidate_passed_gateand keep downstream live-gate requirements explicit. - Treating
same_tree_practical_closure(or downstream / execution-tree / path-ranker / accepted-feedback / retained-session-scope completion) as a hard promotion gate. It is an OPTIONAL enhanced-lifecycle path, not a promotion prerequisite. Persrc/application/factor_lifecycle/profitability_admission.rs(promotion basisgood_factor_verified_cost_positive, policygood_factor_verified_cost_positive_downstream_feedback_optional_20260602), a clean-AQ verified-cost-positive good factor — learning-admitted,evidence_count >= 12, no lookahead, validated provenance, verified instrument cost, positive net — ispromotion_allowed/trade_usableWITHOUT same-tree closure, accepted paper/live/broker feedback, Pre-Bayes/BBN/execution-tree placement, path-ranker use, or ranker validation. The prior blockersaccepted_execution_feedback_missing,execution_readiness_below_live_floor,execution_tree_gate_status_not_ready,execution_tree_branch_not_live_ready,path_ranker_score_not_used_by_execution_tree,ranker_validation_not_ready, andretained_session_scope_unverifiedare now robustness/longevity debt, not practical vetoes; this matches theict-engi-fact-rese-mutagood-factor/superior-factor standard. Still never advertise a factor as funded-live-trade ready on this advisory CLI. - Accepting a claimed
same_tree_practical_closurepacket — produced only as the optional stricter-lifecycle path above, never required for promotion — as valid without the full lifecycle tuple. A validsame_tree_practical_closuremust prove the referenced evidence packet is same-root, every command result has exit zero with explicittimed_out=false, and command names cover the provider/data, Pre-Bayes, BBN/workflow, path-ranker, execution-tree, feedback/update, and policy-training stages. It must also prove exact branch survived, execution candidate is actionable, validation counters cover raw/production/observation floors, policy training summary exists, and the lifecycle tuple is exactlylearning_admission_status=admitted,paper_admission_status=ready, andlive_trade_status=ready. It must also carrydeploy_ready=true,funded_live_fill_required=false, and readiness contractdeploy_ready_from_backtest_autoquant_provider_or_paper_sim_execution_chain_not_funded_fillat packet and policy-lifecycle level, with positivedeploy_ready_count. Rawpromotion_allowed=true,trade_usable=true, or a single aggregate command row such asname=allis not enough, and practical closure must not require a funded live fill. - Letting compact audit formatting hide pass-gate debt. If a pass gate carries warning/debt fields that matter for objective closure, compact output must preserve the minimal fields needed by the parent snapshot; otherwise closure packets can look surface-green while the current worktree still contains unsafe practical-admission code.
- Letting parent objective snapshots name
factor_closure_blockedwithout reusable blocker detail. The parent packet must preserve compact factor-closure counts, coordination-only count, invalid active count, live process count, attention groups, action queue roots/claims, blocking reasons, and next action so the packet stays actionable without opening the child factor audit. - Letting parent objective snapshots name
release_readiness_blockedwithout reusable blocker detail. The parent packet must preserve release head, unresolved gates, pass/fail/skip counts, release next actions, skipped remote gates, proof rejection fields when present, and compact remote readback status such as origin vs release-mirror failure so operators can act without opening the child release audit. - Letting parent objective snapshots name
done_definition_not_completion_readywithout reusable blocker detail. The parent packet must preserve done-definition head, tracked worktree fingerprint, completion/evidence status, pass/fail/skip/total gate counts, unresolved and skipped gates, next action, quickstart status, and proof rejection fields when present so operators can see whether the blocker is heavy-gate coverage, failing gates, stale proof, or source-surface debt without opening the child done-definition audit. - Letting await-launch wrappers use
live_factor_processes=0as the only launch guard. Await-launch wrappers that call child prep/launch code must also fail closed on active/fresh claim counters fromfactor_claim_terminalization_audit.py; otherwise a fresh claim without a live process can be bypassed and a partial collision launch can start.done_definition_audit.pysurfaces this asawait_launch_source_surface; objective snapshots must preserve pass-state debt and block onawait_launch_source_debtwhen it is not retired/quarantined/tracked. - Reporting a debt blocker without a full manifest. Counts plus sample rows can prove non-completion, but they cannot drive systematic closure of all violating wrappers. Stage a complete manifest into the objective packet when the blocker names a many-file source debt surface.
- Keeping retired or non-blocking gate fields as active hard blockers in skills. Before repeating an older blocker name, inspect current source/readback semantics and update the skill when the contract drifted.
- When a user asks whether an ict-engine profitability factor is "实战"/live-usable and a readiness floor changes, audit both repo consumers and active runtime skills for stale threshold language before committing. For the current profitability loop,
execution_readiness >= 0.45is the closed-loop return-to-duty/live-plane admission floor for cost-positive same-root candidates;>= 0.65is only the strongerexecution_readyclass. Preserve0.65in historical references only when it is clearly framed as strong-ready, not as a hard exile rule. - Same-root execution-tree materialization in
src/analyze_shared.rsmust reuseict_engine::application::factor_lifecycle::LIVE_EXECUTION_READINESS_FLOOR; do not hardcode0.65there. Regression should proveexecution_readiness=0.45withbranch=fill_viable, used+validated path ranker, admitted closed-loop flags, and even highhybrid_transition_hazardstill materializes an actionable same-root candidate.transition_hazardmay remain telemetry/source-scan debt, but must not re-enterbranch_local_admitted,promotion_allowed,trade_usable, orupdate_goalas a hard live gate. - Readiness-floor audits must include non-lifecycle consumers that can silently re-exile same-root candidates after the core lifecycle passes. In particular, inspect
src/analyze_shared.rssame-root execution-tree admission (actionable_admission) and strict trace fallback paths:0.65there is only valid for strong-ready classification, not as the live-plane floor. Add or run a regression provingexecution_readiness=0.45still permits a cost-positive same-root closed-loop candidate to remain actionable when all other live-plane gates pass. - Treating release mirror readback as a generic network failure when an HTTPS GitHub URL reports SSH-style
port 22errors. Preserve no-rewrite HTTPS fallback diagnostics for both source origin and release mirror probes so operators can distinguish GitHub reachability from local git URL rewrite / SSH transport drift. A fallback namedhttps_public_no_rewritemust actually neutralize local git rewrite config, for example by running withGIT_CONFIG_GLOBAL=/dev/nullandGIT_CONFIG_NOSYSTEM=1; otherwiseurl.*.insteadofcan silently turn the HTTPS fallback back into SSH and create falseremote_readbackblockers. - Letting release signoff and release notes drift across tags.
release_readiness_audit.pyshould parse the signoffSelected candidate, release-notesVersion, and current Cargo package version; signoff/notes tag mismatch or Cargo-version drift must failrelease_docs_fresh_for_selected_tagbefore publishing. Do not use currentHEADas an implicit signoff source-commit equality check because committing refreshed signoff docs changesHEAD; source alignment stays undersource_origin_matches_selected_sourceand the clean selected export flow. - Counting command-introspection probes or zero-config smoke children as live factor owners.
run_tomac.py --help,python -m unittest ...run_tomac..., grep/sed/rg/find readbacks, ps/awk process pollers, exit-filecat/Python-heredoc readbacks, TOMAC diagnostic probes, and directict-enginedemo/DEMO smoke commands underict-engine-done-definition-audit-smoke,ict-engine-smoke-acceptance, orict-engine-first-runare not provider/AQ writers and must be filtered before declaringlive_factor_processes > 0. Add regression tests tosupport/scripts/tests/test_factor_claim_terminalization_audit.pywhen a new probe shape appears. - Counting zero-config consumer smoke as live factor ownership.
ict-engine analyze|workflow-status|pre-bayes-status|policy-training-status --symbol DEMO --demo/--state-dir /tmp/ict-engine-*-smoke*is first-run or done-definition evidence, not Board B profitability runtime. Filter these smoke/readback commands before declaring factor closure blocked, while keeping real TOMAC/factor lifecycle commands under Board B run roots classified as live. Compact factor action queues should preserve a shortcommand_excerptfor live runtime rows so parent objective packets remain actionable without opening the child audit. - Missing direct ict-engine factor lifecycle commands in live-process occupancy.
cargo run --quiet -- factor-research ... --state-dir /tmp/ict-engine-*and directict-engine factor-research/factor-autoresearch/auto-quant-agent-material*commands writing under a Board B/tmproot are live factor/runtime work, even when they are not namedrun_tomacorfetch_external.py. Keepps|rg, unittest, and help probes ignored, but add a focused classifier regression when a real factor CLI shape is missed. - Missing generic Python factor scripts in live-process occupancy. A Python command that runs a script from a Board B
/tmp/ict-engine-*lane root, for example/tmp/ict-engine-.../scripts/run_*_pybacktest.py, is live factor/runtime work even when it is not namedrun_tomac,run_ibkr_*, orfetch_external.py. Keep help, unittest, grep/sed/rg, and TOMAC diagnostic probes ignored, but classify generic.pyscripts with an extracted Board B run root as live and cover new shapes withsupport/scripts/tests/test_factor_claim_terminalization_audit.py. - Letting shell wrapper variables pollute live-process run roots. Parent commands such as
root=/tmp/ict-engine-...followed by--root "$root/run"must resolve the simple shell assignment, and unresolved$root/...tokens must be ignored rather than surfaced as literal run roots. macOSpsmay render wrapper newlines as\\012; normalize that before extracting assignments so action queues do not report roots like/tmp/ict-engine-...\\012python3. - Collapsing all active claims into the same cleanup action. Fresh active claims without a live process are wait/inspect targets until stale-safe timeout or terminal evidence exists; fresh wait-only prep claims are also wait targets; stale-safe wait-only claims are cleanup/externalization targets; live-runtime-owned active claims belong under live-runtime wait actions, not generic
terminalize or externalize active claimswording. - Treating every workdoc
Decision:field as terminal evidence. Workdocs can contain workflow sections such as## TDD RoutewithDecision: skipped,strict,light,auto, oroff; those are process-route decisions, not factor terminalization.factor_claim_terminalization_audit.pyshould terminalize workdocs from terminal/final sections, explicitterminal_*fields, terminal-looking status, or terminal-looking decisions only, and any new nonterminal workflow section needs a focused regression test. - Treating every terminalized missing
run_rootas live evidence debt. A terminalized duplicate/no-launch/collision-deferred claim with explicit falsepromotion_allowedandtrade_usablemay intentionally have no AQ root because no launch produced factor economics; it should not block closure asmissing_run_roots. Active missing roots and terminalized claims with positive practical flags still require attention, restoration, or explicit evidence review. - Treating
/tmpand/private/tmprun roots as different Board B owners on macOS. Claim/live-runtime matching must normalize tmp aliases and common lane subdirs before deciding a claim isfresh_active_without_live_process; otherwise the same live AQ lane can appear twice in the parent action queue. - Applying a heavy done-definition proof by replacing the current light child surface. Proof reuse may clear full-gate coverage only; it must preserve current practical-source debt/quarantine details from the same packet, or parent snapshots can hide untracked wrapper residue.
- Letting objective-level audit wrapper timeouts kill only the direct child.
objective_closure_snapshot.pyand similar parent wrappers must kill the full child process group on timeout, or broad child scanners such asdownstream_practical_admission_source_check.pycan survive, consume shared resources, and distort later claim/process readbacks. - Flattening practical-source scanner failures into generic source-debt counts. If
downstream_practical_admission_source_check.pytimes out, returns non-zero without JSON violations, or otherwise fails as tooling,done_definition_audit.pyandobjective_closure_snapshot.pymust preserve scanner command, error/timeout, return code, stdout, and stderr so parent packets distinguish tooling failure from a clean source surface. - Reporting
remote_readbackas a release-mirror repair when only sourceoriginfailed and the release mirror is readable. Release audits should preserve the failed remote side and point the operator atoriginvs release mirror specifically. - Letting audit-only, coordination-only, or inventory-only claims block factor closure. A claim with explicit
active_audit_only/active_coordination_only/active_inventorystatus, false practical flags, and no-launch/read-only or artifact-scan language is bookkeeping, not an active profitability factor owner. It should remain visible ascoordination_only_active_claimsbut must not pollute compact factor action queues or practical closure blockers. - Fingerprinting untracked practical-admission source debt with incidental line/column positions. Quarantine matching should use the stable violation signature (
file,key,value,violation) so scratch-wrapper line churn does not create false unquarantined debt. If shared untracked wrapper residue oscillates between reviewed stable signatures for the same count/file set, record the alternate digest underreviewed_alternative_untracked_violations_sha256; do not replace count/file/schema/decision checks, and do not treat the quarantine as release or trade evidence.
Chinese triggers
ict-engine维护, ICT维护, provider 8/8, provider-status, 8/8 ready, IBKR依赖, TradingViewRemix 429, TVR 429, Hubble base url, 提交前更新skill, 维护经验沉淀, 训练完沉淀skill, 训练后更新skill, 提交ict-engine, ict-engine commit, Board A/B evidence packet.