|
|
|
|
@ -1,8 +1,127 @@
|
|
|
|
|
# AG Workspace Rules
|
|
|
|
|
# Agent Rules & Governance
|
|
|
|
|
|
|
|
|
|
This document persists the active constraints, policies, and guardrails enforced by the Agent (`AG_GLOBAL` and `AG_WORKSPACE`).
|
|
|
|
|
|
|
|
|
|
## AG_GLOBAL
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
AG_GLOBAL:
|
|
|
|
|
meta:{v:"1.4",mode:GOVERNOR,block:true,scope:ALL,override:WORKSPACE_ALLOWED}
|
|
|
|
|
|
|
|
|
|
op_mode:{default:READ_ONLY,change_trigger:"DO_CHANGE",no_write_without_trigger:true}
|
|
|
|
|
|
|
|
|
|
enforce:
|
|
|
|
|
def:BLOCK
|
|
|
|
|
on_block:{out:[reason,rule,evidence,next],next:[request_context,run_gates,patch_plan]}
|
|
|
|
|
approvals:[
|
|
|
|
|
freqtrade_core,new_feature_outside_refs,arch_layer_change,public_api,db_schema,open_ports,new_file_creation,
|
|
|
|
|
diff_budget_exceed,dead_code_exception,global_ownership_exception,sequencing_exception,
|
|
|
|
|
time_determinism_exception,import_side_effect_exception,exit_policy_exception
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
id:{system:ProjectBot,persona:SINGLE,roles:[CA,SBE_LL,DevSec,Trader,QuantRisk,QA,BreezeSDK]}
|
|
|
|
|
authority:{prio:[FUNCTIONAL_LAW,ARCHITECTURE,ARCH_ADD,SCHEMA_MAP,MASTER_LEDGER,TDD],external:[FREQTRADE_DOCS,BREEZE_API,BREEZE_PYPI],invent:false}
|
|
|
|
|
prime:{no_floating:true,no_partial:true,missing_ctx:BLOCK,silent_fix:false}
|
|
|
|
|
diff_budget:{max_files:3,exceed_requires_approval:true}
|
|
|
|
|
|
|
|
|
|
dead_code_policy:{forbid:true,allow_only_if_header:{schema:[reason,objective,expected_input,expected_output,unblock_condition],ledger_entry_required:true}}
|
|
|
|
|
new_files:{default:BLOCK,allow_only_if:[explicit_user_request,technically_unavoidable],require:[justification,alt_reuse_attempts]}
|
|
|
|
|
|
|
|
|
|
arch:
|
|
|
|
|
imports:{abs:true,forbid:["^from\\s+src\\.","^import\\s+src\\."],wild:false,circ:false,bare_except:false}
|
|
|
|
|
layers:
|
|
|
|
|
D:{allow:[dc,typing,proto,logic,derr],deny:[sdk,http,db,fs,fw,di,pres]}
|
|
|
|
|
A:{allow:[D],deny:[sdk,http,db,fs,fw,pres_spec]}
|
|
|
|
|
I:{allow:[D,A,sdk,http,db,fs],deny:[pres]}
|
|
|
|
|
P:{allow:[A,D],deny:[I_direct]}
|
|
|
|
|
wire:{comp_root:true,svc_loc:false,god:false,max_resp:1,reexport_modules:false,canonical_owner_required:true,owner_registry_required:true}
|
|
|
|
|
|
|
|
|
|
change:
|
|
|
|
|
scope:MIN
|
|
|
|
|
require_trigger:"DO_CHANGE"
|
|
|
|
|
ref_only_if:[fail_test,rule_violation,explicit]
|
|
|
|
|
rename_req:[refs,tests,docs]
|
|
|
|
|
allow_paths:[src/**,tests/**,docs/**,scripts/**]
|
|
|
|
|
restrict_paths:[freqtrade/**,.github/**,docker/**,compose/**,pyproject.toml,requirements*.txt]
|
|
|
|
|
restrict_paths_override_requires_approval:true
|
|
|
|
|
|
|
|
|
|
ai_comments:{req:true,scope:[src/**,tests/**,scripts/**],rule:["new_code=>intent","if_file_no_comments=>retrofit","comments=WHY>WHAT"]}
|
|
|
|
|
security:{no_secrets_code:true,no_secrets_logs:true,src:[env,secret_files],bypass:false}
|
|
|
|
|
sdk:{broker:ICICI_BREEZE,adapter_boundary:true,undoc:FORBIDDEN}
|
|
|
|
|
test:{unit:{net:false,fs:false,det:true,glob:false},int:{sdk:mock,sqlite:temp},regr:REQ}
|
|
|
|
|
net:{bind:"127.0.0.1",ports:{st:8501,h:8000,nv:6080,v:5900},open:false,approval:true,docs:[deploy,compose,security]}
|
|
|
|
|
|
|
|
|
|
# === TERMINAL: keep prefixes minimal; rely on unix_prefix matching ===
|
|
|
|
|
|
|
|
|
|
terminal:
|
|
|
|
|
auto_exec:
|
|
|
|
|
unix_prefix:[
|
|
|
|
|
"python","pytest",".venv/bin/pytest","ruff","mypy","pydeps","pip check","pip list","pip freeze","pip show",
|
|
|
|
|
"git status","git diff","git show","git log","git branch","git rev-parse",
|
|
|
|
|
"rg","fd","ls","tree","wc","sed","awk","env","which","sha256sum","md5sum","jq","uname","df","free","ulimit","ps",
|
|
|
|
|
"freqtrade --version","freqtrade list-exchanges","freqtrade list-markets","freqtrade download-data --dry-run","freqtrade trade --dry-run",
|
|
|
|
|
"bash scripts/accept_all.sh","bash scripts/run_tests.sh","bash scripts/ci_verify.sh","bash scripts/collect_p12_data.sh","bash scripts/lint_check.sh","bash scripts/dry_run.sh"
|
|
|
|
|
]
|
|
|
|
|
deny:
|
|
|
|
|
unix_prefix:[
|
|
|
|
|
"bash -c","sh","source",". ",
|
|
|
|
|
"sudo","su",
|
|
|
|
|
"rm","mv","cp","chmod","chown",
|
|
|
|
|
"curl","wget","ssh","scp","rsync",
|
|
|
|
|
"pip install","pip uninstall","pip upgrade","pip install -r","pipx","apt","apt-get","dpkg","snap","brew",
|
|
|
|
|
"git commit","git push","git pull","git fetch","git reset","git rebase","git checkout","git clean",
|
|
|
|
|
"freqtrade trade","freqtrade webserver","freqtrade rpc","freqtrade telegram","freqtrade install-ui","freqtrade download-data","freqtrade backtesting","freqtrade hyperopt","freqtrade new-strategy","freqtrade create-userdir",
|
|
|
|
|
"&&","||",";","|","`","$(","<",">","2>","1>","&>"
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
ownership:
|
|
|
|
|
def:BLOCK
|
|
|
|
|
objective:ONE_OWNER_PER_GLOBAL_ENTITY
|
|
|
|
|
scope:[class,singleton,global_config,constant,enum,registry,service_locator,stateful_cache]
|
|
|
|
|
rules:{single_owner:{block:true},no_reexports:{block:true},no_multi_singleton:{block:true},import_contract:{block:true}}
|
|
|
|
|
allowed:[TYPE_CHECKING,owner_factory,explicit_DI]
|
|
|
|
|
evidence_on_block:[entity,owner_candidate,dups,reexports,instantiations]
|
|
|
|
|
|
|
|
|
|
sequencing:
|
|
|
|
|
def:BLOCK
|
|
|
|
|
objective:DETERMINISTIC_LIFECYCLE_ORDER
|
|
|
|
|
no_side_effects_on_import:true
|
|
|
|
|
single_orchestrator_required:true
|
|
|
|
|
orchestrator_path_hint:"main.py"
|
|
|
|
|
invariants:["config_before_net","logging_before_bg","rl_before_clients","ex_before_loop","loop_after_ready","shutdown_reverse_cleanup"]
|
|
|
|
|
forbidden:["net_on_import","threads_on_import","boot_singletons_on_import","hidden_top_level_init"]
|
|
|
|
|
exception_requires_approval: sequencing_exception
|
|
|
|
|
|
|
|
|
|
time_determinism:
|
|
|
|
|
def:BLOCK
|
|
|
|
|
objective:DETERMINISTIC_TIME
|
|
|
|
|
scope_paths:[src/**,tests/**,adapters/**]
|
|
|
|
|
runtime_time_deps_must_inject:[now_fn,sleep_fn]
|
|
|
|
|
forbidden_in_tests:["time.sleep(","asyncio.sleep(","datetime.now(","time.time(","perf_counter("]
|
|
|
|
|
required_patterns:["FakeClock","now_fn","sleep_fn"]
|
|
|
|
|
exception_requires_approval: time_determinism_exception
|
|
|
|
|
|
|
|
|
|
exit_policy:
|
|
|
|
|
def:BLOCK
|
|
|
|
|
objective:EXITS_NO_SHORTS
|
|
|
|
|
rules:{buyer_only:true,exit_intent_keys:[reduceOnly,ft_exit],sell_requires_exit_intent_if_no_pos:true,forbid_shorts:true,forbid_silent_bypass:true}
|
|
|
|
|
exception_requires_approval: exit_policy_exception
|
|
|
|
|
|
|
|
|
|
import_side_effect_scan:
|
|
|
|
|
def:BLOCK
|
|
|
|
|
objective:NO_IMPORT_SIDE_EFFECTS
|
|
|
|
|
scope_paths:[src/**,adapters/**,freqtrade/**]
|
|
|
|
|
forbid_patterns:["BreezeConnect\\(","requests\\.","httpx\\.","aiohttp\\.","websocket\\.","Thread\\(","create_task\\(","schedule\\.","patch_ccxt\\("]
|
|
|
|
|
allow_if:["inside_def_or_class_only","guarded_by_if_name_main"]
|
|
|
|
|
exception_requires_approval: import_side_effect_exception
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## AG_WORKSPACE
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
AG_WORKSPACE:
|
|
|
|
|
|
|
|
|
|
## === REUSE FROM trade-bot REPO (HARD GUARDRAILS) ===
|
|
|
|
|
# === REUSE FROM trade-bot REPO (HARD GUARDRAILS) ===
|
|
|
|
|
|
|
|
|
|
reuse_policy_trade_bot:
|
|
|
|
|
trust_level: "LOW"
|
|
|
|
|
@ -32,7 +151,7 @@ AG_WORKSPACE:
|
|
|
|
|
- no_leaked_secrets
|
|
|
|
|
- no_layer_violation
|
|
|
|
|
|
|
|
|
|
## === PORTS & ADAPTERS RULE (CLEAN ARCHITECTURE) ===
|
|
|
|
|
# === PORTS & ADAPTERS RULE (CLEAN ARCHITECTURE) ===
|
|
|
|
|
|
|
|
|
|
ports_and_adapters:
|
|
|
|
|
principle: "DEPENDENCY_INWARD_ONLY"
|
|
|
|
|
@ -54,7 +173,7 @@ AG_WORKSPACE:
|
|
|
|
|
- domain_importing_streamlit_or_any_ui
|
|
|
|
|
- application_importing_infrastructure_details
|
|
|
|
|
|
|
|
|
|
## === DEPENDENCY DIRECTION ENFORCEMENT ===
|
|
|
|
|
# === DEPENDENCY DIRECTION ENFORCEMENT ===
|
|
|
|
|
|
|
|
|
|
dependency_guard:
|
|
|
|
|
checks_required:
|
|
|
|
|
@ -65,7 +184,7 @@ AG_WORKSPACE:
|
|
|
|
|
- STOP_ON_FIRST_VIOLATION
|
|
|
|
|
- require_fix_before_any_new_work
|
|
|
|
|
|
|
|
|
|
## === FUNCTIONALITY VALIDATION WHEN REUSING CODE ===
|
|
|
|
|
# === FUNCTIONALITY VALIDATION WHEN REUSING CODE ===
|
|
|
|
|
|
|
|
|
|
functional_validation:
|
|
|
|
|
required_for_any_trade_bot_reuse:
|
|
|
|
|
@ -76,7 +195,7 @@ AG_WORKSPACE:
|
|
|
|
|
- rate_limit_behavior_verified
|
|
|
|
|
- logging_verified
|
|
|
|
|
|
|
|
|
|
## === DOCUMENTATION DUTY ===
|
|
|
|
|
# === DOCUMENTATION DUTY ===
|
|
|
|
|
|
|
|
|
|
docs_update_required:
|
|
|
|
|
on_any_trade_bot_reuse:
|
|
|
|
|
@ -85,7 +204,7 @@ AG_WORKSPACE:
|
|
|
|
|
- record_changes_made
|
|
|
|
|
- record_tests_run
|
|
|
|
|
|
|
|
|
|
## --- OWNERSHIP GUARD (ADD) ---
|
|
|
|
|
# --- OWNERSHIP GUARD (ADD) ---
|
|
|
|
|
|
|
|
|
|
ownership_guard:
|
|
|
|
|
owner_registry:
|
|
|
|
|
@ -98,7 +217,7 @@ AG_WORKSPACE:
|
|
|
|
|
- verify_imports_target_owner_module
|
|
|
|
|
handling: STOP_ON_FIRST_VIOLATION
|
|
|
|
|
|
|
|
|
|
## --- SEQUENCING GUARD (ADD) ---
|
|
|
|
|
# --- SEQUENCING GUARD (ADD) ---
|
|
|
|
|
|
|
|
|
|
sequencing_guard:
|
|
|
|
|
objective: "Ensure runtime lifecycle order is explicit, deterministic, and testable."
|
|
|
|
|
@ -118,11 +237,11 @@ AG_WORKSPACE:
|
|
|
|
|
- "scheduler_start_on_import"
|
|
|
|
|
- "thread_start_on_import"
|
|
|
|
|
commands:
|
|
|
|
|
- "rg -n \"^(?!\\s*#).*\\b(requests\\.|httpx\\.|aiohttp\\.|websocket\\.|BreezeConnect\\(|create_task\\(|Thread\\(|schedule\\.)\" src/ tests/ || true"
|
|
|
|
|
- "rg -n \"^(?!\\s*#).*\\b(requests\\.|httpx\\.|aiohttp\\.|websocket\\.|BreezeConnect\\(|create_task\\(|Thread\\(|schedule\\.|patch_ccxt\\()\" src/ adapters/ freqtrade/ tests/ || true"
|
|
|
|
|
orchestrator_scan:
|
|
|
|
|
rule: "Only main/orchestrator may call bootstrap/start loop."
|
|
|
|
|
commands:
|
|
|
|
|
- "rg -n \"\\b(start|run|bootstrap|init)_(scheduler|loop|engine)\\b\" src/ | head -n 200"
|
|
|
|
|
- "rg -n \"\\b(start|run|bootstrap|init)_(scheduler|loop|engine)\\b\" src/ adapters/ | head -n 200"
|
|
|
|
|
tracer_gate:
|
|
|
|
|
requirement: "viztracer trace must show expected sequence markers"
|
|
|
|
|
markers_required:
|
|
|
|
|
@ -136,3 +255,43 @@ AG_WORKSPACE:
|
|
|
|
|
violation_handling:
|
|
|
|
|
- STOP_ON_FIRST_VIOLATION
|
|
|
|
|
- require_fix_before_any_new_work
|
|
|
|
|
|
|
|
|
|
# =========================
|
|
|
|
|
|
|
|
|
|
# ADD: TIME DETERMINISM WORKSPACE CHECKS
|
|
|
|
|
|
|
|
|
|
# =========================
|
|
|
|
|
|
|
|
|
|
time_determinism_guard:
|
|
|
|
|
objective: "Prevent flaky gates by banning wall-clock and sleep in unit tests and requiring injectables."
|
|
|
|
|
checks_required:
|
|
|
|
|
ban_wall_clock_in_tests:
|
|
|
|
|
commands:
|
|
|
|
|
- "rg -n \"\\b(time\\.sleep\\(|asyncio\\.sleep\\(|datetime\\.now\\(|time\\.time\\(|perf_counter\\()\" tests/ || true"
|
|
|
|
|
require_injection_for_time_deps:
|
|
|
|
|
commands:
|
|
|
|
|
- "rg -n \"class\\s+(RateLimiter|AlertManager)\\b|def\\s+__init__\\(.*(now_fn|sleep_fn)\" adapters/ccxt_shim/ || true"
|
|
|
|
|
violation_handling:
|
|
|
|
|
- STOP_ON_FIRST_VIOLATION
|
|
|
|
|
|
|
|
|
|
# =========================
|
|
|
|
|
|
|
|
|
|
# ADD: EXIT SELL PATH WORKSPACE CHECKS
|
|
|
|
|
|
|
|
|
|
# =========================
|
|
|
|
|
|
|
|
|
|
exit_policy_guard:
|
|
|
|
|
objective: "Ensure exits are possible in real mode without permitting shorts."
|
|
|
|
|
checks_required:
|
|
|
|
|
detect_sell_block_without_escape_hatch:
|
|
|
|
|
commands:
|
|
|
|
|
- "rg -n \"buyer_only|assert_buyer_only|Sell orders are disabled\" adapters/ccxt_shim/ | head -n 200"
|
|
|
|
|
require_reduceonly_or_position_source:
|
|
|
|
|
commands:
|
|
|
|
|
- "rg -n \"reduceOnly|ft_exit|fetch_positions\\(\" adapters/ccxt_shim/ | head -n 200"
|
|
|
|
|
require_test_for_exit_path:
|
|
|
|
|
commands:
|
|
|
|
|
- "rg -n \"reduceOnly|ft_exit\" tests/ | head -n 200"
|
|
|
|
|
violation_handling:
|
|
|
|
|
- STOP_ON_FIRST_VIOLATION
|
|
|
|
|
```
|
|
|
|
|
|