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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions