Skip to content

M-ISSUES backlog + M-THEME token map - #59

Merged
NCCU-Schultz-Lab merged 9 commits into
mainfrom
claude/cloud-session-todos-fhwi2w
Aug 22, 2026
Merged

M-ISSUES backlog + M-THEME token map#59
NCCU-Schultz-Lab merged 9 commits into
mainfrom
claude/cloud-session-todos-fhwi2w

Conversation

@NCCU-Schultz-Lab

@NCCU-Schultz-Lab NCCU-Schultz-Lab commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Two unrelated pieces of work landed on this branch in the same session — kept as one PR rather than opening a second for the same branch.

M-ISSUES: clear the 8-item standing backlog

Closes out all 8 items in the M-ISSUES standing backlog (defects and maintainability findings surfaced by a code review of the M-METAL branch against pre-existing M-CHECKPOINT/M-DF/M-PROGRESS code — none are M-METAL regressions). One commit per issue.

  • ISSUE.1 — Consolidated the calc-type key mapping. The correctness bug (reorg misclassified as single-point) was already fixed incidentally by earlier work; this removes the two remaining duplicate label→key dicts in favor of the canonical one.
  • ISSUE.2 — Frequency estimator's fallback now threads source= through to _estimate_frequency_cost, removing a bias that inflated small-molecule frequency estimates.
  • ISSUE.3density_fit is now recorded on TD-DFT/NMR/Frequency/Geometry-Opt results, not just single-point. Also fixes a separately-found gap: results_storage.save_result() never persisted density_fit into result.json for any calc type, so the "⚡ RI" badge vanished on History replay even for single-point runs.
  • ISSUE.4 — A warm-start SCF failure now falls back to a scratch guess instead of hard-failing the whole calculation.
  • ISSUE.5 — Fixes the steps_done regression on geometry-opt resume (seeds dyn.nsteps from the checkpoint). The duplicate-boundary-frame half of the original filing does not reproduce against the pinned ASE version — verified directly with a real PySCF run→resume — since ASE's own Dynamics.irun() already guards that case. New regression test added either way.
  • ISSUE.6 — Resume restore/discard buttons now wrapped in _safe_cb, consistent with every other action button.
  • ISSUE.7estimator_eval.replay() is O(n) instead of O(n²).
  • ISSUE.8 — Hill-formula formatting consolidated to one helper (connectivity.hill_formula); Molecule.get_formula and app_runflow._formula_from_symbols both delegate to it.

M-THEME: token map for the widget-building "chrome" files (roadmap 14, Execution Sequence step 1)

Adds 22 new tokens to theme.py (a text-tier greyscale set, BG_PANEL, BORDER_LEGACY, and a status-accent set) and migrates 9 widget-building modules (app.py, app_builders.py, app_formatters.py, app_runflow.py, descriptor_cards.py, help_content.py, app_analysis.py, app_history.py, calc_log.py) to reference them instead of scattered literal hex — 379 of ~436 hardcoded-hex occurrences in that file set.

Each token keeps its call sites' exact original value — a pure extract-to-constant refactor with zero rendered-pixel change, not a harmonization pass, so it's safe without a browser. Deliberately excludes the plotting/3-D-viewer files (analytics.py, orbital_visualization.py, app_visualization.py, visualization_py3dmol.py, ir_plot.py) — a wrong substitution there risks an actual rendering regression this session has no browser to catch. New standing regression test (TestNoRawHexReintroducedInMigratedChrome) guards against the migration eroding.

Test plan

  • pytest -m "not network" — 2587 passed / 24 skipped / 0 failed / 0 errors (2611 collected)
  • ruff + black clean
  • mypy — same 19 pre-existing stub-availability errors as main, zero new
  • ISSUE.5 fix verified directly against real PySCF/ASE (run → resume, before/after the change)
  • Theme migration verified by construction: ast.parse on every touched file, a case-insensitive re-scan confirming zero raw occurrences of the 22 target values remain outside theme.py

NCCU-Schultz-Lab and others added 9 commits August 21, 2026 22:59
Three separate label->key dicts had drifted apart: app_runflow's
_CALC_TYPE_CANON (header banner) and an inline dict in app.py's _do_run
(prediction-log calc type) duplicated calc_type_key()'s canonical
_CALC_TYPE_KEYS mapping, which already includes "Reorganization Energy"
but the duplicates existed only as a maintenance hazard now that all
three agree. Both call sites now delegate to _CALC_TYPE_KEYS /
calc_type_key() instead of carrying their own copy.

Contributions:
- Claude (Sonnet 5): code edits, review, and conceptual discussion
- Jonathan Schultz: overall vision, planning, review, and orchestration

Co-authored-by: Jonathan Schultz <nccu-schultz-lab@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
estimate_time_from_records() partitions its pool by source (and
density_fit) for every calc type, but the frequency-cost-model fallback
called _estimate_frequency_cost() without threading source through —
the function already accepts and uses it. A Frequency estimate for an
app run was drawing its single-point anchor from the mixed app+
calibration pool (which includes fresh-subprocess import cost),
systematically inflating small-molecule frequency estimates — exactly
the bias the source field exists to remove.

Contributions:
- Claude (Sonnet 5): code edits, review, and conceptual discussion
- Jonathan Schultz: overall vision, planning, review, and orchestration

Co-authored-by: Jonathan Schultz <nccu-schultz-lab@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…SUE.3)

session_calc.SessionResult recorded whether density fitting was used;
TDDFTResult, NMRResult, FreqResult, and OptimizationResult discarded
try_density_fit()'s flag instead of storing it. A DF-on TD-DFT / freq /
NMR / geometry-opt run was logged as unfitted: the perf record stored
density_fit=None, the result card's "RI" badge never showed even though
the run header printed "Density fitting: RI", and the estimator's DF
partition could never match those calc types.

Also: results_storage.save_result() never persisted density_fit into
result.json at all, for any calc type (including single-point) — so
even a live SessionResult's RI badge would vanish on History replay.
Added it alongside the existing gpu_used field.

Contributions:
- Claude (Sonnet 5): code edits, review, and conceptual discussion
- Jonathan Schultz: overall vision, planning, review, and orchestration

Co-authored-by: Jonathan Schultz <nccu-schultz-lab@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
_prepare_scf_checkpoint's loaded density was passed straight into
mf.kernel(dm0=_dm0) inside the same try/except that turns any SCF
failure into a hard RuntimeError. A warm-start-specific rejection (a
GPU-migrated mean-field rejecting a host/numpy density, or a loadable
but incompatible chkfile density) aborted an otherwise-fine calculation
— contradicting the module's own "a warm start is an optimisation, not
a requirement." Now a warm-start failure logs a warning, drops dm0, and
retries mf.kernel() from a scratch guess before giving up.

Contributions:
- Claude (Sonnet 5): code edits, review, and conceptual discussion
- Jonathan Schultz: overall vision, planning, review, and orchestration

Co-authored-by: Jonathan Schultz <nccu-schultz-lab@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
A freshly constructed BFGS instance always starts nsteps at 0, even on
a resumed run. Left unseeded, the per-step checkpoint.update(steps_done
=dyn.nsteps) callback reported a count that restarted at 0 instead of
continuing from what the interrupted run had already banked — a
resumed-then-interrupted-again optimization under-reported how much
work was saved. Seeding dyn.nsteps from the checkpoint on resume fixes
it.

The originally filed duplicate-boundary-frame half of this issue does
not reproduce against the pinned ASE version: Dynamics.irun() already
guards its pre-loop observer call with _traj_is_empty(), so appending
to an already-populated trajectory on resume correctly skips that
write. Verified directly against real PySCF/ASE (steps=1, compressed
H2/STO-3G, run -> resume): trajectory length after resume was already
old+1 without this change, but steps_done regressed 1 -> 1 instead of
1 -> 2. New regression test covers the step-count behaviour and keeps
the trajectory-length invariant as a live check.

Contributions:
- Claude (Sonnet 5): code edits, review, and conceptual discussion
- Jonathan Schultz: overall vision, planning, review, and orchestration

Co-authored-by: Jonathan Schultz <nccu-schultz-lab@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Every other one-off action button (cancel, basis-fix, spin-suggest,
spin-apply, ...) wraps its .on_click callback in _safe_cb so an
unexpected exception is logged instead of escaping into ipywidgets'
click dispatch. The resume-list restore/discard buttons skipped it.

Contributions:
- Claude (Sonnet 5): code edits, review, and conceptual discussion
- Jonathan Schultz: overall vision, planning, review, and orchestration

Co-authored-by: Jonathan Schultz <nccu-schultz-lab@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
past = history; history = history + [record] allocated a fresh
length-i list on every one of n iterations (~n^2/2 element copies),
making `python -m quantui.estimator_eval` needlessly slow on a large
perf_log.jsonl. Appends the current record in place after it has
already been used as the prediction's history snapshot instead —
same behaviour (a prediction never sees its own ground-truth record),
linear time. estimate_time_from_records() only reads its records
argument, so sharing the growing list by reference across iterations
is safe.

Contributions:
- Claude (Sonnet 5): code edits, review, and conceptual discussion
- Jonathan Schultz: overall vision, planning, review, and orchestration

Co-authored-by: Jonathan Schultz <nccu-schultz-lab@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…UE.8)

connectivity._hill_formula, app_runflow._formula_from_symbols, and
Molecule.get_formula each implemented the same C,H-first Hill order
with inline subscripts. Renamed connectivity._hill_formula to the
public hill_formula() and made the other two delegate to it, so a
convention change (e.g. a different subscript style) only has to be
made once. _formula_from_symbols keeps its "?" fallback for an empty
symbol list; hill_formula([]) itself still returns "" (matching
Molecule.get_formula's prior empty-molecule behaviour).

Contributions:
- Claude (Sonnet 5): code edits, review, and conceptual discussion
- Jonathan Schultz: overall vision, planning, review, and orchestration

Co-authored-by: Jonathan Schultz <nccu-schultz-lab@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…roadmap 14)

Execution Sequence step 1 ("define one theme token map... route hardcoded
hex values through the tokens"). Adds 22 new tokens to theme.py alongside
the existing BORDER/BORDER_STRONG: a text-tier greyscale set (TEXT_HEADING
through TEXT_SLATE_DARK), BG_PANEL, BORDER_LEGACY, and a status-accent set
(ACCENT_ERROR/_ALT, ACCENT_SUCCESS/_BG/_ALT, ACCENT_WARNING/_LIGHT,
ACCENT_INFO, ACCENT_PURPLE, ACCENT_TEAL).

Migrates the 9 widget-building "chrome" modules (app.py, app_builders.py,
app_formatters.py, app_runflow.py, descriptor_cards.py, help_content.py,
app_analysis.py, app_history.py, calc_log.py) to reference these tokens
instead of scattered literal hex — 379 of ~436 occurrences in that file
set (the 22 highest-frequency distinct values; a long tail of ~70
low-frequency values is left for a follow-up pass). _APP_CSS's three new
substitutions use the pre-existing sentinel + .replace() mechanism, same
as the existing __Q_BORDER__ sentinel, since that block is too CSS-brace-
dense for an f-string.

Each token keeps its call sites' exact original value -- this is a pure
extract-to-constant refactor with zero rendered-pixel change, not a
harmonization pass, so it's safe to do without a browser (verified by
construction: ast.parse on every touched file, a case-insensitive re-scan
confirming zero raw occurrences of the 22 target values remain outside
theme.py, full suite green). A later, visually verified pass can still
collapse near-duplicate tiers into fewer WCAG-measured values the way
BORDER/BORDER_STRONG already were.

Deliberately excludes the plotting/3-D-viewer files (analytics.py,
orbital_visualization.py, app_visualization.py, visualization_py3dmol.py,
ir_plot.py) -- a wrong substitution there risks an actual rendering
regression this session has no browser to catch.

New regression tests in test_theme_contrast.py: widened sentinel-leak
guard, and a standing scan (TestNoRawHexReintroducedInMigratedChrome)
that fails if any of the 22 migrated values reappear as a raw literal in
the 9 migrated files.

Contributions:
- Claude (Sonnet 5): code edits, review, and conceptual discussion
- Jonathan Schultz: overall vision, planning, review, and orchestration

Co-authored-by: Jonathan Schultz <nccu-schultz-lab@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
@NCCU-Schultz-Lab NCCU-Schultz-Lab changed the title M-ISSUES: clear the 8-item standing backlog M-ISSUES backlog + M-THEME token map Aug 22, 2026
@NCCU-Schultz-Lab
NCCU-Schultz-Lab merged commit 05c4e18 into main Aug 22, 2026
5 checks passed
@NCCU-Schultz-Lab
NCCU-Schultz-Lab deleted the claude/cloud-session-todos-fhwi2w branch August 22, 2026 01:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant