From 80924d0d48cded4297383a106269d5c6567597db Mon Sep 17 00:00:00 2001 From: Ludger Paehler Date: Sat, 10 Oct 2026 21:18:04 -0700 Subject: [PATCH 1/2] Stop tracking compiled Python files and forbid committing them Nine .pyc files under koopmanrl/environments/__pycache__/ and koopmanrl/koopman_tensor/__pycache__/ were tracked, among them the bytecode of the removed cartpole environments. They showed up as modified after every run and shipped stale bytecode to every clone. They are build artefacts that Python regenerates on import, so they are removed from the repository. .gitignore listed __pycache__/ per directory and missed koopmanrl/koopman_tensor/ and its observables/ package, which is how those files got in. The per-directory entries are replaced by a general rule, __pycache__/ and *.py[cod], that covers every directory. Ignoring does not stop a force-add, so a local pre-commit hook, forbid-compiled-python, fails on any .pyc, .pyo, .pyd or file under a __pycache__/ directory. CI runs `pre-commit run --all-files` on the tracked files, so a compiled file that is committed anyway fails the Lint workflow. The guides describe the new state: koopmanrl/environments/AGENTS.md no longer warns about tracked .pyc files, and the root AGENTS.md and the contributing page of the docs list the new hook and the ignored compiled files. Co-Authored-By: Claude Opus 5.5 --- .gitignore | 10 +++------- .pre-commit-config.yaml | 8 ++++++++ AGENTS.md | 4 ++-- docs/docs/developers/contributing.md | 1 + koopmanrl/environments/AGENTS.md | 2 +- .../__pycache__/__init__.cpython-310.pyc | Bin 500 -> 0 bytes .../cartpole_control_env.cpython-310.pyc | Bin 7565 -> 0 bytes .../continuous_cartpole.cpython-310.pyc | Bin 5719 -> 0 bytes .../__pycache__/double_well.cpython-310.pyc | Bin 4898 -> 0 bytes .../__pycache__/fluid_flow.cpython-310.pyc | Bin 4736 -> 0 bytes .../__pycache__/linear_system.cpython-310.pyc | Bin 3693 -> 0 bytes .../__pycache__/lorenz.cpython-310.pyc | Bin 4639 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 233 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 977 -> 0 bytes 14 files changed, 15 insertions(+), 10 deletions(-) delete mode 100644 koopmanrl/environments/__pycache__/__init__.cpython-310.pyc delete mode 100644 koopmanrl/environments/__pycache__/cartpole_control_env.cpython-310.pyc delete mode 100644 koopmanrl/environments/__pycache__/continuous_cartpole.cpython-310.pyc delete mode 100644 koopmanrl/environments/__pycache__/double_well.cpython-310.pyc delete mode 100644 koopmanrl/environments/__pycache__/fluid_flow.cpython-310.pyc delete mode 100644 koopmanrl/environments/__pycache__/linear_system.cpython-310.pyc delete mode 100644 koopmanrl/environments/__pycache__/lorenz.cpython-310.pyc delete mode 100644 koopmanrl/koopman_tensor/__pycache__/__init__.cpython-310.pyc delete mode 100644 koopmanrl/koopman_tensor/__pycache__/utils.cpython-310.pyc diff --git a/.gitignore b/.gitignore index 2bbe367..f086144 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ -# Ignore PyCaches -koopmanrl/__pycache__/ -koopmanrl/environments/__pycache__/ -tests/__pycache__/ -koopmanrl_utils/movies/__pycache__/ +# Ignore PyCaches and compiled Python files, in every directory +__pycache__/ +*.py[cod] # Ignore simulation results runs/ @@ -18,7 +16,6 @@ tsne_koopman_tensor_results/ skvi_policy_checks_results/ skvi_sensitivity_checks_results/ koopman_prediction_validation_results/ -koopmanrl_utils/__pycache__/ # Output of koopmanrl_utils/koopman_regressor_comparison.py koopman_regressor_comparison_results/ @@ -32,4 +29,3 @@ ablation_results/ # Output and bookkeeping of the Snakemake workflows in workflow/ results/ .snakemake/ -workflow/__pycache__/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ac0247a..07fcdb9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,3 +28,11 @@ repos: - id: isort name: isort (python) args: ["--profile", "black"] + + - repo: local + hooks: + - id: forbid-compiled-python + name: Forbid compiled Python files + entry: Compiled Python files (.pyc, .pyo, .pyd, __pycache__/) must not be committed + language: fail + files: '(\.py[cod]$|(^|/)__pycache__/)' diff --git a/AGENTS.md b/AGENTS.md index 586b80d..0e35e2e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,7 +32,7 @@ workflow/ Snakemake workflows: Snakefile, rules/*.smk, helpers.py ## Running Code - Run everything from the repository root as a module: `uv run -m koopmanrl.` or `uv run -m koopmanrl_utils.`. Every algorithm and most scripts take `--help` (typed `tap` parsers). -- Runs write TensorBoard logs to `runs/` and checkpoints to `saved_models/` in the working directory. These and the result directories of the scripts (`*_results/`, `results/`, `figures/`, `video_frames/`, `.snakemake/`) are gitignored; do not commit outputs. +- Runs write TensorBoard logs to `runs/` and checkpoints to `saved_models/` in the working directory. These and the result directories of the scripts (`*_results/`, `results/`, `figures/`, `video_frames/`, `.snakemake/`) are gitignored; do not commit outputs. Compiled Python files (`__pycache__/`, `*.py[cod]`) are gitignored in every directory and are not tracked. - Do not execute `koopmanrl_utils/run_skvi_optimization.py` or `run_sakc_optimization.py` to inspect them: they take no arguments, so even `--help` starts four full Ray Tune studies. Read the source instead. Before executing any other script, check that it has an argument parser. - `koopmanrl.{skvi,sakc}_optuna_opt` default to `--cpu_cores_per_trial 28`, which Ray cannot schedule on a smaller machine (the study then idles forever), and to a `--storage_dir` on the authors' machine. Pass both when running them. - The reproduction launchers (`run_optimized_experiments`, `run_ablations`) start hundreds of 50,000-step runs by default. Use `--dry_run` to list the commands, and the filters described in their guides to run a part. @@ -49,7 +49,7 @@ workflow/ Snakemake workflows: Snakefile, rules/*.smk, helpers.py ## Testing, Linting and CI - Run the tests of what you touch: `uv run pytest tests/test_.py [-k ]`. There are no pytest markers; `uv run pytest` runs the whole suite (several minutes). Details and known failures are in `tests/AGENTS.md`. -- `uv run pre-commit run --files ` (or `--all-files`): ruff (`--fix`, format; line length 120), isort (`--profile black`), vulture on `koopmanrl/`, and the basic pre-commit-hooks (whitespace, end of file, YAML, files > 1 MB, merge conflicts, debug statements). +- `uv run pre-commit run --files ` (or `--all-files`): ruff (`--fix`, format; line length 120), isort (`--profile black`), vulture on `koopmanrl/`, the basic pre-commit-hooks (whitespace, end of file, YAML, files > 1 MB, merge conflicts, debug statements), and the local `forbid-compiled-python` hook, which fails on any `.pyc`/`.pyo`/`.pyd` or `__pycache__/` file. - CI runs only pre-commit (`lint.yml`) and the docs build (`test-deploy-docs.yml` on PRs, `deploy-docs.yml` on `main`, Node 20). It does not run pytest, so run the relevant tests locally. - Docs site: `cd docs && npm ci && npm run build`; the build fails on broken links. diff --git a/docs/docs/developers/contributing.md b/docs/docs/developers/contributing.md index 8ba4de0..9fe19d5 100644 --- a/docs/docs/developers/contributing.md +++ b/docs/docs/developers/contributing.md @@ -43,6 +43,7 @@ The repository enforces formatting and linting via pre-commit: - **Ruff** — linting with `--fix` (`ruff`) and formatting (`ruff-format`), line length 120 - **isort** — import sorting with `--profile black` - **Vulture** — dead-code detection on `koopmanrl/` with `--min-confidence 80` +- **forbid-compiled-python** — a local hook that fails on any compiled Python file (`.pyc`, `.pyo`, `.pyd`, `__pycache__/`); these are gitignored and must not be committed In CI, `.github/workflows/lint.yml` runs `pre-commit run --all-files` on every pull request and push to `main`, and `.github/workflows/test-deploy-docs.yml` builds this documentation site on pull requests to `main`. diff --git a/koopmanrl/environments/AGENTS.md b/koopmanrl/environments/AGENTS.md index 7916c8e..a11c152 100644 --- a/koopmanrl/environments/AGENTS.md +++ b/koopmanrl/environments/AGENTS.md @@ -28,6 +28,6 @@ Each environment module calls `gym.envs.registration.register` at import, under * `gym==0.23.1` is pinned; its warning that Gym is unmaintained is expected. * `koopmanrl_utils/movies/` plots only FluidFlow, Lorenz and DoubleWell. -* `__pycache__/` of this directory holds tracked `.pyc` files (including those of removed cartpole environments); they show up as modified after any run. Do not commit them. +* `__pycache__/` of this directory is regenerated on import and gitignored, like every compiled Python file of the repository; the `forbid-compiled-python` pre-commit hook rejects one that is committed anyway (e.g. force-added). See the root `AGENTS.md` for setup, testing and the working checklist. diff --git a/koopmanrl/environments/__pycache__/__init__.cpython-310.pyc b/koopmanrl/environments/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 9f54ac96bbc2949a0712c3b83f12dfd3c70f4c9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 500 zcmZ{g!Ab)$5QdX(cU#LAd;t%Nmm)S7k0K({i;F^gDC{M~ZfZj($&zd>^$~m%U#U0o zKcghad>4XfjPkc!RblbbNt4EMi34nAkf|aU9VAlwFp^Ox6vhj`7$XQ{X zG%xpqZh5k_w${Qp7)tZ3oHbgS#t*C5jIXhq3nt6sJ;HgI!{<22B|&$(M+eaY_tArE z2kFs1X>{jO)VvXwVT$4Fl`X863~C`4ARU`pw`60f%-p(}489B8(kS!9?tZo!7lo)B zTmLh=5gX~1Fb{R3w0aSZvWEQ{Id{OkoBbiu?w>Hul~E1n!+NvrUTRydKweR_=ernk JlGB_X(r;73n9l$J diff --git a/koopmanrl/environments/__pycache__/cartpole_control_env.cpython-310.pyc b/koopmanrl/environments/__pycache__/cartpole_control_env.cpython-310.pyc deleted file mode 100644 index 57604dca805467dbdd884ca9a427297106a8a972..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7565 zcmai3&5s<%b?>j4>FJrBon0=u{Ib-RXowS#vrCGSCE5{}q!hz2wPHv{aoP^r&90i6 zp6%%#Rrf4+*E6RG$ccatxj4vS*FX*ef*b(8eiZmU`|&7EUJS@?*xgXqUEc4Y?S2 zVG!-zma7vimqTse-@5<4^YQg}-?{n7I)yNl-Ikt}!?@e!A~OZ=2H;R+CPdqL@IyyUelMsL_P@&>zOm%doF}Vrr_5@sj*$vmVGaD6Y?U?fTV-o(9lsVZ&#;ZpRj0--va{?Q zT6MO`&SP$cnNaDaZ2jd^c>i8j6wAi*Ay0e}4AUTvZp#50ylYFn2Z`;aspt1{g?o`b zimrQpI`YT_`gC?Xjcrew$~F60k1S#k?{lmR>vkR;9z##nQf4J%}~To;V-kjn3VL>T$cC1M|`btpZv6UBL-4&l(X{5(}atC zZ&@!-4u|}jv#>(;=iuWYns*jjAA1KgD%-_4*^2!zP6FC_0oS&# z-)g_NG*EOfJfm`Bk;943jFHFMccU)g3(xiK_N^Q5*}`M? z)$2EJ*^GBvgt9PPjLwL@U67a(9fh8-mstEd)+Cv`(u9)*`;hwhFn|joz+JuhqEhk& zGZu0gKO7}JX@^q_3VA1;;p7s02}gQGZW(lr-8h9IkOO&xctmc9=G2(c@!%avZuzjc zSWJBa9gIiue7{a`z}a`mml!8!Ol+u~sCiQE)SAWu8SLOlg{GP!ReLdZRG=7Gy2F1m+ygs9EgoL(%$iNqz(Mf`z}MBGbz;5Zk@ zBmT@2Y_5~MPu$(GJ2*LFg*Zfb;X^z1_IPxSWD$-iIY_!-b`V6;(Ii$82`C&9%HtHl zZchDf7~1jNH4*3pM1_3WjUZbO3a|#79K+TnU_Y zIdn85M@TG4hM{-Znr|}YHsn#4q@O^&&;v9r`MSBiJ;!|9?vYq63&w9KtIjG75GjOJnh+f)*l=;~R>0luj+<5<;_I4imZ)|TPK1T`nM`^GR zd5ORa3o&J--e}-OSygnOx}Ff;;pt5z;+A$)7chD*+5_b7W`M}&fI2GyBBukQ)u-3kRM10~2gEDKDjPIr zO6)2#(Y9C>u*NLFI;#P$uzK3)uWl%8FEj9#D* z>evNy*s%+q@X~qa)R#Evs@Z7c5#6_HBtAckBFe4l= zzi=3IyUEJ?0e^;DPf1ERTaz~r_bER_z;am}@s^eWGweu>f1!xm;O)16xz&pYd@CG! zyazkm`qNnKZ9U?26iAS&+y~qf5pv(w58`-;sQKu@18lLz`3jy$SVAlU2c^h>=>Wnzqt$BOtvEPBy<`n*n4P9PtsQ>da51cJbgNw zK__Y=5FeKq#EzLV&V+9wCv-xj(fn+ED50hAiVL75HUL^?e#$#&XC=e|zn2;C>u!GT z>L^M+8*zTbGkq98TNDDmDA2JHp>jDSP9+yaLf-z8AlCP}5AwkgXRvlDlfT2BQYLkE z8^(R~tyjq8NkF_y!?xcd2 zE?ef9>I7q4V%izh2V;}eg^|)FWrAu4RRl)Hm2q_gCX7Dia@0co>bO#@khte%Z85RN zw8j`)v_@7TpaauKt<<-ezNd-4H2d0Emu8_!m#B?vvImZUR~w^#ktRcxS&e9+SBfsb zfJ??Tr?Z5+Ob2JJV^^YHDyj+6)e6=_UnklG^_HRZ8_f8&qA4yaxPBvD-78IUjQV&b zP&#nUR%tiSu4KGojetz-O(FIA76vjM_Lb@Q$RXaKd7Hp%1ine&8w6e_aD~8|1pa`) z1Axq;OaTMM#Zgo-&}!sXvqO{Wfm1p_`bgm^lnk9}o)hJW%n^=Bwk_vOFd$o*fiHwZ z$CMq<_Z{N^Fe~R)1aCt+deIgQV&fmNXF{ws3=`qlQZE}f)$^*QHIM=tYEx|#tquCs zFs{8iJc8DerIKmSg35Q%fo&=yNRqUHpnK`#^A0b1_tLqHh`n_`n5;ahvI-myf{+6IPiC@eh_B9*nyQRz$0ag(iomWmuGT;kC4E&w zI3n6sKGrc1ChC)wNn^4)wwQ$-n^;{Q*T<_J4X^>YQb3H515MU|Q8|GVx#oE7m|WgG zQL!s{Ikv`YvRx_mtjOI=gbVD75K@dU?fd`jw?1A!uF)q~wsL~69Tjq%2~e44TlzwN%PubZtkKTHrKy3cozPQ(TX}oZhnj1)iGK@X&BgnH_s?*FrJGiq?1g%ZcB2HvPeHSg~eD`qB&i}U{|4))>O)Gvx)8$WP zLGG;lQ4oflp{P9U#`x&)gtn&7LQd63u_-xmOph@apVvj+>hc)V@LrG%W8qY(WX>^b z1AMn~{XqC3cMR_UcOv5ft~X8z^ZuS=;Z}h1nkdL1ld1d8Dp8Wl^CLTT8W6Zi(G85^ zGKsHsRtEmepsyc5!Dmb!xz7TY_MDZX*W>g--l;u{1@1#~4mS?p11}{y&0)@JzNkW+ z;7XPsG#|4FE2kpGl&N8+icC#2^{HdgapFz~+&KmzItGyt4@sVq{=o}rL;M6&U*b)E z2tXGAOEUotWQ)94N9!uC32&$tt_pQr1m3{Nx@^}equ`I=ISI?iDTZ3sui=tV);1*O zx^{HoKA3q3Ru--WxzLur1;J*K%8T$y`4@|IM&Ks|$mbT+B3YML8Tv4=i8r|n zU_v|PEln-|-Yi+4nub|1%cgF9%c|Dj6@=MZ5qtQ_bhwouDGHqc)w)@gTn!)c!X&>+ zm7>vLcqrZ?gbxW&;gabeMf;M}tGLO`@8(DUfV7lc1TYk{vH?Rd@n`6ors4Jo2ERI2 F{$Jztl41Y= diff --git a/koopmanrl/environments/__pycache__/continuous_cartpole.cpython-310.pyc b/koopmanrl/environments/__pycache__/continuous_cartpole.cpython-310.pyc deleted file mode 100644 index 34bb481d3b6978c980c51f528a597cb62e886b9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5719 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 diff --git a/koopmanrl/environments/__pycache__/double_well.cpython-310.pyc b/koopmanrl/environments/__pycache__/double_well.cpython-310.pyc deleted file mode 100644 index 0b157ec04aa8d21fa5d270a140f209898658288b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4898 zcmb7I-EJGl72erDE-8wpE!vXO1YIlFi!_jwxMyl5EzAY}P*fLzC$4FI^oS$DuSR?qCaEmzO6 zd!@eD^3Zo$Wl`a-D1Xm*$XaW{<0bBiHC}#VG2^DeD}3#d!PkV@tv<9`>)gC!G^?lB z)o3#1{c4cMX%hDKfwSMBrRc<2E@bBqjjwP1ef;R1(*_od*MFG~@AbqdqSxEG z|HgRdi!>ed!$kIWMRGruY0?)-p6zlyD|mou*A^?9mNH|m)-Xkmf#b68{+7q9d>t#wyvEO=t?)WOk9G~~F7ORdsPYECh>>-EiEpB;cK~)x~ zXfw@C0jTfdeGhN81&p(a5kP~0j9c99P|qYDb2b4z6L#2itcAn^NntmDQIzwDTr6Aj7r&QxifuC5d(L(({*D z=lZmBbvAPKdi<|v&z?z|efnSYnzpif=>ugS#GM1>WC!6uD2L~xfoN{2a+Zg=2zcCA zm9R|)P5stdF)YKRBU;tz2aPF{=h6dlWhMjVgi?m1R<)fbd7KQ>VHUi*g56M-7zxFG zt=MhljD<`ybxw*%NRhO~)RgTs5t*tLd-mfb?hpG5JUrC6v}jZ7MtZ19Q7;YipZ-{# zPw!;y^zhYbN%lZoMOWdzoy{P+-em zzPIG%yMvMPf&hokgWv*~%XR@=(`6O2Vp6+hHCWB6v6{JMZ84i&VBRy^X|M)!fqDO_ zc;k(QlkLuE?Q0Wg+n_dks86rXvb~0Uz9gH*Odh1>7_y)`T^R z)};0hY_p4)x~*r;XVVz0dA?>kXS#CwwOHS@_ay~+xki9Y6&iB1u9~)d8MtDfD)w8& zKGq5=z$-Lf9;7++6NkNPKr;#Pa;k+x0FfWw+lFx3AuM%=hU&nE z10j_oMJ94d`9-<#PM-EvX_&;Y;=X*5h`mJMJb@n)_yK{}090izp-j06=7+t)tE&Z_ zfXnbfrYe+Jf_6Gg@}{X3qj`VIR5=LRy)esyV4)oOBapt1H={$c`D0x@@uE#t_7`9VE(m|@ohL|W)t)DpI79N825j`5W3!*E`} zVz~*R*j>4Ww&@f+)8Um{gfZnJTO#HuyPanFS@SB)PyfCqzNNGA=#G5MMVeosWXA7=hO()H`Kb>bJn!XKo)xIOaY%pYcg@6PG0 z#N9H^OmTMuuddxE?04pod1QU1&5g66A?vwu%)Vk>)N@BR`WEUzs8IlqRSXPso_P@t^0c(GkBzP&7Q3)y~T7 z9J11d$I2)zxEuEc18!0wyS@(j&)_Obb4f{!u4s-C>at;HYq8U;1 z)GUJ1%S1=}gLVZg3Wjvy(x&TGY|}$%zhYL=dMHiCmzR8DVXQ&4`xeqy*vsDD1%Z7{ zaOQS8_I*6x<}UU0Ud!cV6w#(6j9SIs8gG8bHY-j~RyGfWzXw8Ah5H3U+_r%`18k|d zGa$Jb$FQvve3`I^W)8bT=%a+AD}ZgIPHWxVIza`*ZEpV&t0Pc>-LZ*1aW-{5)O5nn zpp>}=SACbqSzC&nBHDL3um907I}n+V%uS)+k7U~SU(K6-o}%$z^Evv%3;@N zTcs@S^h3CU!(|-hxZK831OcbX*&M*4KY>n0SDqK@4f6`jeq3F$!e}MPk)hK29<8|t zpz8o#UY;P>X>*%mC<-YXTgPN-$is}vYKO36_XOFQa2xrUvo{UX2uk=`%DpcfGFs$u zb7I9tgxaTR?(3qlS(Z1jVNvOQND2k#PAF8ll=x%S9J^(^^~mI|@i$b+jr- z9JqraF!8gZuqntLgG5o^nRVPs>bRR!teQ1GwQol~=+H%_E}V+vQR0@j2xxWdgMLPn*QXU}8~>fms!|=l zuF_-*ERs?XRm0gO0MGDP<<%|M+we-B<+&BhyIjAd=QL}|#RVDeCJR0~qrP&IVSg|x z%uY^D9Hv2Qw*r5FU;2a$$d?JNv@hf9rV1n3Yol3(LJN; XwQ6`ex>jLwwpnE+E`#o~OV0lQRGfpT diff --git a/koopmanrl/environments/__pycache__/fluid_flow.cpython-310.pyc b/koopmanrl/environments/__pycache__/fluid_flow.cpython-310.pyc deleted file mode 100644 index 92a4ab1bfb615bb912832bcb0b1fabdc95fc4aab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4736 zcmb7I&5s;M74Pb=>FJ%FU9Z>n`Xf=x2_K`xvj!yrqL9Q6NdyUtu`K~Dpw*tLneFj( z_oTXK;~8eT#K<{djz}O5Yfgj%2X36gKfpgwH^c$?hLjspWPY!DK6WhS zUcL8wuP0w$_YFMW&+_E2XAI+C)Hwb)XuOWMn4;hYX9FW;A!9_F12Z&rZH2b3ozOvT z4b0RHT`gk|YN;1`nsx^D)DL~oZn!2Iye8Hz8XvH5U3lE%b+OL%ihP_{G z|K;s}PVT?-O5=Nx7$!x|MTDh?MThoy{2~3(Q}j^?BV^ow&KNiE8==L| za9h~IId62$2S%51hr9RJLzmaMhyEI`b04)==_9Q3b>2kV=V$o_-@MPlHGYb3fz#lp z`8MkH2Zn8gO=#>yy`S{E>sVEp*-$yLl<`!z1?>zIJ)`n zyYaBhhs*Zv^>{3bB+dx>(qy7fuscJqD{`<~$j-cp)^RY~U4mJAI96U1L1ASS5gZoZ zLE)M%^G)A$EtlyZ+O}mg`aNx4VgWNhb)W3inpTrF%}r|){4M4^*>QGel^58%&`4URPq!G>?DB|kzcgdVBw>okjjyw5T$&I`dwHq z&r?+!WeKh&m0zZzU!j8ZgdyYv@(R&D0e#fTM_GwA+9dN$DrnJ<5PG7hGl+{KiuCo% ztJL=*itphq&Z1~qp5>aPUMT)k*Yz1xZ%sCqD%3k$QQTZ==jEl<<^o z8dIxpq6B*PEvl(?&N#HE_ATsduVu?GVVt~-Lb2QO8PqLjxqszWKA>DgG8|UfoxCWk zGmstYgQyxYqiz<1Q@AL67MQjs zt~t51)Wm0nS5$KRRwSupeh=TL^UUsnHYdq;Pu|1!vDp_Ye~$zSRVGh=?lu;J9lE#q zLmQdD#TFV5j0da>P(YgG9hy^0|Ln;>{9yLHE#ZCqN-0O>{`0{yj0Aj~#c9$hg1j4) z`ywdDaMrZ#FGk*oWtTt}-#A8p~9j)Os^fOhcRZZHtt zGKh;{58>o_S~?3VNC}4dAnA;QqzFcZ;O)gcD+-{{NZxcBZ}A5dQ}$Eq&^)vb?GITW z&b)1)W|U6t5CxSW-LSPWI=ZKlfawxXOMse5xM*8Q!0ggKatLc5nLCE2t%}|@4r?D8 zhu+lVCh+%7^wF5wBL@5F=R)iy@&X_uQjqF&=Cv_rkdkBOq-vXVJ!^HtB}Nzsv_B((Y>*9>lqihWT8h`NO8L09H!@YS*vlsT&4xqyQn708Z)m^>Y^ zDTAkJ2mHVNS_d|mQk;z!J6_t4_VcCfEkNL;^vwHb;){uHigF~g&)~|U|HMMUkPeOm z&kmks0a81$Twfb)Xy1J2g%>G9?~bz2EhFTgnKH*$l?xc#&-tEw6IX`dPO(jfR9vFs zR>fVWCuBaMjql>@B#^W2Z_%fX=E5dSb8Trf-4&D~OQBa=%1sbDic|guL;*}2M-(D; z3mF*&Q|pL6^bkgo+hJ%QA@v)Ei4RF|ozlJQz@}(~Ikgg_i$tYm?#TvbZq+2MQe{>@ zCrSrNHy#c}#^tw&L!gO+>m$5ITWb(iSe)6m~;me;PT+k|%&LXL`e5+|q zn#*I85O%Ux#lsCsnh{q-6e&N7(wvV5L^q=7y-_@>0(C=2J@6r`}fNvtdmC{lnxA(ih72}c3$$%c{R`ST;K98Z*EJH zXl*JNpKNfH*)DqHR5{rw9ga1|$+u`i3xzs^F8afxXjgxkNc}k>>1xA`qLU2AZ5%=L zz!#NWX_M;G1o|V+dNVuFiyl+&68OAVDiys-`F24_+b}%f9w8t7Y_q{k`q+4K*7+aG CTz8KE diff --git a/koopmanrl/environments/__pycache__/linear_system.cpython-310.pyc b/koopmanrl/environments/__pycache__/linear_system.cpython-310.pyc deleted file mode 100644 index fbfa3efd77a98affe2fd072d86bbaa940eb177d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3693 zcmZ`+-H#i$5nnD>tJTNpK778M?KqJW_d^AImlQ?Q9Ma_Mpmo~1*Thb1Kxnbqh?H*S z)vipg&X%BivVlAq{R4^ucaMJWAJE7A4SX$7;GXkVph$khmE@D1P~a?QI2_IgXGmo$ zD^&+A_*)iVU3Z-S5OThifb64d0U#W~5@*2LjM3Ol+_r1KyzSXEB_bwpLV{pu6mt_k;^)2f|eC#S_s@TXxOXK9oi z0P*!O>PSswC3~^Xr8@f>e3R8XaVjHqZw%7l#?d>IcOPWga1f;`*^%i{tg>_<(_HT) zmM_$naqs-97B_AzObu*m91gQM&CU8CdK}7OtTQ1)h#u+=sdc`QYpCfj0Ho7q!ht)O zaGyGDE-na9da`uM>AGJzT_#Gxf4b6!`69r4xiGyQh?=MauZR`Vz_%(^#Tvdfu`V|7 zt$*csPJ0Dz*);X@I(HatJ!@rrseg>F|AiUBrcQ_e0W!gb*Q1e3I@l4Xtm>iZ{U zXyl%{$1D#-FlGO6{^>qJchvAzn0G;`p46u9Df=rw=EvSKpMrK$pR!Z73I3Cn zsdvh*ILGeP?Kh_G8dip@cGVhWtYV#eTsr2&iN21$F)f{9^(i~{u{-Uyy4XJu)v3S0 zN+%a)y09KJfaFcAzi4$MY-@%=7O>ZVZ7=370kf-VuJ4N4C1;a#yZjQ}ozbu4ulKKl z^D_DslG0_c;tf%MMqYb!w#x3*=L>1gm*{h8*Jje1kaP{5ElGQ;N1D7X97K5K;EW@H zXB62UI@CpJVMK&2qV)2JZhYiql=KYON5Xje zp~?-1wuXIf*iFM>k>SuB+|b&1St_+*w=gl5hJ9w(T~nG!m1(o8WLGMgcH}I58-;Fz zIE@FRfi`nIdTen;jyC*O_SlrWNfzb5{DoQ1zSL43MbdaAK=WFKfQq9~Mj!h7TaA_Wf7oeX00Kj*BR>jX}4c=fI_-(T~ z;1*kR8*I~38}2sWW*(@)x7(%ps9Ks_JYUjw=CTjSeNuE>h@UqaQ^BRc>3x9Qd4gn` zGQplvxpMowkM!)9(0%kWO0N5iBe?=#L66EpMG#&k9O>raT2XtD)Z(g+k6Ho1&M}UZ z&50V~G#W}}N=j;(t4(6MNMMUVi@?tatO0~r<0@SkVJ91?D!aVQ2%aenoS?2G~c}bQL%F>mIzxeLmS(@{U!aL-x`lFUQ0JiKsh?t<`VoPv1bz(ADiu0^h_UgD956m^K^SPf zPNwrhc{-xj0#hbp*iAnLMf(6%)^t60vbkizjA_XRvd2Rw8@_1(Oq~<516NWFMN!=X z332)@KF|3JwG{EctVKo1N0AcH<347;p(E2^ldUBk7A#9zkSD2IPtuliPxcuuEcXQd z#94Ft9(i=lIb|m$feQdLK75Lkc1j*DZ_a$%XEQ2Bgm3 zVZJ+gbIBR6@-KPid~DQhNSa6Eb24cb4bo42M!+727iVJgob-j)zaYln15B>{kR}V> zS9BqLY=kHi;cr9<@t`VTPc?k*M%R$K)#j|-R!Bi{BUhvRuqnoAG>AL8nRT0qeG4{= zx8P27vEb84MFWX6)(g^&MO%<;A~g4!Q954GXvce$Ak9c)q8TX_jdvE)Mf|>J%}sls zE-zZFx-0XMN?*}sG5rdE)bi*wlveL5g4Tg3N@ujNJ+#`s8Az)7MsOra`@43C{v+6A_~1cP}OYBrL%$;h%E}Him2iq zM})-7#(Gq)kHDm_b>j{!GByLaAz2X7@u!CdvGcu%X!}K6_hKFxo)Z1Og{u z+c$!>pd9eP5BS;zMf0t?@$q=WyI{6`Z;Yo`IvNbe#WnUvFcpuWibI}<6{Qqy2zXMYWm{$M* diff --git a/koopmanrl/environments/__pycache__/lorenz.cpython-310.pyc b/koopmanrl/environments/__pycache__/lorenz.cpython-310.pyc deleted file mode 100644 index 1e98aef039d0d1fee0990544cd35723da4482980..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4639 zcmb7I&668P6`!6jjXrn1UOVg9fhhAjAJ-Wl2>zvCMk zcUTz(oxqH}VRcmN)G+otb z>tqwVXVsgT6zS~p;g#8oce89fic>k<7U^LkvvefVTx|~x#p?xO+tGHybsZ~m8jZ6g z&Gng4d@mB?L}gq=IB=}GB-xXVv_?%00EE?H+=8YUx9?jWho9rFaD{il>e&yh9^)SO z?>9R>ukZlt6<*~v^g*G8PL(%#3-cQGt?~8ytW)P__y#ZyewJ^dZ$7YGtJ8vx&TGGr zyUWb^1#r<-@V$dieTEgz=2nFF17zIcZl6Xr$zeuL?qcrd9-zl7fIbfZAsJwhS0B~p z)&Q76h1*-!rgcpG>R*FzEa*Vf#JGM0>OtcOXAYW24tBLL^6M5sUh6yPD|2Uytbk_r zoalqP)pz=iIcbgdaJ$d2ZoU$~4*VI=7V>PAGj_~)V-wt?v*lTJ(2!Kka^EK5`xbA0 z3R=*eE9b3pem;M0um$>a_|D_Qo8{HP1-|x>^z=NaF9K`!4jf*)0F3~D=_$Nj;$JAa zUBaFhXx|FAZ}e&JH@St^T;Dr!@MI_SmVJC^Kl*$z*ewR1@0Xa*_jgaol}|1K^nYcV zw<~Gy$(LyT|33cr-+yuE{kPgq$>QpQ*Nw#h?zLRp{TFtk-Po1u=-RG!hS^8jJxKZo z+EWMdSZI&u)3IoW@V7k9MZ}YluEkyQPBX3-Xc?z{p&R8wF|&CttKbV(Nq-b;M;>I_ zy(98i+v!-l>O+}#9QawsnG%>qI4+hlp6W(7OYKX@BS4B82VVycv)4Ye6m38*bq&C`eO9w;uJ8EFd~D0!VvTa_vX_|u z<(AWOHh^Du)|tyTSn%bRw^fd6-fXRiP}>XMd!!P2EAY?9_} zTV5d=I`1*EQ51EDu~JcF9$3CYYp(*8+k?dcz0Or;s zlHWeI>j-u7ZJ_W#Kc&t&6-W~O)8|*E_$Zbf5`2KwFUVF}Y_`7CTe-M$KIx7=;%5wb zp}PS?3bG$TgD@{^;F1p4kw6}K9046GKC}qqIwqY~HcM>|7);99lWSmiLISjdLbKN} z)?N-rJLgVkPK1~V?ToXJRupfHr&1_h=}Mt_rJYgy70quPiY|D=W;qPa zJVKW)M32y5SD0_lE|h9`2Bib4MWgZJJ>+#v7B8@m@!|zYGWi|>^Z2J0u=xb{RXjrYdYF#4Q*N@&a*afI+oZOz zxczo`qZbZEFArlC?jb9@Oh>0-5i-JYHcYzHFj3(|3BJALv!VdXfTV!4_*4&I&VJ_{ z*+nNB9oJ}nGQtmt= z4&E^X&I1MHNr2*0MK{zFa#%g4?iX;WEB0%a7jn8^f#{ z57nF7*t%!@WZ^yUkdzStbHE>HM3H}`V(ATmQRIoOntOhB_8CX4#4(~IZztyJWq_O_ zDaBEw#@t5vj#$N=hc4v=6r(P8|AfN6hv&z$`|)kmgGE!BwsSx7x_e{UkL`w^`{OB$8>RAxV(6hhA6AV>G{S;wY&fB)mNxe z?oCqd=MieZRNK=l+DGg;$as-3kcBA~$qxuzAn+RiV2w3W9yZ2_;v^fUPlsOC`!fiP z#XP?bqYO%m>8->SGLuDkR}|7sx-}Klu}#0c9#J|&Jw<6PqQr-IL6~F4KlY^5gMXq+Gs97z%TX`;q0M zt}-cH*AS6WLL*l2r!VSKDEJh_icV>vnryL_Q$uYztCx2siXv~VQK^a)AfiauqG*)y z$&kj4DEe>`4~rG~Di}%1*4n}EcvFFyilevysY%`<@BsmHmAe?}W?8;<#c;SN;fzba zMRcZ^qZ*E?O0@|PSOMGmVXzid0w?fmPVlYuO-U5(br{8T4EHFd=ub!5ODCi8)Pytn zE{KYsA?L6}|CUhO#eX%VDc~i&sa{jvWIWx*6+|C+QCO2Pq>LDlwzcz<^w1pogkDbr eUGPSsqBrU1p`!5FumZ$6igfhn+6^fCyz@T`k7VEg diff --git a/koopmanrl/koopman_tensor/__pycache__/__init__.cpython-310.pyc b/koopmanrl/koopman_tensor/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 3de3394b7b13c7ba3fde4987edf273db4f32dd33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 233 zcmYk0F$w}f3`IxTLWDhth2{bxV(X%?7GgCF8a3=rGR%yHp23TFC0h&cVC5_->xaDX zk`$3V@2ix}(^AtP4gS+fGEEh-gq>QcL1%GOz8SZ8UEwGep>_t3HF{W!ub@QYz4$F! z{##VNx8Yj({p_`DYH&v2DfB*mh diff --git a/koopmanrl/koopman_tensor/__pycache__/utils.cpython-310.pyc b/koopmanrl/koopman_tensor/__pycache__/utils.cpython-310.pyc deleted file mode 100644 index a1194d8bc98529bbb267e6642208000bae282449..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 977 zcmZWoOK%e~5cXqtvuzXl0EC1PiV&iT1X;Kvgh2E{6{HraqL*kJyTr||z4AIOt|D@I(u#h=UDD}+zsnKADTehLR;fV*(t<1Vc!;y0~bwdBQgq386{hgPXP0TQ#fss zXQX_30QNXPz(TAQcBc2+$-tN*Pj%NxT^gH|>An=*+z6SK$&@D3TDwraK_)#r*lER{ znbHSE>iRyCpH%5eALr>n3S|K|h15RSGfMktW)+BGUbI4g<9Zyh*85#0{L+kAnL5n=jlCugFZO3w*ly3t6Yo#4wrQAf&z3Cq`M-WkHcd&Bb@>1cN`Z%MRGXi zC-gIQpos{mZa{N{lL#APi?Az1S2REVkLFs(Vj31(&teis^Y8nzxvMhSTs>M|Z3-jH zrZ%ow5!&|5?zCz)!t3}ni%I+CHMrj~Zp{p}cw?=x7XK29@Ag4vQqc Date: Sat, 10 Oct 2026 21:24:48 -0700 Subject: [PATCH 2/2] Move the note on compiled files to the pre-commit bullet of AGENTS.md Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 0e35e2e..5d0d6ab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,7 +32,7 @@ workflow/ Snakemake workflows: Snakefile, rules/*.smk, helpers.py ## Running Code - Run everything from the repository root as a module: `uv run -m koopmanrl.` or `uv run -m koopmanrl_utils.`. Every algorithm and most scripts take `--help` (typed `tap` parsers). -- Runs write TensorBoard logs to `runs/` and checkpoints to `saved_models/` in the working directory. These and the result directories of the scripts (`*_results/`, `results/`, `figures/`, `video_frames/`, `.snakemake/`) are gitignored; do not commit outputs. Compiled Python files (`__pycache__/`, `*.py[cod]`) are gitignored in every directory and are not tracked. +- Runs write TensorBoard logs to `runs/` and checkpoints to `saved_models/` in the working directory. These and the result directories of the scripts (`*_results/`, `results/`, `figures/`, `video_frames/`, `.snakemake/`) are gitignored; do not commit outputs. - Do not execute `koopmanrl_utils/run_skvi_optimization.py` or `run_sakc_optimization.py` to inspect them: they take no arguments, so even `--help` starts four full Ray Tune studies. Read the source instead. Before executing any other script, check that it has an argument parser. - `koopmanrl.{skvi,sakc}_optuna_opt` default to `--cpu_cores_per_trial 28`, which Ray cannot schedule on a smaller machine (the study then idles forever), and to a `--storage_dir` on the authors' machine. Pass both when running them. - The reproduction launchers (`run_optimized_experiments`, `run_ablations`) start hundreds of 50,000-step runs by default. Use `--dry_run` to list the commands, and the filters described in their guides to run a part. @@ -49,7 +49,7 @@ workflow/ Snakemake workflows: Snakefile, rules/*.smk, helpers.py ## Testing, Linting and CI - Run the tests of what you touch: `uv run pytest tests/test_.py [-k ]`. There are no pytest markers; `uv run pytest` runs the whole suite (several minutes). Details and known failures are in `tests/AGENTS.md`. -- `uv run pre-commit run --files ` (or `--all-files`): ruff (`--fix`, format; line length 120), isort (`--profile black`), vulture on `koopmanrl/`, the basic pre-commit-hooks (whitespace, end of file, YAML, files > 1 MB, merge conflicts, debug statements), and the local `forbid-compiled-python` hook, which fails on any `.pyc`/`.pyo`/`.pyd` or `__pycache__/` file. +- `uv run pre-commit run --files ` (or `--all-files`): ruff (`--fix`, format; line length 120), isort (`--profile black`), vulture on `koopmanrl/`, the basic pre-commit-hooks (whitespace, end of file, YAML, files > 1 MB, merge conflicts, debug statements), and the local `forbid-compiled-python` hook, which fails on any `.pyc`/`.pyo`/`.pyd` or `__pycache__/` file. Compiled Python files are also gitignored in every directory, so none are tracked. - CI runs only pre-commit (`lint.yml`) and the docs build (`test-deploy-docs.yml` on PRs, `deploy-docs.yml` on `main`, Node 20). It does not run pytest, so run the relevant tests locally. - Docs site: `cd docs && npm ci && npm run build`; the build fails on broken links.