Builder and Data Contracts
Builder inputs, data contracts, pack creation, and the main integration flow.
Use this chapter when you already have validated H data, optional IR data, or source data that Builder can convert, and you need to produce a pack that Runtime can load. It explains the Builder setup flow, the shape rules that matter at the handoff, and the checks worth running before you blame Runtime for a bad pack. This chapter stops at the pack-to-runtime handoff; the full runtime lifecycle and step loop live in their own chapters.
If your starting point is already FRF data, impulse-response data, or a Builder-ready workflow output, start here. If your starting point is a circuit netlist, RAW case, or Touchstone-driven circuit flow, start with Circuit SDK instead.
Purpose
Use Builder to turn validated time-domain H data, optional IR data, or
Circuit-produced spectra into a binary pack that Runtime can load. Builder owns
shape validation, pack metadata, and serialization; Runtime owns stepping after
the pack bytes are loaded.
5-Minute Path
tdse_builder_t* b = NULL;
tdse_builder_create(&b);
tdse_builder_configure(b, cfg);
h_desc.dt = cfg.dt;
tdse_builder_apply_h(b, &h_desc);
tdse_builder_write_pack(b, "model.pack");
tdse_builder_destroy(b);
Expected Output Sample:
builder: configured np=1 nq=1 nh=128 dt=1e-05
builder: wrote model.pack
runtime: pack validation OK
Production Path
For release builds, validate inputs before tdse_builder_apply_h, write the
pack to a controlled artifact directory, run tdse_pack_validate, inspect pack
summary metadata, and keep a small Runtime create/step smoke test beside the
pack-producing job.
Troubleshooting
- If
tdse_builder_configurefails, checknp,nq,nh, anddtfirst. - If
tdse_builder_write_packfails, verify the output directory exists. - If Runtime rejects the pack, run
tdse_pack_validatebefore debugging the host step loop.
Related Docs
Related Chapters For Runtime lifecycle semantics after pack creation, see Runtime Lifecycle. For step execution inside the simulation loop, see Step Execution.
Use this chapter when your integration starts from one of these Builder-side artifacts:
| Starting artifact | Builder role |
|---|---|
validated H tensor | attach H, write pack, hand off to Runtime |
validated H plus optional IR | attach both, preserve shape and horizon contracts |
| matrix or circuit workflow output | accept Builder-ready handoff from Circuit or workflow API |
Prerequisites
- Built SDK artifacts (Runtime
tdse, Buildertdse_builder, headers). - A generated pack input (
Hrequired,IRoptional). - Build/test workspace ready:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release
Quick Start
Both paths below end with a written pack and a small handoff check. Use the minimal path for prototyping; switch to the production path before release.
Minimal path
tdse_builder_t* b = NULL;
tdse_builder_options_t cfg = tdse_builder_options_init();
cfg.dt = dt;
cfg.nh = nh;
cfg.port_count = np;
cfg.output_count = nq;
tdse_builder_create(&b);
tdse_builder_configure_ex(b, &cfg); /* port_count/output_count/nh/dt */
h_desc.dt = cfg.dt; /* must match configured Builder dt */
tdse_builder_apply_h(b, &h_desc); /* required */
tdse_builder_apply_ir(b, &ir_desc); /* optional */
tdse_builder_write_pack(b, "model.pack");
tdse_builder_destroy(b);
Then hand the pack to Runtime Lifecycle for create/destroy behavior and to Step Execution for the simulation loop.
Minimal host-side interpretation:
- Builder owns pack construction and pack metadata
- Runtime owns create, step, and destroy after pack bytes are handed off
- the host owns artifact selection, pack storage, and when to start Runtime
Production path
For production integration, add these practices on top of the minimal flow:
- Validate pack bytes before runtime create (
tdse_pack_validate). - Inspect the pack summary before create so shape and metadata mismatches are visible early.
- Archive a Builder snapshot (
tdse_builder_info(...)) next to the pack or release artifact. - Run one deterministic runtime smoke check: create the model, read
tdse_model_info(...), and verify a known-good step path. - Archive
tdse_model_create_diagnostics_ton non-OK create paths. - Run threading stress and contract tests before promoting binaries.
Runtime handoff note:
- use Runtime Lifecycle for
create,close,destroy, andrelease - use Step Execution for prime, trial, commit, and post-commit queries
- use Runtime API Summary when you need a fast symbol map instead of a narrative walkthrough
Smallest Supported Builder -> Runtime Handoff
If your team needs the shortest credible integration contract, treat the handoff as these four checks:
-
Builder writes one pack successfully
-
tdse_pack_validateaccepts that pack -
Runtime create succeeds and
tdse_model_info(...)matches expectednp,nq,nh, anddt -
one prime-and-step smoke path completes without status errors
Validation Checklist
-
tdse_pack_validatepasses on release pack. - Minimal step loop returns
TDSE_STATUS_OKend-to-end. - One failure-injection case per major status is covered.
- Threading stress case is green on target build.
- Runtime outputs are stable across repeated runs with same input.
- Linux deployment claims match the current Runtime SDK Linux support scope when shipping on Linux.
Parameter Cookbook
| Parameter | Meaning | Recommended Baseline | Notes |
|---|---|---|---|
np | primary input count | system-dependent | Must match host primary vector width. |
nq | operator row count | >= np | Use full rectangular view when nq > np. |
nh | history taps | start with calibrated value | Higher nh raises history cost. |
dt | step interval | fixed per model | Runtime Pack 1.0 requires an exact positive whole number of nanoseconds. |
IR length | independent sequence horizon | cover whole simulation window | Out-of-range returns TDSE_STATUS_OUT_OF_RANGE. |
| runtime handles | parallel threads | one handle per worker | Never step same handle concurrently. |
Data Contracts
TDSE Core is strict about dimensions, layout, and ownership. Most early integration failures are shape mistakes rather than numerical mistakes.
Primary Dimensions
Four dimensions define most Builder-to-Runtime compatibility:
| Symbol | Meaning | Practical Rule |
|---|---|---|
np | primary input count | must match host primary vector width |
nq | output-equation count | must satisfy nq >= np |
nh | history tap length | must match the supplied H tensor depth |
dt | model step interval | must be consistent across Builder and Runtime expectations |
Runtime Pack 1.0 Time-Step Contract
Runtime Pack 1.0 stores the simulation step as a positive integer number of
nanoseconds. For a pack-producing Builder flow, configured dt must therefore
be finite, positive, at least 1 ns, and exactly representable as whole
nanoseconds. Values such as 10 ns, 100 ns, 1 us, and 10 us are valid;
sub-nanosecond and fractional-nanosecond values such as 0.5 ns and 1.5 ns
are rejected. The writer does not silently round them.
The written header h_dt, the TIME_CONTRACT nominal step, and
TIME_CONTRACT.dt_ns all describe the same canonical value:
dt = dt_ns / 1e9. Pack inspection reports this integer as dt_ns. Verify it
before Runtime create whenever the host time step is safety- or
reproducibility-critical.
API Families
At the Builder boundary, the main API families are:
Builder lifecycle
tdse_builder_createtdse_builder_configure_extdse_builder_apply_htdse_builder_apply_irtdse_builder_write_packtdse_builder_destroy
Canonical selector boundaries
tdse_builder_set_pack_meta_v2accepts rawint32_tform/domain valuestdse_builder_h_from_spectrum_v3accepts a fixed-width request containing correction, parallel-mode, and tail-preset valuestdse_builder_irc_profile_select_v2andtdse_builder_irc_compress_v2accept fixed-width IRC selectors
Use these entrypoints when selector values originate in a file, RPC, plugin, language binding, or other untrusted integer boundary. They validate the raw representation before converting it to an enum. The older enum-by-value APIs remain available for source compatibility and for callers that already hold valid C enum values; they are not the canonical raw-integer trust boundary.
Pack validation and inspection
tdse_pack_validatetdse_pack_inspecttdse_runtime_pack_inspect_summarytdse_pack_error_token
Runtime handoff surface
tdse_model_createtdse_model_info
For full Runtime lifecycle and step APIs, switch to Runtime Lifecycle, Step Execution, or Runtime API Summary.
Ownership Model
- Builder descriptors such as
tdse_h_desc_tandtdse_ir_desc_tare borrowed views - Pack-validation and pack-inspection outputs are caller-owned result structs
- No Core API transfers ownership of caller-owned
H,IR, or step-output buffers
Failure Atomicity
Builder commits state and caller outputs only after validation, finite-result checks, and required allocations succeed:
- failed
tdse_builder_apply_h(...)ortdse_builder_apply_ir(...)calls leave the handle's previously attached payload and pack-producing state unchanged - failed uniform-
Hconversion leavesh_out, and for the piecewise helper bothtau_outandh_out, unchanged - failed Spectrum conversion, including a fatal Tail-processing failure, leaves
h_outand the optional effective-nhoutput unchanged - failed IRC compression leaves a previously initialized/reusable output buffer unchanged
Finite inputs that overflow while deriving weights, moments, or time-axis
values return TDSE_STATUS_NUMERIC; they are never reported as successful
non-finite output. Allocation failures return TDSE_STATUS_OUT_OF_MEMORY.
Pack-file commit has a separate three-outcome contract described under
Write Gate Checklist.
Compatibility Equation
Builder-side and Runtime-side assumptions are compatible only when all of these are true:
- Builder
np,nq,nh, anddtmatch the intended runtime model His laid out exactly as declared by its descriptor- optional
IRis laid out exactly as declared by its descriptor - runtime host buffers are sized from runtime-reported dimensions rather than from memory or guesswork
H Tensor Contract
H uses tap-major row-major storage: shape [nh][nq][np], linear index tap * nq * np + row * np + col, layout enum TDSE_H_LAYOUT_TAP_MAJOR_ROW_MAJOR.
H[0]is the instantaneous operator returned bytdse_step_op(...)H[1..nh-1]contribute to the delayed-history term returned bytdse_step_hr_v2(...)
Explicit-tau contract:
h_desc.tau == NULLmeans delayed taps live on the implicit uniform axistau[k] = k * dth_desc.tau != NULLmeans Runtime evaluates history on the supplied explicit time axis- when
tauis explicit,H[1..nh-1]must already be weighted for that axis - if your source taps came from a uniform grid, convert them first with
tdse_builder_h_uniform_to_tau_1d(...)ortdse_builder_h_uniform_to_piecewise_tau_1d(...)
IR Sequence Contract
IR is step-major: shape [nsteps][nq], linear index step * nq + row, layout enum TDSE_IR_LAYOUT_STEP_MAJOR. Runtime queries IR by current step time. If the query falls outside the configured support window, tdse_step_ir_v2(...) returns TDSE_STATUS_OUT_OF_RANGE.
Dense Operator Contract
tdse_step_op(...) writes into a tdse_dense_block_t. Supported views: square (np x np) or full (nq x np). cols must always equal np; rows must equal either np or nq.
Shape Worked Example
Assume np = 3, nq = 4, nh = 8, ir_nsteps = 100. Then:
| Query | Required Length / Shape |
|---|---|
primary vector passed to commit | length np = 3 |
hr_out buffer | length nq = 4 |
ir_out buffer | length nq = 4 |
square op view | 3 x 3 |
full op view | 4 x 3 |
committed dr_out buffer | length nq = 4 |
The common bug: sizing hr, ir, or dr buffers to np because the host thinks in terms of ports rather than equations. These buffers are nq-sized outputs.
Step-Term Contract
For the mathematical definitions, see Theory and Concepts.
| Term | Meaning | Side Effect |
|---|---|---|
op | instantaneous operator | none |
hr | delayed-history contribution | none |
ir | independent-response contribution | none |
dr | committed-step direct response | query-only, post-commit |
Read these equations literally: y_trial = op * primary_trial + hr + ir; dr[n] = op * primary_accepted[n]. dr is the direct-response slice on the committed step, not "the whole committed output."
Runtime Handoff Contract
Builder is done once the pack is internally consistent, validated, and clearly labeled. The runtime handoff should answer three questions before any simulation work starts:
- does the pack validate cleanly
- do inspected dimensions and metadata match what the host expects
- does Runtime create the model without reporting pack or compatibility errors
After that point, move to Runtime Lifecycle and Step Execution instead of continuing to reason about Runtime behavior from the Builder chapter.
Host-Side Assertions
In production, assert these once near the integration boundary:
model_info.npmatches host primary-vector widthmodel_info.nqmatches host equation/output widthmodel_info.nhmatches intended history depthmodel_info.dtmatches host time-step contract
Common Shape Mistakes
- host primary vector width does not match
np hr/irbuffers sized tonpinstead ofnq- square operator storage used when host required
nq x np - Builder
dtand simulationdtassumed to match without verification - inferring
np/nqfrom old code paths instead oftdse_model_info(...) - treating
IRas a runtime side channel instead of packaged model content
Power Systems Guide
Typical Parameters by Scenario
| Scenario | dt (s) | nh | nfft | np | nq | Notes |
|---|---|---|---|---|---|---|
| Transmission line (100 km, 500 kV) | 1e-6 to 10e-6 | 1000-5000 | 2 x nh | 2 (1 port) or 4 (2-port) | np or np+1 | Large nh for propagation delay |
| Transformer (50 MVA) | 1e-6 to 50e-6 | 200-1000 | 2 x nh | 2-6 | np | Moderate nh for winding capacitance |
| Distribution cable (underground) | 1e-6 to 10e-6 | 500-2000 | 2 x nh | 2-4 | np | nh depends on cable length |
| EMI/EMC (wideband) | 10e-9 to 100e-9 | 1000-4000 | 4 x nh | 1-10 | np | Very fine dt for high-frequency content |
| Power electronics (switching ~100 kHz) | 10e-9 to 100e-9 | 500-2000 | 2 x nh | 1-4 | np | Fine dt for switching transients |
Choosing nh
The history depth nh must be large enough that H[nh-1] has decayed to near zero:
- Build the pack with an initial
nhestimate - Inspect
H[k]for the last few taps (k near nh-1) - If
|H[nh-1]|is not negligible compared to|H[0]|, increasenh - Typical transmission lines:
nh >=round(propagation_delay / dt) + margin
For a 500 kV, 100 km line with propagation speed ~2.8x10^8m/s and dt = 50 us: propagation delay >=357 us ->nh >=9. For dt = 1 us: nh >=367.
When to Use nq > np
Set nq > np when the model needs measurement equations beyond the port count: multi-port models with internal measurements, mixed Y/Z representations, or host simulators needing both terminal currents and internal state outputs. For standard Y+ISC or Z+VOC, nq = np is typical.
Builder Flow
Builder is the handoff layer between validated source artifacts and Runtime. A clear Builder boundary makes later debugging much easier: you can tell whether a problem comes from the source data, Builder configuration, pack generation, or Runtime execution.
Builder Responsibility
Builder owns the configured dimensions and dt, attachment of required H and optional IR, optional conversion from frequency-domain data into time-domain H, optional Builder-side shaping such as IRC, and the final pack metadata and pack write.
Builder does not own upstream artifact validity beyond descriptor and shape checks, host-specific port order or matrix-family interpretation, Runtime step execution, or Runtime shutdown and concurrency policy.
The main rule is simple: Builder should emit the final artifact, and Runtime should execute it as-is. Runtime is not expected to reconstruct or repair pack content later.
Builder State Machine
Important rules: tdse_builder_configure_ex(...) is the recommended configure entrypoint, re-configuring replaces dimensions and clears previously attached H and IR, tdse_builder_info(...) is the best snapshot of the current Builder state, and a successful pack write does not transfer handle ownership.
Builder Contract Table
| Contract Item | Set By | Why It Matters Downstream |
|---|---|---|
dt | tdse_builder_configure_ex(...) | Runtime timing and IR step addressing |
np | tdse_builder_configure_ex(...) | host primary vector width must match |
nq | tdse_builder_configure_ex(...) | hr, ir, dr, and full op row count |
nh | tdse_builder_configure_ex(...) | delayed-history horizon and H tensor depth |
H layout | tdse_h_desc_t | wrong layout produces plausible but incorrect packs |
explicit tau axis | tdse_h_desc_t | malformed nonuniform timing rejected before pack write |
IR layout and horizon | tdse_ir_desc_t | runtime tdse_step_ir_v2(...) legality |
| pack form/domain metadata | tdse_builder_set_pack_meta_v2(...) | support and consuming hosts interpret the pack |
Direct H Ingestion
Use when the upstream artifact is already a validated time-domain kernel. Sequence: configure -> populate tdse_h_desc_t -> tdse_builder_apply_h(...) -> snapshot with tdse_builder_info(...) -> write pack. Post-apply: verify info.configured, info.has_h, and dimension/tau expectations match.
Spectrum-to-H Conversion
Use tdse_builder_h_from_spectrum_v3(...) when the upstream artifact is frequency-domain data.
The sequence: define positive-frequency grid -> map source matrix into tdse_builder_cplx_mat_view_t -> choose correction method -> run conversion -> attach -> snapshot before write.
Initialize tdse_builder_h_from_spectrum_request_t with
tdse_builder_h_from_spectrum_request_init(), then set its fixed-width
correction_method, parallel_mode, and tail_preset fields. Invalid raw
selector values return TDSE_STATUS_INVALID_ARG without loading an invalid C
enum representation.
The shipped tdse_builder_h_from_spectrum(...) entrypoint is deprecated; its compatibility
alpha argument is reserved and must be 0.0, and a non-zero value returns
TDSE_STATUS_UNSUPPORTED instead of being silently ignored.
Deprecated Builder symbols remain ABI-supported throughout 1.x. Their earliest
removal milestone is 2.0, after at least two minor releases and 12 months of
published migration guidance; new code should use the canonical names now.
Correction methods:
TDSE_BUILDER_CORRECTION_NONE_RECONSTRUCT_FROM_REAL_RECONSTRUCT_FROM_IMAG_RECONSTRUCT_FROM_MAG_RECONSTRUCT_FROM_PHASE
These options change how Builder computes H; Runtime only sees the
finished pack. When this path looks wrong, ask two separate questions:
did Builder produce the intended H, and did Runtime execute that pack
correctly?
Grid Planning: dt, nh, and nfft
These three parameters must satisfy nfft >= 2 * nh (FFT covers full impulse
response without aliasing), dt must capture the highest source frequency, and
nh * dt must capture full decay. The planner takes separate input and output
structures:
tdse_builder_grid_planning_input_t grid_in =
tdse_builder_grid_planning_input_init();
tdse_builder_grid_planning_output_t grid_out =
tdse_builder_grid_planning_output_init();
grid_in.f_max_hz = 5.0e6;
grid_in.target_dt = 100.0e-9; /* optional; 0 selects automatic dt */
grid_in.target_time_window_s = 1.0e-3;
tdse_status_t rc =
tdse_builder_compute_consistent_grid(&grid_in, &grid_out);
An explicit non-zero target_dt must satisfy Nyquist and the exact positive
integer-nanosecond Runtime Pack contract. In automatic mode (target_dt == 0),
the planner derives a Nyquist-safe value and floors it to whole nanoseconds;
flooring makes the step no larger than the raw result. If the derived value is
below 1 ns, planning fails instead of emitting a step that the Pack writer
cannot represent.
| Scenario | dt | nh | nfft | Rationale |
|---|---|---|---|---|
| Power electronics (~100 kHz) | 10-100 ns | 500-2000 | 2 x nh | Fine dt for switching edges |
| Transmission line (long delay) | 1-10 us | 2000-10000 | 2 x nh | Large nh for delay + reflections |
| Structural dynamics (< 1 kHz) | 1-10 us | 200-1000 | 2 x nh | Coarse dt sufficient |
| EMI/EMC (wideband) | 10-100 ns | 1000-4000 | 4 x nh | Large nfft for spectral resolution |
Common mistakes: nh too small ->truncated impulse response; dt too large ->aliasing; nfft < 2*nh ->wrap-around corruption.
FRF Data Layout
The source frequency-domain data must be organized as a row-major complex matrix: H_frf[freq_idx * np * nq + row * np + col]. The grid must be monotonically increasing, include near-DC, and use approximately uniform spacing. The Builder expects Y or Z parameters (not S-parameters). Multi-port ordering must be consistent across all frequency points.
Builder IRC (Impulse Response Compression)
IRC reduces effective history depth by replacing the delayed tail with a dyadic explicit-time representation. V1 aggregates source taps into dyadic bins; V2 represents each non-trivial bin with endpoint taps that preserve both its sum and first time moment. Both retain the configured exact prefix. These modes do not fit an exponential envelope, and the tolerance fields remain reserved.
tdse_builder_irc_profile_v2_t profile;
tdse_builder_irc_profile_v2_init(&profile);
tdse_builder_irc_profile_select_v2(
(int32_t)TDSE_BUILDER_IRC_PRESET_BALANCED_V1, &profile);
tdse_builder_irc_buffer_t compressed;
tdse_builder_irc_buffer_init(&compressed);
tdse_builder_irc_compress_v2(&h_desc, &profile, &compressed);
tdse_builder_apply_h(b, &(tdse_h_desc_t){
.struct_size = sizeof(tdse_h_desc_t),
.port_count = compressed.port_count,
.output_count = compressed.output_count,
.nh = compressed.nh,
.dt = compressed.dt,
.data = compressed.data,
.tau = compressed.tau,
.layout = compressed.layout,
});
tdse_builder_irc_buffer_release(&compressed);
The fixed-width *_v2 profile API is canonical for new integrations. Choose a
stable semantic preset (BALANCED, COMPACT, AGGRESSIVE, CONSERVATIVE,
HIGH_FIDELITY, ULTRA_FIDELITY, or MAX_FIDELITY); its versioned shape is
bound by manifests/policy/builder_irc_presets_v1.json. The older DEFAULT_V1
and STUDY_P*_V1 names remain source-compatible 1.x aliases only.
Keep the IRC parameters next to the pack so later comparisons are reproducible. Use the Profiler IRC scan to explore compression quality before production use.
Optional IR
IR is optional, but once attached it becomes part of the pack Runtime will load. Keep Builder dt and IR dt aligned, keep IR dimensions aligned with np and nq, make sure the IR support length covers the simulation horizon, and set pack form metadata intentionally (FLOW_FROM_EFFORT = Y+ISC, EFFORT_FROM_FLOW = Z+VOC, UNKNOWN only for packs without IR).
Builder Inspection
tdse_builder_info(...) is the fastest way to confirm what Builder currently has attached. Use it after configure and after every attach or clear. Fields worth logging are configured, dt/nh/np/nq, has_h/has_h_tau/h_layout, has_ir/ir_nsteps/ir_dt/ir_layout, and pack_form/pack_domain. tdse_builder_last_diagnostics(...) is the sticky failure-time snapshot for mutating Builder APIs; capture it whenever configure, attach, clear, metadata, or pack-write calls return non-OK. Once the pack is written, tdse_model_info(...) becomes the matching Runtime-side confirmation point.
tdse_builder_diagnostics_t diag = tdse_builder_diagnostics_init();
tdse_status_t rc = tdse_builder_last_diagnostics(builder, &diag);
if (rc == TDSE_STATUS_OK && diag.last_code != TDSE_STATUS_OK) {
tdse_runtime_error_category_t category =
tdse_status_error_category(diag.last_code);
printf("builder failure api=%s code=%d category=%s reason=%s details=%s\n",
diag.api_name,
diag.last_code,
tdse_status_error_category_name(category),
tdse_status_stable_reason(diag.last_code),
diag.details);
}
Write Gate Checklist
Before tdse_builder_write_pack(...), confirm that Builder is configured, H is attached, dimensions match, optional IR is either absent or correctly attached, pack metadata is explicit, and the output path is stable. After the write, validate the pack, inspect it, then hand off to Runtime for create and loop verification.
Pack writes use a same-directory temporary file, flush it, and atomically replace a regular target. Symbolic-link and multiply-linked targets are rejected so the writer does not follow an ambiguous artifact path.
Pack write completion has three distinct outcomes:
TDSE_STATUS_OK: the target was replaced and durability confirmation completed- an ordinary pre-commit error such as
TDSE_STATUS_IO: the target was not replaced TDSE_STATUS_COMMITTED_DURABILITY_UNCERTAIN: the target was already replaced, but the platform could not confirm parent-directory/crash durability
For the last outcome, do not assume that the old artifact is still present.
Inspect and validate the current target, preserve the stable reason
committed_durability_uncertain in incident evidence, and regenerate on known
reliable storage if crash durability is required.
Worked Paths
Path A: Direct-H Pack
Highest-confidence path: configure once ->attach H ->inspect ->write ->validate ->create Runtime model. Fewest transformations; easiest to isolate failures.
Path B: Frequency-Domain Source To Pack
Archive the frequency grid and matrix family -> run tdse_builder_h_from_spectrum_v3(...) -> attach -> inspect -> write -> validate. Needs more release discipline because a successful write does not prove the conversion policy was correct.
Path C: H + IR With Explicit Pack Meaning
Configure -> attach H -> attach IR -> tdse_builder_set_pack_meta_v2(...) intentionally -> inspect -> write -> validate -> create. Most likely to confuse downstream users if metadata is omitted.
Triage
Failure Modes
| Failure | Symptom | Root Cause | Fix |
|---|---|---|---|
TDSE_STATUS_OUT_OF_RANGE | tdse_step_ir fails mid-run | Simulation time exceeds IR support window | Extend IR sequence or clamp simulation horizon |
TDSE_STATUS_CONCURRENT_API_USE | sporadic non-OK in multi-thread run | same handle stepped by multiple threads | Serialize per handle; one handle per thread |
TDSE_STATUS_INVALID_ARG | immediate failure on create/step | null/shape mismatch in inputs | Validate pointers, dimensions, struct sizes |
TDSE_STATUS_NUMERIC | conversion/compression fails without changing outputs | finite inputs overflowed while deriving a result | Rescale source data or choose a representable grid; do not consume canary outputs |
TDSE_STATUS_COMMITTED_DURABILITY_UNCERTAIN | pack write is non-OK but target contains the new artifact | replacement committed, then directory durability confirmation failed | Validate the current target; archive the stable reason; regenerate on reliable storage if required |
| pack validation failure | create rejects model bytes | corrupted or incompatible pack | regenerate pack, inspect tdse_model_create_diagnostics_t |
Builder Failure Classes Worth Catching Early
| Failure Class | Typical Root Cause | Best Stage | Support Clue |
|---|---|---|---|
| dimension mismatch | np/nq/nh disagreement | configure/apply | Builder snapshot vs. source planning sheet |
| malformed descriptor | null pointer, bad struct size, invalid layout | apply | attach call fails immediately |
| tau-axis issue | invalid explicit nonuniform timing | apply H | has_h_tau vs. source timing mismatch |
| wrong matrix family | host supplied wrong physical meaning | preflight | pack validates but numerical behavior is wrong |
| IR horizon issue | sequence shorter than intended run | preflight/attach | Runtime fails at tdse_step_ir_v2(...) |
| metadata ambiguity | form/domain not set intentionally | pre-write review | cannot tell Y+ISC from Z+VOC |
| write-path issue | unstable output path or file handling | pack write | configure/attach succeeded but no artifact exists |
Builder-To-Runtime Failure Isolation
When a runtime test fails after a fresh pack write, split the investigation: did Builder produce the intended artifact, or did Runtime execute it incorrectly? This separation keeps teams from debugging the wrong layer.
Troubleshooting Decision Flow
Rapid checks: prefer tdse_model_create(...) over process-global create diagnostics; log tdse_model_info once at model create; log t, dt, and step index on each failed call; keep one deterministic repro input for local and automated runs.
Anti-Patterns
- re-configuring a handle and assuming previous
H/IRis still attached - treating
tdse_builder_write_pack(...)as proof of semantic correctness - attaching
IRwithout deciding pack representation metadata - debugging Runtime first when Builder snapshots were never captured
- letting Runtime compensate for Builder-side source interpretation mistakes
- using ad hoc output paths that break pack provenance
Pack Incident Triage
When a pack validation or create issue is reported, collect:
- Builder configure inputs (
dt,nh,np,nq) - Builder snapshot from
tdse_builder_info(...) - whether the pack came from direct
Hor spectrum conversion - any conversion or tail-processing settings
- whether
IRwas attached and what pack-form metadata was used - result of the
tdse_pack_validatecommand - result and diagnostics from
tdse_model_create(...)
If the first five items are missing, do not start by blaming Runtime.
