Skip to content

0.2c — Route the bundled solve template and inspector per-iter PNGs through AbstractIntermediateCallback #21

Description

@jack-champagne

Phase: 0-prime — Contracts/foundation · Plan task: 0.2c · Implementing repo: amicode (consumes DirectTrajOpt.jl symbol from 0.2a) · Depends on: 0.2a

Important

Problem

β shipped its live per-iter plot by hand-rolling a CairoMakie PNG inside the bundled solve-script template, driven off the raw Ipopt callback (β.5 inspector slice + β.3 template). PR #14 swapped that to a plot_pulse call as an interim, but it is still ad-hoc template scaffolding, not the contract surface. The Phase-0prime DoD requires β's live plot to flow through AbstractIntermediateCallback.

Approach

Once 0.2a exports AbstractIntermediateCallback from DirectTrajOpt.jl, retire the hand-rolled/plot_pulse per-iter PNG path: the bundled template attaches Piccolo's LivePulsePlotCallback (an AbstractIntermediateCallback subtype) so per-iter PNGs are emitted through the callback abstraction, and AGENTS.md teaches that idiom as the blessed convention. The inspector continues to read PNGs from the run dir unchanged.

Approaches Considered

  • Migrate template to LivePulsePlotCallback via the new abstraction — CHOSEN; satisfies the DoD, removes bespoke plotting from the agent-authored surface, and stays inside the run-dir PNG contract the inspector already reads.
  • Keep PR feat: plot the pulse with Piccolo plot_pulse (not hand-rolled Makie) #14's plot_pulse interim — rejected; still bespoke per-iter scaffolding, does not satisfy "flows through AbstractIntermediateCallback."
  • Make the inspector subscribe to the callback directly (skip PNGs) — rejected; the inspector is intentionally PNG/HDF5-agnostic and reads the run-dir contract, not solver internals.

Scope

In: bundled solve-script template per-iter plotting; AGENTS.md callback idiom; confirming the inspector renders callback-emitted PNGs.
Out:

  • Defining/exporting AbstractIntermediateCallback — owned by 0.2a (this slice consumes it).
  • HDF5 pulse export — Phase 3 (this slice touches per-iter PNGs only).
  • Multi-run inspector / runs/index fan-out — Phase 1 (single-run path only here).
  • MadNLP per-iter callback wiring — scoped to the DTO-side slices (0.2a/b), not this slice; 0.2c's only MadNLP-relevant invariant is the Q74 live-inspector enum-restrict to ipopt, so the β plot-path supersession here is ipopt-only by design (not a silent drop of the plan's "Ipopt + MadNLP" wiring scope).

Assumptions

  • 0.2a lands the symbol on a pin the bundled Julia project resolves; until then this slice cannot go green (hard dependency, not soft).
  • Piccolo's LivePulsePlotCallback subtypes the 0.2a symbol and emits a PNG into the run dir at the template's plot cadence.

Acceptance Criteria

  • The bundled template, run unmodified on the β/Schuster params, attaches a LivePulsePlotCallback (an AbstractIntermediateCallback) and emits iter_<N>.png frames through the callback at the template's plot cadence, with no direct CairoMakie/plot_pulse call remaining in the template.
  • A repo grep confirms the hand-rolled per-iter plotting and the PR feat: plot the pulse with Piccolo plot_pulse (not hand-rolled Makie) #14 plot_pulse interim are gone from the bundled template.
  • AMICODE_ITER stats telemetry remains intact across the migration (the existing Ipopt text-callback fields still stream).
  • The single-run inspector renders the callback-emitted iter_<N>.png from the run dir live during a solve, with no change to inspector plumbing.
  • AGENTS.md documents LivePulsePlotCallback / AbstractIntermediateCallback as the blessed per-iter plot idiom.
  • A clean run still produces a run dir conforming to the run-dir contract (FINISHED{completed}, pulse, result.toml).

Key Decisions

Constraints & Invariants

  • Live inspector is ipopt-only for v1 (Q74 schema enum-restricts the live-inspector backend to ipopt; MadNLP callback wiring is a DTO-side 0.2a/b concern). The template must not select a backend that silently drops per-iter PNGs.
  • The inspector reads PNGs from the run dir; this slice must not introduce a solver→inspector channel that bypasses the run-dir contract.
Prior Art / Patterns

LivePulsePlotCallback (Piccolo) subtyping AbstractIntermediateCallback (DirectTrajOpt); the existing Ipopt text-callback that streams AMICODE_ITER; the bundled solve-script template and AGENTS.md authoring conventions; the single-run inspector's run-dir PNG watcher.

Source

Phase-0prime plan task 0.2c (companion to 0.2a's DirectTrajOpt.jl symbol). Sole provenance for this slice is the DoD line "β's live plot now flows through AbstractIntermediateCallback" — task 0.2's PRD requirements (S14/S15/S16/S17/S26/S27/S29/S30) are realized by the schema/lab.toml/result-round-trip slices, not by this PNG-callback slice. Downstream context only: the migrated PNG path feeds the inspector that ultimately serves S4 (inspector refreshes plot) and S5 (live stats row), which the plan realizes via β (single-run) and Phase 1 (full) — not this contracts-phase slice. Related decision: D10 (per-iter PNG callback idiom; LivePulsePlotCallback subtypes the DTO symbol) and the independent Piccolo-main-missing-DTO-symbol bug fixed upstream in 0.2a. Q74 (live-inspector enum-restrict to ipopt). Supersedes β scaffolding from #3 (β.3 template) and the β.5 inspector slice, plus the PR #14 interim.

Testing

Extend the amico-run fast tier with a template-rendering / per-iter-PNG check (template emits callback-driven iter_<N>.png at the plot cadence and AMICODE_ITER survives); semi-TDD — phrase as a failing check first, let the loop decide structure. Inspector PNG-render behavior can ride the existing single-run inspector test surface.

Notes

Cannot go green until 0.2a publishes AbstractIntermediateCallback on a resolvable pin. Slice is intentionally thin (template + docs + inspector confirmation); do not merge with 0.2a (the DTO symbol) or pull Phase 1 multi-run work in.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions