Comet Analyzer formula documents, drafts and atomic persistence

R149 remains the target-aware document and atomic-file foundation; R179 supersedes the former Save-to-runtime application semantics with explicit draft, Refresh, Save and Analyse transactions.

Current formula route: typing → draft only; Refresh → validate both documents + atomic runtime commit; Save → atomic MagParams.dat persistence only; Analyse → immediate typed commit + one render.

Document grammar

One selected target

The established simple editor remains valid and requires no target header:

H0=7.24 mag, n=6.70 [-inf, 0]
H0=8.56 mag, n=4.59 [0, inf]

Multiple selected targets

Both editors contain one complete document with one block per selected comet:

# TARGET 4P | 4P/Faye
H0=7.24 mag, n=6.70 [-inf, 0]
H0=8.56 mag, n=4.59 [0, inf]

# TARGET 10P | 10P/Tempel
H0=5.50 mag, n=4.00 [-inf, inf]

The token immediately after # TARGET is the authoritative canonical designation. Text after | is display-only and must not be used as persistence identity.

Changing the target combobox moves the cursor to the matching block in both editors. It does not replace either document or create target-local editor state.

Validation invariants

The canonical typed parser validates the complete document set before a runtime or file transaction. It rejects text before the first target header, duplicate or unknown blocks, missing selected targets, malformed rows and any required Regular block without a formula.

Typing signals do not validate or mutate committed state. Validation is invoked only by an explicit operation such as Refresh or Save. Partial target updates remain forbidden.

Draft and committed state

Regular and Additional editor text is a draft until a valid Refresh. Intermediate strings—including i, in, -, 1e or an incomplete interval—must not change committed formulas, formula revision, graph or persistent files.

A valid Refresh parses both documents, commits them together, advances the formula revision exactly once and starts one render. An invalid Refresh preserves the previous committed model and graph.

Typed Additional series preservation

Fit-generated Additional results remain typed FormulaSeries objects while their target block is unchanged. A manual edit converts only the modified target block to the established numerical/manual representation. Other targets retain series identity, fit-group identity and typed metadata.

This is a per-block preservation rule inside one complete editor document; it is not a return to separate per-target editors.

Atomic Save transaction

  1. Parse and validate the persistence draft.
  2. Prepare numerical formula maps for all selected targets and exact canonical-designation replacements.
  3. Read config-files/MagParams.dat and preserve unrelated, malformed and comment records verbatim.
  4. Write one same-directory temporary file, flush and fsync it.
  5. Commit once with os.replace().

An invalid Save leaves MagParams.dat byte-identical. A valid Save persists the draft atomically but does not apply it to the committed graph, advance the runtime formula revision or trigger a render. Manual draft application remains the responsibility of a separate valid Refresh.

Refresh, Save and Analyse semantics

ActionRuntime effectFile effect
TypingDraft only; no revision or redraw.None.
RefreshValidate both documents, atomically commit, advance one formula revision and render once.None.
SaveDo not apply draft to graph.Atomic MagParams.dat replacement.
AnalyseCommit typed result immediately and start one implicit Refresh/render.No implicit Save.

None of these formula-only operations restarts observation loading. Missing physical coverage can still request only the necessary geometry work through the established compute-once pipeline.

Canonical parser and compatibility

  • Explicit -inf, historical [inf, inf] and leading whitespace remain compatible.
  • _analysis_parse_formula_text() has been removed from production.
  • ParseFormulas() is side-effect free and delegates to the canonical typed parser.
  • wlightcurves.py no longer calls koprobs.magparams().
  • The legacy request preparation and row converter are compatibility-only and isolated from the typed Analyzer runtime.

Release gates and source-reported validation

R149 remains the grammar and file-transaction foundation. R179 adds the interactive formula smoke and qualification gate.

  • R177 and R178: 9/9 PASS each.
  • R179 headless: 13/13 PASS; real Qt skipped because PyQt5 was unavailable.
  • R177–R179 targeted: 24 passed, 1 skipped.
  • R149–R179 current regression: 236 passed, 3 skipped.
  • Strict --require-qt correctly fails when the runtime is absent.

R179 transaction and interactive-gate contract

Current integration: R187 retains these formula transactions inside the typed 1..N Comet Analyzer architecture. The current release criterion is the R135–R187 behavioral suite, not removed transitional source assertions.

Scientific and architectural non-changes

R149 does not alter observation loading, channel classification, ephemeris mathematics or policy, physical geometry, H0/n or phase equations, fitting mathematics, adaptive breaks, colour-index arithmetic or the scientific behaviour of WPlanner, WVisual, WCCD and WStack.

User formula guide · WLightCurves architecture · Supplied R149 report