Repository navigation
Version 2 - #22
Merged
Merged
Version 2#22
Conversation
- Remove tracked sampler.py.backup and reagent.py.backup - Remove .gitattributes LFS rule: data/ is gitignored so the rule matched zero tracked files (git lfs ls-files was empty) - Drop the matching no-op lfs: true / git lfs pull steps from the test and publish workflows Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
The legacy tree (17 modules, 1.2 MB) had no importers in src/ or tests/ and shipped in every wheel. The Zhao 2025 RWS reproduction remains available at tag v.1.2.0. BREAKING CHANGE: TACTICS.thompson_sampling.legacy no longer exists. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
baseline.py could not execute: it read config.evaluator_class_name, evaluator_arg, reaction_smarts and reagent_file_list, none of which exist on RandomBaselineConfig, and called create_reagents(ts_mode=...) with a keyword that signature never accepted. run_random_baseline and run_exhaustive_baseline were exported but had no callers anywhere. BREAKING CHANGE: RandomBaselineConfig, run_random_baseline and run_exhaustive_baseline are removed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
- evaluators.py: drop test_fred_eval / test_rocs_eval / test_ml_classifier_eval stubs and the __main__ block (never collected by pytest; constructed real OpenEye objects) - top_two_selection.py: drop unreferenced disagreement_rate and component_disagreement_rates properties - reagent.py: drop compatible_smarts property, add_compatible_smarts, is_compatible_with (zero callers; set_compatible_smarts stays) - disallow_tracker.py: drop unused sample() and the random import - ts_utils.read_reagents: drop the smarts_compatibility parameter that no caller ever passed (the sampler applies compatibility via SynthesisPipeline.auto_detect_compatibility instead) - config.py: drop unused model_validator, Literal, logging imports Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
- Delete conformer_gen.py: never imported anywhere, and its unguarded module-top openeye import made it unimportable without the optional [openeye] extra - generate_products.py: drop generate_combinations_parallel (no callers) and the deprecated LibraryEnumerator class - enumeration_utils.py: drop read_all_reagent_files, smiles_to_mol, and find_reactants_from_product_code (no callers; the last was also broken -- a nested closure passed to a spawn-context Pool) - constants.py: drop derived SALT_FRAGMENT_SMILES (never consumed) - _validator.py: drop unused rdkit.Chem.Draw import - Trim now-unused typing/polars/os imports Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
- Delete library_analysis.py (LibraryAnalysis) and library_analysis_utils.py: their only consumer was the dead LibraryVisualization class or a gitignored notebook - visualization.py: delete LibraryVisualization (371 lines, sole user of seaborn/matplotlib/pandas/IPython in this module) and get_performance_summary; the module is now polars + altair only - diagnostic_plots.py: delete eight plot functions with no callers (disagreement/scale/TT-TS-decomposition trajectories, posterior heatmap, convergence comparison, min-GMIC-vs-advantage, oracle flexibility, GMIC-vs-oracle) and the unused _rolling_mean helper. The eight functions used by tutorials are unchanged. - library_analysis/__init__.py exports TS_Benchmarks only BREAKING CHANGE: TACTICS.library_analysis.LibraryAnalysis, LibraryVisualization, compile_product_scores and compile_product_smiles are removed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
useful_rdkit_utils cost 3.85 s of the 7.1 s import (it pulls umap -> pynndescent -> numba -> llvmlite, ~149 MB) to supply MolWt and two Morgan-fingerprint wrappers. Replace with rdkit.Chem.Descriptors.MolWt and a shared rdFingerprintGenerator Morgan generator (radius 2, 2048 bits) -- verified bit-identical, and it drops the deprecation warning uru's smi2morgan_fp emitted. pandas was used only to read the LookupEvaluator table and the validator's CSV reagent files; both now use Polars (null score cells map to NaN so the sampler's NaN-skip path is unchanged). dill was imported solely by multiprocessing_utils.initializer, which set dill.settings -- a value the stdlib Pool never consults. Delete the module and the initializer= kwarg; the pool already pickled plain dicts and SMILES strings. seaborn's single call site was deleted with LibraryVisualization. import TACTICS: 7.1 s -> 1.0 s. BREAKING CHANGE: TACTICS.library_enumeration.initializer is removed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
product_scores.csv (12.1 MB, 94% of the uncompressed wheel) becomes product_scores.parquet (4.7 MB, zstd). Same 499,720 rows and schema (Product_Code: str, Scores: f64); round-trip verified equal. LookupEvaluator already dispatched on the .parquet extension. BREAKING CHANGE: the bundled dataset path is now TACTICS/data/thrombin/product_scores.parquet. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
…nches Config fields that were plumbed end-to-end (Pydantic field -> factory kwarg -> __init__ assignment) but never read by any code path: - RouletteWheelConfig: exploration_phase_end, transition_phase_end, min_observations, cats_exploration_fraction (+ their validator) - BayesUCBConfig: exploration_phase_end, transition_phase_end (+ validator); its min_observations and cats_exploration_fraction ARE live and stay - TopTwoConfig: min_observations (self-documented as inert) ThompsonSamplingConfig.max_resamples: the early-stop branch in search() compared against a counter that was reset every iteration and never incremented, so the field had no effect. Removed from config, sampler, presets and docstrings. Sampler diagnostics: the 3-column (cycle, component_idx, criticality) fallback was reachable by no shipped strategy -- every strategy that implements get_component_criticality also implements get_component_state. The empty frame now uses the three columns all enhanced schemas share (current_cycle, component_idx, criticality) and diagnostics.compute_convergence_point no longer sniffs for a 'cycle' column. Strategy and warmup config models now reject unknown fields (extra='forbid') so scripts passing removed knobs fail loudly. BREAKING CHANGE: the fields above are removed; passing them raises ValidationError. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
The preset existed to reproduce Zhao et al. (2025); that reproduction
is pinned at chem-tactics 1.2.0. The Boltzmann-weighted posterior
update it used is unchanged -- it remains the update rule for the
recommended and recommended_rws presets.
BREAKING CHANGE: get_preset('legacy_rws') raises ValueError.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
…ncedWarmup StandardWarmup (random partners with replacement) was the baseline comparison arm and consistently the weakest warmup. Remove it and its config model. ThompsonSampler(...) constructed directly with no warmup_strategy now defaults to EnhancedWarmup(), matching what from_config() and every preset already did. The unreachable 'else StandardWarmup()' branch in from_config is gone (config.model_post_init guarantees warmup_config). Three tests skipped as 'Warmup has edge case with small test data' pass with the Enhanced default and are un-skipped. Three others still fail, in search() rather than warmup (an all-NaN slice on a tiny library, and a None evaluator in a pool worker with product_library_file); their skip reasons are updated to say so. BREAKING CHANGE: StandardWarmup and StandardWarmupConfig are removed; the direct-construction default warmup changes from Standard to Enhanced. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
RouletteWheelSelection, TopTwoSelection and BayesUCBSelection each carried their own copies of the heated-component index, round-robin rotation, flexibility-weighted rotation, and (for the first two) the GMIC computation. The two GMIC bodies had already drifted -- one wrapped its result in float(), the other did not -- and a 2026-06 comment in TopTwo explained its gate removal as 'for consistency with RouletteWheelSelection', which is the tell that this should be one implementation. New private module strategies/_thermal.py: - ThermalCyclingMixin: current_component_idx, rotate_component, rotate_component_weighted (template method; exactly one rng.choice after deterministic weights), _rotation_flexibility hook - GMICCriticalityMixin(ThermalCyclingMixin): _calculate_gmic_details, _calculate_gmic, get_component_criticality, GMIC-weighted _rotation_flexibility with the shared _cached_gmics cache RWS and TT-TS inherit GMICCriticalityMixin; BayesUCB inherits ThermalCyclingMixin and supplies its criticality-weighted hook. TT-TS's _component_gmic is renamed to _cached_gmics. RWS's write-only _mean_criticality is dropped (BayesUCB keeps its own, which is read). Also deleted: RWS.select_batch (60 lines duplicating select_reagent; never called by the sampler -- callers fall through to the base default) and BayesUCB.select_batch (byte-equivalent to the base default). adapt_temperatures and reset_temperature stay per-class: their zero-unique branches genuinely differ in direction, and merging them would hide that; cross-reference comments added instead. Verified RNG-identical: seeded 30-cycle thrombin runs for all three strategies hash identically before and after (selected compound sequence + heated-component sequence). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
Before: import TACTICS took 7.1 s, and even a pure config import paid
~6 s, because config.py -> core.evaluator_config tripped
core/__init__.py, which eagerly imported the sampler, every evaluator,
and their dependencies (RDKit, sqlitedict, and -- via strategies --
scipy.stats).
New TACTICS._lazy.install() gives a package a PEP 562 __getattr__ over
a {name: submodule} map; the four hubs (TACTICS, .thompson_sampling,
.thompson_sampling.core, .library_analysis) now resolve names on first
access. Every existing import path keeps working: top-level
(from TACTICS import ThompsonSampler), hub (from
TACTICS.thompson_sampling import TopTwoSelection) and full submodule
paths. TYPE_CHECKING blocks keep IDEs/pyright informed. Spawned
multiprocessing workers resolve classes by module path, so parallel
evaluation is unaffected.
Leaf deps deferred to the call that needs them: scipy.stats in
BayesUCBSelection._compute_ucb_indices; matplotlib.pyplot via a
_pyplot() helper in diagnostic_plots (also replaces plt.cm.get_cmap,
removed in matplotlib 3.9, with matplotlib.colormaps). altair's import
in visualization.py is guarded with an install hint.
pyproject: matplotlib and altair move from dependencies to a new [viz]
extra; [tutorials] includes them. Core dependencies are now pydantic,
rdkit, numpy, scipy, polars, tqdm, sqlitedict, joblib.
tests/test_import_time.py pins the contract in fresh subprocesses.
import TACTICS: 7.1 s -> 0.04 s. Config import: ~6 s -> 0.14 s.
BREAKING CHANGE: plotting now requires pip install chem-tactics[viz].
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
- pyproject: version 2.0.0 - CHANGELOG: full Removed / Changed / Performance / Fixed entry - README: drop legacy_rws row; document the [viz] extra - docs: library_analysis.rst rewritten around what exists (TS_Benchmarks + the eight real diagnostic_plots functions -- the old page documented five plot functions that never existed); StandardWarmup anchors, legacy_rws rows, max_resamples and the inert phase_end fields removed from configuration/thompson_sampling/ strategies.rst; conf.py autodoc mocks trimmed. Sphinx builds with no warnings. - tutorials: StandardWarmupConfig -> EnhancedWarmupConfig; drop max_resamples kwargs; interactive_sar_explorer uses Polars; remove the BoltzmannConfig UI from thompson_sampling_tutorial (that class never existed, so the notebook could not be opened). All three pass marimo check. - delete src/TACTICS/README.md: a stale duplicate front page describing a Boltzmann strategy, Stratified/Latin-Hypercube warmups and a run_ts() in main.py, none of which exist; not packaged, not linked. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
conf.py - Import the installed package instead of a sys.path hack that pointed at the repo root (the package lives in src/ and was never importable) - version/release from importlib.metadata (were hardcoded '0.0') - autodoc_mock_imports = [] -- the real package is installed and mocks at sys.meta_path[0] would shadow it and break Pydantic model import - MyST dollarmath + amsmath, heading anchors to depth 4, ready for the theory pages - GitHub/PyPI icon links; html_context + use_edit_page_button so the 'edit this page' item actually renders - Fresh polars intersphinx URL; linkcheck settings - Two hooks for Pydantic models under autodoc: render a Fields block from model_fields (descriptions and defaults read from the code) and hide model_*, validators and the generated __init__. Dormant until reference pages land. pyproject [docs]: version floors (sphinx>=8,<9; sphinx-design>=0.6.1 for Sphinx 8) plus matplotlib/altair so a docs install can import library_analysis for autodoc. docs.yml: install -e '.[docs]' instead of a hardcoded list that duplicated the extra; build with -W --keep-going; checkout@v4 / setup-python@v5 with pip cache; upload the HTML as an artifact on PRs; separate non-blocking linkcheck job; run on PRs to streamline/v2. Makefile: html target mirrors CI flags; clean/linkcheck/livehtml. custom.css: drop rules with no consumer (badges, migration table, returns table, graphviz-wide, version badge, depends-on, method category, class-methods, sd-* overrides pydata already provides). 415 -> 284 lines. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
…s_filename Docstrings the API reference needs: - Evaluator ABC: the contract (evaluate(mol) -> float, counter, NaN = skip) and how evaluators are built from configs - each of the 8 evaluator classes: what it scores, its input_dict keys, its paired *EvaluatorConfig, speed/licence notes; CustomEvaluator states the picklability rule for processes > 1 - ThompsonSampler: full NumPy-style Parameters block (7 of 12 were undocumented) and the direct-construction call order API: - TACTICS and TACTICS.thompson_sampling lazy hubs now export Evaluator, CustomEvaluator and all 16 config models (strategy, warmup, evaluator), so docs can show one canonical import style - RouletteWheelSelection.__init__ drops its **kwargs, which had no handler and silently swallowed typos (criticality_metric='shannon' was accepted with no effect); BayesUCBSelection keeps its deprecated- name warning and raises TypeError for anything else - Remove ThompsonSamplingConfig.results_filename: from_config never passed it and the sampler never wrote it. Preset output_dir now only places the log. Remove the unread ThompsonSampler(cats_manager=) - bayes_ucb docstring default 0.5 -> 0.3 (matches code); get_diagnostics '17-column' -> 18 Tutorials: fix stale notebooks/ paths and the manuscript_plots.py reference in module docstrings. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
docs/source/snippets/<block>_<name>.py hold every code example the guides will show. Each is a runnable script on the bundled thrombin data with a [start:tag]/[end:tag] region for literalinclude, its code inside main() (required so processes > 1 snippets survive multiprocessing's spawn re-import), and smoke assertions outside the displayed region. tests/test_doc_snippets.py runs each one in a temp cwd via runpy (honours '# requires: viz|openeye' headers with importorskip), and asserts the README quickstart is byte-identical to the [start:search] region of search_minimal.py -- the two can no longer diverge. README quickstart now runs as-is on the bundled data (the old one used placeholder paths). test.yml installs [test,viz] so viz snippets are not permanently skipped in CI. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
- base_strategy.select_reagent / select_batch: rewrite in Google style (the 'Parameters:' header with both a colon and a dash underline was not recognised by napoleon, so the raw **kwargs reached docutils as an unclosed strong marker; inherited by UCB/EpsilonGreedy too) - visualization.get_barplot_TS_results_data: proper NumPy section headers and the blank line before Returns - diagnostic_plots.plot_rws_diagnostic: the indented axis description parsed as a block quote; make it a list Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
docs/source/reference/{library,scoring,search,scale,inspect,visualise,
extending}.rst -- every public symbol documented exactly once, by full
submodule path (the package hubs are lazy; autodoc on a hub renders
empty). Pydantic configs render a generated Fields block with the
description and default of every field, read from model_fields.
Three conf.py findings on the way:
- autodoc_default_options = {'members': True} silently overwrote every
explicit ':members: a, b' list (a bool default takes the else branch
in process_documenter_options). Dropped; directives name members.
- napoleon rendered 'Attributes:' sections as .. attribute:: object
descriptions, colliding with real @Property members
(SynthesisPipeline.reagent_file_list). napoleon_use_ivar = True.
- autodoc_class_signature='separated' added __init__/__new__ entries
that bypass autodoc-skip-member, leaking Pydantic's boilerplate.
'mixed' puts the signature on the class line; the hook strips the
boilerplate napoleon merges in.
guides/*.rst and extending.rst are stubs so the reference pages' links
resolve; the guides replace them in the next phases. Root toctree gains
Guides and Reference sections; the 1.x pages stay until superseded.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
docs/{thompson_sampling_equations,bayesian_ucb_equations,
search_performance_metrics}.md -> docs/source/theory/, with a theory/
index in the root toctree. MyST dollarmath renders the LaTeX (242
display blocks in the TS document); the six cross-file anchor links
resolve unchanged under MyST's GitHub-compatible slugs.
Structure: hand-maintained tables of contents removed (the sidebar
replaces them); the subtitle H2s become italic lines and the '---'
rules go, since a transition at a section start is a docutils error.
Content that was false about the 2.0 API:
- TS equations §10: max_resamples dropped; seed/processes/
min_cpds_per_core/product_library_file added; RouletteWheelConfig
table rebuilt from the live fields (exploration_phase_end,
transition_phase_end, min_observations, criticality_metric were
never RWS fields and the example raised ValidationError); a Top-Two
section added -- the recommended strategy had none; StandardWarmup
section removed; Enhanced relabelled from 'Legacy' to the default it
is; tuning table updated
- Bayes-UCB §10: exploration_phase_end/transition_phase_end replaced by
the real cats_exploration_fraction in the table, effects and all
three examples (which raised ValidationError)
- §6.6 warmup comparison row reflects 2.0
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
guides/01_library.rst replaces library_enumeration.rst (1,431 lines of hand-written reference now generated in reference/library). Core: define the bundled thrombin library, make one product, validate SMARTS coverage against the real reagent files. Build on it: multi-step synthesis, alternative SMARTS, protecting groups/salts, enumerate everything without TS. Three snippets executed by the suite. read_reagent_file is now exported from TACTICS.library_enumeration -- it is the natural way to read a reagent file and the guide needs it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
Core: the lookup table on the bundled data, and the two decisions that travel with every scorer (direction lives on the strategy; what 'missing' means -> default_score). Build on it: your own Python function via CustomEvaluatorConfig with the module-level rule for parallel runs; the table of all eight scorers by cost and requirement; using an evaluator class directly. Gotchas cover the drift-audit findings (FPEvaluatorConfig has no radius/bits; evaluator configs are permissive). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
guides/03_search.rst replaces configuration.rst, thompson_sampling.rst and strategies.rst (2,753 lines; the reference half is now generated in reference/search). Core: the five calls, the four parameters that matter first, what search() returns, and an Imports box explaining the lazy hubs. Build on it: the three presets with their benchmark numbers, a hand-built config, how each strategy turns posterior draws into a pick and how GMIC chooses the heated component, Enhanced vs Balanced warmup with their actual costs, driving the sampler directly. Gotchas include the two crashing 1.x examples and the unseeded-warmup caveat. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
Core: processes / min_cpds_per_core, how workers rebuild the evaluator from its config (and why that is the parallel-safe path), when parallelism pays. Build on it: product_library_file, budgeting a run (max_evaluations; what warmup costs for an expensive scorer), cluster notes incl. the __main__ guard for spawn. Snippet runs a real 2-process search on the fingerprint scorer. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
Core: track_diagnostics and the three accessors -- get_diagnostics, get_posterior_landscape, get_sar_summary -- with what each returns. Build on it: the columns worth watching per strategy (TT-TS 12, RWS 18, Bayes-UCB 18), the six analysis functions, and how to stack runs for the replicate-averaged plots. Snippet runs a tracked search and exercises compute_posterior_entropy / compute_convergence_point / format_sar_report, writing Parquet for the next block. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
guides/06_visualise.rst replaces library_analysis.rst -- the last of the six 1.x pages. Core: TS_Benchmarks comparing the two recommended presets against the exhaustive thrombin scores (two seeded replicates each), with the three chart methods. Build on it: the eight diagnostic plots grouped by what they need -- single-run, replicate-averaged, layered -- and the phase/replicate/method column contract, which nothing else documented. Gotchas: no_of_cycles means replicates; reference column order; sort_type must match mode. Both snippets require [viz] and are skipped, not failed, where it is absent. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
cats_diagnostics_analysis.py, cats_vs_rws_tutorial.py, thrombin_recovery_benchmark.py and the empty library_enumeration_demo.py were untracked working files whose fate was deliberately deferred; an over-broad 'git add -A tutorials' in the docstring commit swept them in. They still use 1.x APIs (StandardWarmupConfig, max_resamples, pandas) and are not part of 2.0. Files stay on disk, untracked. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
extending.rst: the contract for each of the three base classes -- the kwargs select_reagent receives, the hooks the sampler probes with hasattr, the attributes it reads off a warmup -- and how to reuse the _thermal mixins. The custom-strategy example is a snippet the suite runs (a GMIC-mixin strategy driving a real search). Also: how the package is laid out and why imports stay lazy. tutorials.rst: card gallery of the nine tracked marimo notebooks with what each exercises (marimo files cannot be rendered by myst-nb). changelog.md: MyST include of CHANGELOG.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
index.rst: one sentence, six cards in dependency order (Library -> Scoring -> Search -> Scale -> Inspect -> Visualise), four smaller cards (Extend, Reference, Theory, Tutorials), the ten-minute quickstart pulled from the same snippet the README shows and the suite runs, install extras. Hidden toctrees drive the sidebar. README: badge row deep-links to the guides and tutorials; the evaluator table gains CustomEvaluatorConfig; the tutorial table lists all nine notebooks (was four); doc links point at the search guide, reference and theory pages instead of the site root. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
The word survived in two places after the redesign and meant the wrong
thing in both.
Theory pages: the derivations of standard Thompson Sampling and the
published RWS (Zhao et al. 2025) are the baselines CATS and TT-TS are
measured against and stay -- but the headings said 'Legacy', which now
reads as 'the deleted code'. Relabelled as Baselines / Published RWS,
with a note at the top of section 4 saying the 1.x implementations
were removed and where each baseline lives now (GreedyConfig; 1.2.0).
Section 4.2.5 claimed Boltzmann-weighted updates are 'Legacy Only' and
that CATS uses uniform updates -- false: the recommended presets run
with use_boltzmann_weighting=True and the 86.1%/85.5% figures were
measured that way. Rewritten as the switch it is, keeping Theorem 4.1
and stating the trade-off it captures.
Source docstrings that autodoc carries into the reference described
live features as legacy: EnhancedWarmup ('the legacy warmup approach'
-- it is the default), use_boltzmann_weighting ('legacy RWS'),
adaptive_temperature ('legacy-inspired'), the Shannon criticality
metric. Reworded. The only remaining mention is presets.py saying
legacy_rws was removed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
Header: engineering-interlude note (hypothesis unchanged; 2.0 removals point at CHANGELOG; Boltzmann weighting kept; HPC3 runners need porting). Established Results: 2.0 outcome; Boltzmann is the production update rule. Ruled Out: two entries with Heptabase cards (46511b3d: deleting Boltzmann as 'legacy' -- rejected on verification; bb22697e: Sphinx autodoc traps with lazy hubs). Open Questions: unseeded EnhancedWarmup, three skipped search-phase tests, API warts from the docs pass, benchmark-data storage + HPC3 script porting. Session log trimmed to the 10 most recent entries + this session; 21 older entries archived to docs/handoffs/session-archive-2026-05.md (appended) and session-archive-2026-06.md (new). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGA4NaBZPsgXgze4qPnmND
Under Linux's default fork start method a worker rebuilding a
LookupEvaluator deadlocked in polars.read_csv: the child inherits the
parent's Rayon thread pool without its threads. This hung every
processes > 1 run and left the CI test job stuck in
test_parallel_matches_sequential until the 30-minute timeout.
macOS/Windows default to spawn, so it never reproduced locally.
ParallelEvaluator now uses multiprocessing.get_context("spawn"),
matching the pool in library_enumeration. Verified by forcing fork
globally: the 14 parallel-evaluation tests hang without this change
and pass in under 2 s with it; full suite 326 passed, 5 skipped.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XqsaX2SHzvmoeHmbAu6F8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Version 2 streamlines the code base further and removes the legacy methods. Updates the documentation and makes it easier for the user to use the package.