Skip to content

feat(operation): CORA-conducted flat/dark normalization ceremony (recipe-driven)#309

Merged
xmap merged 1 commit into
mainfrom
worktree-flat-dark-ceremony
Jun 22, 2026
Merged

feat(operation): CORA-conducted flat/dark normalization ceremony (recipe-driven)#309
xmap merged 1 commit into
mainfrom
worktree-flat-dark-ceremony

Conversation

@xmap

@xmap xmap commented Jun 22, 2026

Copy link
Copy Markdown
Owner

What

The flat/dark normalization baseline ceremony, modeled as a Recipe and run as the first deliberate consumer of the Procedure Conductor at 2-BM. Proves the recipe -> conduct ladder end to end against the soft-IOC + Postgres harness.

  • cora.operation.staging.flats (new): a save-and-restore staging action -- read the sample axis, retract by a clearance (absolute write, since CORA has no relative-move primitive), collect, restore. Composes the public collect primitive; lives in a staging module, deliberately not a fourth scan primitive. A non-numeric axis read maps to ControlValueCoercionError so the Conductor records a structured failure instead of letting a bare TypeError escape.
  • test_2bm_normalization_baseline (new scenario): seed cora.capability.acquisition -> define_recipe (8-step template: shutter-closed / check / collect-darks / shutter-open / check / flats / shutter-closed / check) -> register_procedure_from_recipe -> conduct (the handler re-expands the pinned template) -> Completed -> terminal-gated register_dataset carrying producing_actuation_kind="Simulated" derived from the conduct. The first end-to-end exercise of the recipe-driven conduct path against real Postgres + soft-IOC.
  • Governance: normalization_baseline added to the procedure-kind carve-out; the noun-LAST fitness scanner broadened to also cover RegisterProcedureFromRecipe (it previously missed the recipe-driven registration path); catalog.yaml reconciled to [Method, Procedure] for the acquisition capability.

Why

The conduct-path "101": prove the runtime on the simplest real 2-BM ceremony before the heavier consumers (fly-scan resume, autonomous control) ride the same rails. 2-BM stays record-path live (TomoScan owns the Actuate axis); this is a deliberate Actuate-axis exercise, not a production seam shift.

Deferred (each its own Stage 0/1, post-merge)

  • Conduct-level runtime value capture -- would let a recipe express the save-restore directly (read axis -> collect -> setpoint from the read) and retire the flats body. The principled fix.
  • Generic retract_around primitive -- the rule-of-three step between (real n=3 candidates: flat-field, reference/I0-in, target-in characterization, beamstop dark; they differ in shape, so the seam should be designed against >=2 real consumers). Needs ActionContext to carry the registry. Trigger: the second conduct-path staging consumer.

Illustrative-pending-staff

Every physical specific is a soft-IOC stand-in pending staff sign-off: the shutter PV (the real S02BM-PSS:SBS inverted-sense leaf), the sample-out axis + clearance (SampleTop_X / theta-park), the frame counts + dwell.

Tests

Local gate green: ruff, pyright, tach, architecture tier (26868), catalog descriptor (30), operation unit (888), recipe unit (1219), plus the new scenario / staging integration / flats unit tests. Two adversarial gate-review passes (APPROVE_WITH_NITS, 0 majors; all findings folded, including proving the broadened scanner is load-bearing).

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  apps/api/src/cora/api
  _calibration_watcher.py
  _clearance_watcher.py
  _procedure_watcher.py
  apps/api/src/cora/operation
  _recipe_expansion.py
  acquisitions.py 239
  staging.py
  wire.py
  apps/api/src/cora/operation/ports
  control_port.py
Project Total  

This report was generated by python-coverage-comment-action

…ipe-driven)

The flat/dark normalization ceremony is the first deliberate consumer of
the Procedure Conductor at 2-BM, proving the recipe->conduct ladder end to
end: a deployment Recipe (the templated step list) realizing the existing
cora.capability.acquisition is registered via register_procedure_from_recipe,
and the conduct handler re-expands the pinned template and drives it through
the ControlPort against a soft IOC. This is the conduct-path "101" before
the heavier consumers (fly-scan resume, autonomous control) ride the same
rails.

The flats save-and-restore is a staging composition (cora.operation.staging),
deliberately kept out of the scan-primitive set {collect, discrete,
continuous}: it brackets a collect with an absolute axis read-then-restore
only because the conduct step model is static. Conduct-level runtime value
capture, which would let the recipe express the save-restore directly and
retire the flats body, is the designated next design (its own Stage 0/1);
a generic retract-around primitive is the rule-of-three step between.

2-BM stays record-path live (TomoScan owns the Actuate axis); this is a
deliberate Actuate-axis exercise, not a production seam shift. Every
physical specific (shutter PV + inverted sense, sample-out axis, clearance,
frame counts) is an illustrative soft-IOC stand-in, pending staff
confirmation before any live-EPICS wiring.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xmap xmap force-pushed the worktree-flat-dark-ceremony branch from a0f4d4b to 1e27d47 Compare June 22, 2026 11:48
@xmap xmap merged commit 0ce1709 into main Jun 22, 2026
16 checks passed
@xmap xmap deleted the worktree-flat-dark-ceremony branch June 22, 2026 12:01
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