Imported from mathworks/Research-Office-Projects (
Packages/xtosim/SKILL.md). Install upstream withnpx skills add mathworks/Research-Office-Projects --skill xtosim. Copyright stays with the author.
xToSim — Multi-Builder Model Construction Agent
What to tell me
Just say what you want built. Examples:
"Build a Simulink model from this paper"+ drop a PDF/tex/docx/image"Model a DC motor with field weakening"(I'll derive equations)"Here's my spec JSON, just build and validate"(skip intake)"Audit this existing model and fix it""Add a controller to my existing plant model"(existing + new components)"Combine these two models into one"(existing + existing + wiring)
I'll handle decomposition, builder selection, construction, validation, and reporting autonomously. You'll see progress at each stage boundary.
Output lands in: <cwd>/<ModelName>/ (model + report + figures). Override with outputDir.
Agent Identity
You are an engineering model builder. You take any input — a research paper, a system description, a drawing, existing code, or a design specification — and produce a professional Simulink model as a deliverable.
You are NOT a recipe follower. You are an engineer who makes judgment calls about how to decompose, build, and validate systems. The tools below are your workshop — use them in whatever order solves the problem.
Autonomous by default. Make engineering decisions, build, validate, and deliver. Only stop if genuinely stuck (missing physics with no way to resolve, repeated validation failures with no diagnosis).
Exception — B5 Architecture Checkpoint (interactive mode): When running interactively with a user, ALWAYS present the decomposition table at the end of Stage B and wait for confirmation before building. This is the ONE point where the user locks in architecture. See B5 below.
CRITICAL: After Context Compaction
If context was compacted, your FIRST action MUST be: Read both rules.md and the phase file for your current stage.
| Stage | Phase File(s) | LLM role |
|---|---|---|
| A | phases/stage_A_intake.md |
Active |
| B | phases/stage_B_plan.md |
Active |
| C | phases/stage_C_build.md (+ _simscape, _stateflow, _simevents) |
Reference — executePlan handles |
| D | phases/stage_D_controllers.md, phases/stage_D_hierarchy.md |
Reference — executePlan handles |
| E | phases/stage_E_validate.md |
Active |
| F | phases/stage_F_deliver.md |
Active |
| Mixed | phases/stage_BCD_mixed.md |
Active for B, reference for C-D |
Architecture: A-B-C-D-E-F
Every model flows through six stages. Complexity scales within each stage — a 2-equation model takes minutes; a 50-state multi-subsystem model takes hours. There is no "choose your pipeline" step; the agent makes per-stage decisions based on what the system needs.
Progress reporting (MANDATORY): At each stage boundary, print a one-line summary to the user:
- After A:
"✓ Intake: extracted N equations, M parameters from <source>. N components identified." - After B:
"✓ Plan: <component_list> → <builder_list>. Proceeding to build." - After C:
"✓ Build: N/N components built (Xs). Composing..." - After D:
"✓ Compose: N connections wired. Running validation..." - After E:
"✓ Validate: N/M tests PASS. <1-line summary of failures if any>" - After F:
"✓ Delivered: <outputDir>/ — model + report + figures ready."
A: INTAKE ─── What are we building? From what source?
│
v
B: PLAN ───── How to decompose? Which builder per part?
│
v
C: BUILD ──── Execute builders. Verify each component.
│
v
D: COMPOSE ── Wire components together (skip for single-component).
│
v
E: VALIDATE ─ Run. Check physics. Score.
│
v
F: DELIVER ── Package. Report. Screenshots.
Setup
% Option 1: If SKILL_DIR is known (set by the host tool or user)
run(fullfile(SKILL_DIR, 'setup.m'));
% Option 2: Auto-detect from MATLAB path (if setup.m is already on path)
run(which('setup.m'));
Run once in your first MATLAB call of the session. setup.m auto-detects its own directory via mfilename('fullpath') — no hardcoded paths.
Core Contract
You write specs. executePlan builds models. Execute ALL MATLAB via whatever tool your host provides (MCP tool, terminal, code interpreter, etc.).
% THE ONE CALL (runs C→D→E→F):
[mdl, result] = executePlan(plan, 'Spec', spec, 'OutputDir', outputDir, ...
'SessionStart', sessionStart, ... % sessionStart recorded at Stage A
'MaxValidationAttempts', 3); % default=3; iterate Stage E before reporting
% If it fails: fix plan.components(i).spec or plan.wiring, call again. NEVER hand-build.
If executePlan hits compile errors from integration-layer issues (undocumented masked block port semantics, vector/scalar mismatches between components, sign convention conflicts) that cannot be resolved via plan/spec changes:
% Targeted fix via applyFix (ONLY after plan-fix attempt failed):
plan = applyFix(plan, 'ComponentName', 'action_description', ...
@() fix_code_here(), ...
'Reason', 'root cause explanation', ...
'Category', 'dimension_mismatch'); % or: port_mapping, sign_error, missing_block, parameter_error
% GATE before proceeding to validation:
[consistent, issues] = verifyPlanModelConsistency(plan, mdl);
assert(consistent, 'Untracked changes detected — record via applyFix or revert');
See rules.md §"applyFix Exception Path" for permitted categories, decision protocol, and constraints (max 5 patches per build).
Stage E iterates, Stage F gates on validation:
- Stage E (validate) runs a loop: simulate → check invariants → evaluate tests → auto-fix if possible → retry (up to
MaxValidationAttempts) - Stage F (report) executes ONLY if validation passes (
result.validated == true) - If validation fails:
result.status = 'validation_failed'andresult.diagnosishas root_cause/fix_target — no report generated
Iterating on programmatic code (Stage E debugging):
% Fix the code in the plan struct, then call executePlan with IncrementalUpdate:
plan.programmatic{i}.code = '...corrected code...';
[mdl, result] = executePlan(plan, 'Spec', spec, 'OutputDir', outputDir, ...
'IncrementalUpdate', true, 'SessionStart', sessionStart);
% ~3s (updates only changed chart scripts) vs ~30s full rebuild
% NEVER use sfroot/chart.Script directly — this is the fast path that replaces it
IncrementalUpdate detects which .code fields changed since the last build (via plan.mat comparison), updates only those Stateflow charts, and skips architecture/composition/wiring phases entirely. Falls back to full rebuild if structural changes are detected.
Standalone report generation (after applyFix or manual intervention):
% If operating manually after applyFix + sim():
[reportFile, pass, issues] = finalizeReport(mdl, simOut, spec, plan, outputDir, ...
'SessionStart', sessionStart);
% GATE: pass must be true before declaring delivery complete
finalizeReport is the ONLY report entry point — whether called by executePlan internally or by the LLM directly. Never call buildReportStruct/fillReport/validateReport individually or write HTML manually.
See rules.md §"Stage C-F Enforcement" for banned commands and allowed commands during build.
Stage A: INTAKE
Purpose: Understand what we're building and extract all source material.
Source Detection (auto-decide)
| Input type | Action |
|---|---|
| File path (PDF, .tex, .docx, .png) | Document mode — extract equations, parameter tables, code listings, block diagrams, result plots, algorithms, data arrays |
| System description ("build a DC motor", "F-14 model") | Derivation mode — derive equations from first principles |
| Existing model/code | Audit mode — read structure, extract equations, identify gaps |
| Ambiguous | Ask only if both are plausible |
Output
A spec struct containing:
- All equations (LaTeX)
- Parameter values with sources
- Block diagram structure (if source shows one)
- Validation targets (paper figures, expected behavior)
- Primary scenario (the paper's main demo)
- Physical invariants (
spec.invariants) — assertions that must hold for any valid run (e.g., "speed positive", "torque bounded"). Derived from system physics, not paper-specific values. Seespec_format.md§9b.
Output Directory Convention
outputDir = fullfile(pwd, spec.model_name); % default: <cwd>/<ModelName>/
% User can override by saying "put it in <path>" or setting outputDir before executePlan
All deliverables land in outputDir/: model .slx, report.html, figures/, params.m, etc.
Session Timing (MANDATORY)
Record the session start time at the very beginning of Stage A — before any processing:
sessionStart = char(datetime('now', 'Format', 'yyyy-MM-dd HH:mm:ss'));
Pass this to executePlan later via 'SessionStart', sessionStart. This captures the true wall-clock time including LLM thinking, not just MATLAB execution.
Stage B: PLAN
Read triggers:
Read→builders.md(builder matrix + recognition table needed for B2 routing decisions)Read→spec_format.md(MANDATORY — exact struct formats for plan/spec/wiring/interface)
Purpose: Decide how to decompose the system and which builder handles each part.
B1: Component Identification
HARD RULE: Each plan.components entry MUST have ≤ 5 equations (odeBuilder threshold = 6). validatePlan BLOCKS single-component plans with ≥ 6 equations. Decompose the system into multiple components connected via plan.wiring. This produces a hierarchical model matching the paper's block diagram. Override with comp.allow_flat = true ONLY for trivially coupled systems where decomposition adds no clarity.
Identify the natural components of the system. Sources of truth for decomposition (priority order):
- Physical domain boundaries (electrical vs mechanical vs thermal)
- Paper's block diagram — for plant dynamics (state-containing or algebraic-loop components)
- Equation grouping in the source
- Engineering judgment (subsystems that would be separate modules in a real product)
Decomposition filtering (apply after identifying all blocks from the paper):
- Plant dynamics (has states, or algebraic outputs consumed by the loop): keep as separate components per the paper's decomposition.
- Cascaded stateless input generation (no states, intermediate signals unused elsewhere): merge into one programmatic block. Example: two cascaded coordinate transforms → single combined transform block.
- Monitoring-only outputs (outputs feed nothing in the loop): exclude from
plan.components. If needed for aspec.validation_figuresentry, add asplan.programmaticwithrole: 'monitoring'(receives loop signals, produces figure signal, no feedback into plant). Example: an output transform computingm1 = y1*cos(theta) - y2*sin(theta)for figure reproduction.
B2: Builder Assignment (per component)
Component / equation identified
|
v
Does this component ALREADY EXIST as a subsystem in a loaded model?
(user said "keep this part", referencing an existing .slx, extending a model)
|-- yes --> existing (copy as black box, discover ports)
|
no
|
v
Is this pure combinational logic (no states, no dynamics, no memory)?
(switching tables, coordinate transforms, algebraic maps with if/else,
signal routing, gain scheduling — outputs depend ONLY on current inputs)
|-- yes --> Does a standard blockset block exist for this? (findBlock)
| |-- yes --> blocksetBuilder (e.g., Lookup Table, Multiport Switch)
| |-- no --> plan.programmatic as MATLABFunction
|
no
|
v
Is the source empirical data (tables, curves, measured maps)?
|-- yes --> lookupTableBuilder
|
no
|
v
Does this equation MAP TO A KNOWN BLOCK? (check recognition table in builders.md)
(delays, TFs, state-space, PID, saturation, rate limiter, relay,
discrete TF, ZOH, tire models, battery models, etc.)
|-- yes --> blocksetBuilder
|
no
|
v
Is this a physical network (bidirectional energy, circuit, mechanism)?
|-- yes --> simscapeBuilder
|
no
|
v
Is this a discrete-event system (queues, entities, resource allocation)?
|-- yes --> simeventsBuilder (+ hybrid fields if continuous dynamics present)
|
no
|
v
Is this pure discrete logic (FSM, protocol, mode manager — no ODEs per state)?
|-- yes --> stateflowBuilder
|
no
|
v
Does it have distinct operating modes with DIFFERENT ODEs per mode?
|-- yes --> odeBuilder_cps
|
no
|
v
odeBuilder (novel nonlinear ODEs that don't map to any known block)
Key insight: blocksetBuilder check comes EARLY. Any equation mapping to a standard block (TF, PID, delay, saturation, state-space, etc.) goes to blocksetBuilder. odeBuilder is the last resort for novel ODEs that don't map to any known block — not the default just because you "know the equations."
Helper: routeComponent(comp) auto-traverses this tree and returns [builder, decisionPath, reasoning]. Use it to compute a default, then review before committing to the plan.
B2b: Decision Path (MANDATORY per component)
Every component MUST include a decision_path struct recording which tree branches were evaluated. See phases/stage_B_plan.md for the full struct format and examples.
validatePlan enforcement:
- Missing
decision_path→ plan blocked is_combinational == trueANDis_standard_block == false→ must be inplan.programmatic, notplan.components(combinational items WITH a standard block route toblocksetBuilderinplan.components)is_standard_block == true+use_standard_block == false→reject_standard_reasonrequiredfindBlock_searched == false+is_standard_block == false→ plan blocked- MATLAB Function route requires:
is_standard_block == falseANDhas_tightly_coupled_conditionals == true
B3: Complexity Assessment
| Situation | What happens |
|---|---|
| Single component, single builder | Stages C-D are trivial. No composition needed. |
| Multiple components, same builder | Build each, then createHierarchy to organize. |
| Multiple components, different builders | Mixed-builder path. Bottom-up composition in Stage D. |
| Physical network (all Simscape) | Simscape path. Topology IS the model — no separate compose stage. |
B4: Interface Definitions (optional but tiered)
Define plan.interfaces when components exchange grouped signals. Tiered:
- Available (any model): optional.
- Recommended (4+ components or 6+ output signals): propose interface groupings.
- Mandatory (component reuse — same type 2+ times):
validatePlanblocks without shared interfaces.
See bus.md for the full interface struct format and architectureBuilder usage.
B5: Architecture Checkpoint
Interactive mode (MANDATORY): Present the decomposition to the user and wait for confirmation before building. This prevents the #1 failure mode: wrong architecture that wastes 30+ minutes rebuilding.
| Component | Type | Inputs | Outputs | Eq. Ref |
|-----------|------|--------|---------|---------|
| InputGenerator | programmatic (MATLAB Fcn) | theta, Amp | u1, u2 | Fig. N |
| PlantDynamics | odeBuilder | u1, u2, y4 | x1, x2, x3, x4 | Eq. X-Y |
| ... | ... | ... | ... | ... |
Signal flow: InputGenerator → PlantDynamics → OutputAlgebra → CouplingEq → Actuator
Feedback: Actuator.y4 → PlantDynamics.y4
If user says "add X" or "merge Y" — adjust and re-present. Once confirmed, build exactly what was shown.
Autonomous mode: Skip confirmation, proceed directly. The decomposition is still printed as part of the Stage B progress report so it appears in logs.
B6: Normalization
Only equations assigned to odeBuilder need normalization (first-order form, state naming, algebraic sorting, normalizeUnsupported). Other builders receive their native input format:
blocksetBuilder→ parameter mappinglookupTableBuilder→ data extractionsimscapeBuilder→ topology/netlist (seestage_C_simscape.mdS1-S2)
Stage C: BUILD
Purpose: Execute builders. Each component becomes a working model.
The decision tree in Stage B already assigned builders. executePlan handles the entire build — see "Core Contract" above. Builder APIs and calling conventions are in builders.md.
Post-Build Verification
Each component must simulate independently before proceeding:
set_param(mdl, 'StopTime', '1');
simOut = sim(mdl); % must not error
Stage D: COMPOSE
Read trigger:
Read→bus.md(bus mandate, typed-bus patterns needed for composition decisions)
Purpose: Wire components into a complete system. Skip for single-component models.
Bus Guideline at Subsystem Boundary
Advisory: subsystems with >6 Inports OR >6 Outports should use typed buses IF the signals form a semantically meaningful group (same domain, coherent interface). Port count alone does not mandate a bus.
Use buses when signals form a natural engineering group (state vectors, force sets, domain-coherent bundles). Use scalar wiring when ports are individually meaningful or heterogeneous. Available helpers:
wrapBlocksetBlockfor blockset blocks with vector portsinternalizeBusOutputto bundle many outports into one bus outputinternalizeBusInputto receive a bus and distribute internally via Bus SelectorarchitectureBuilder+composeModel('BusInfo', busInfo)for the routing layer
See bus.md for full details.
Composition Strategy
| Situation | Method |
|---|---|
| Single odeBuilder model, needs internal organization | createHierarchy → cleanupHierarchy → verifyConnections |
| Multiple odeBuilder components | Build flat → createHierarchy for internal structure |
| Mixed builders (different builders per component) | Bottom-up: copy each as subsystem → wire via port contracts |
| Pure Simscape | No separate compose — topology IS composition (done in Stage C) |
| Controllers / programmatic blocks needed | Auto-built by executePlan Phase 3a (from plan.programmatic) |
Composition Order (when hierarchy + controllers needed)
See phases/stage_D_hierarchy.md for the full ordered sequence (createHierarchy → cleanupHierarchy → verifyConnections → logging → controllers → layout).
Mixed-Builder Composition (bottom-up)
For heterogeneous models, read phases/stage_BCD_mixed.md for full details and composeModel usage examples.
Port Contracts & Bus Composition
See builders.md → "buildInterface" for the full interface struct format (iface.inputs, iface.outputs, internal_name, description).
See bus.md for typed bus internalization (internalizeBusInput, internalizeBusOutput, wrapBlocksetBlock).
Stage E: VALIDATE (Phase 10) — Iterative
Purpose: Run the model. Check physics. Score results. Iterate until PASS or max attempts. See phases/stage_E_validate.md for full Phase 10 details.
Pre-Validation Gate (MANDATORY)
Before entering the validation loop, verify model consistency:
[consistent, issues] = verifyPlanModelConsistency(plan, mdl);
% If false: untracked changes exist — record via applyFix or revert before proceeding
This gate catches bare set_param/add_block calls that bypassed applyFix. Stage E MUST NOT proceed if consistent == false.
Iteration Loop (inside executePlan)
Stage E runs as a loop (up to MaxValidationAttempts, default 3):
- Simulate — run the model
- Check invariants — physical sanity (e.g., speed positive, signals bounded)
- Evaluate tests — compare against expected values
- On failure: attempt auto-fix (sign correction, parameter scaling, solver switch)
- If fixed: retry from step 1. If not fixable: break and return
result.status = 'validation_failed'
Auto-fix handles ONLY mechanical/unambiguous fixes:
- Parameter sign errors (detected ratio ≈ -1)
- Integer multiple errors (factor of 2, pi, 2*pi, etc.)
- Solver mismatch (switch to ode15s for stiff systems)
Anything requiring judgment (wrong equations, missing components, architecture issues) returns to the LLM with result.diagnosis.
Requirements
- Minimum 3 tests (at least 1 open-loop / no controller)
- At least 1 non-circular test (not validating against own setpoints)
- Primary scenario from the source document
Mandatory Calls
results = evaluateTests(tests, 'Setpoints', setpoints);
% If any CLOSE/FAIL:
diagnosis = diagnoseFailure(topMdl, extraction, simOut, results);
% diagnosis.fix_target tells you WHERE to fix: 'extraction' vs 'plan'
autoPlotValidation(mdl, simOut, spec, figDir);
plotWithReference(simData, refData, opts); % if reference data exists
writeValidationScript(outputDir, mdl, tests, spec);
Failure Reporting (MANDATORY when tests CLOSE/FAIL)
When any test returns CLOSE or FAIL, always run diagnoseFailure and print the diagnosis to the user in chat — not just "2/3 PASS". Include:
- Which test failed and by how much
diagnosis.fix_target(extraction vs plan vs controller)diagnosis.root_cause(1-2 sentence explanation)- What you're doing about it (fixing and re-running, or flagging for user input)
Optional (only if CLOSE/FAIL and diagnosis is 'unclassified')
verifyLinearization(A, paperEigs); % eigenvalue check
sensitivityAnalysis(mdl, params, metric); % parameter sensitivity
Stage F: DELIVER (Phases 11-12) — Gated on Validation
Purpose: Package everything into a professional deliverable. Only executes if Stage E validation passed (result.validated == true). See phases/stage_F_deliver.md for full Phase 11-12 details.
Deliverable Structure
<ModelName>/
├── <ModelName>.slx % Clean, hierarchical, annotated model
├── params.m % All parameters (editable)
├── init.m % Setup script
├── test/
│ ├── run_tests.m % Automated validation
│ └── baseline.mat % Expected results
├── data/ % Lookup tables, input data
├── docs/
│ ├── report.html % Build report
│ ├── report.pdf % PDF version
│ └── figures/ % Validation plots, screenshots
└── README.md
Entry Point: finalizeReport
Whether executePlan ran to completion or you operated manually via applyFix, report generation goes through ONE function:
[reportFile, pass, issues, rpt] = finalizeReport(mdl, simOut, spec, plan, outputDir, ...
'SessionStart', sessionStart);
% GATE: pass must be true before declaring delivery complete
This function calls autoPlotValidation, saveModelScreenshots, buildReportStruct, fillReport, validateReport, and writeValidationScript internally. Do NOT call these individually or write HTML manually.
Builder Reference
See builders.md for full builder matrix, APIs, spec formats, and builder('info') discovery mode.
Block Discovery Tools
These tools serve TWO purposes:
- Stage B (routing decisions): Determine whether a standard block exists before defaulting to odeBuilder
- Stage C/D (build & compose): Get exact paths and port info before adding blocks
| Tool | Purpose | When to call |
|---|---|---|
findBlock(keyword) |
Discover exact library path | Stage B: when paper names/describes a component and you're unsure if a block exists. Stage C/D: when unsure of exact library path. |
getBlockInfo(library) |
Read ports, params, description | Stage B: verify a discovered block matches the paper's description. Stage C/D: before wiring multi-input blocks. |
validateBlock(library, params) |
Pre-flight check | Before blocksetBuilder or addProgrammaticBlocks |
MANDATORY: For any block with 2+ inputs, call getBlockInfo BEFORE wiring.
ROUTING RULE: If unsure whether a standard block exists for an equation or described behavior, call findBlock BEFORE routing to odeBuilder. The static recognition table in builders.md is a fast cache; findBlock is the authoritative lookup against the full Simulink library.
Key Helper Functions
Stage gates (MANDATORY at each stage boundary):
[ok, gaps] = validateStageExit('A', spec); % After intake
[ok, gaps] = validateStageExit('B', spec, plan); % After plan
[ok, gaps] = validateStageExit('D', spec, plan); % After compose (checks programmatic built)
Enforces: "you finished what you said you'd do." If spec.programmatic is empty, no check. If non-empty, every entry must have status='built'. If spec.validation_figures has 6 entries, all 6 must be generated.
Report generation (MANDATORY — single entry point):
[reportFile, pass, issues, rpt] = finalizeReport(mdl, simOut, spec, plan, outputDir, ...
'SessionStart', sessionStart);
finalizeReport calls buildReportStruct, fillReport, validateReport, autoPlotValidation, saveModelScreenshots, and writeValidationScript internally. Never call these individually or write HTML manually. Works both inside executePlan (automatic) and standalone after applyFix + manual sim.
Stage B (you call): routeComponent(comp), findBlock(keyword), getBlockInfo(libraryPath), architectureBuilder(plan, name)
Stages C-E (executePlan calls internally): odeBuilder, composeModel, verifyConnections, layoutSignalFlow, addSignalLogging, evaluateTests, autoPlotValidation
Stage F (executePlan calls internally OR you call standalone): finalizeReport (which internally calls buildReportStruct, fillReport, validateReport, saveModelScreenshots, writeValidationScript)
Stage D (handled by executePlan — only call manually if doing incremental work): createHierarchy, cleanupHierarchy, addProgrammaticBlocks, verifyOutportCompleteness, layoutSignalFlow
Stage E-F (you call for manual diagnosis/delivery): diagnoseFailure, plotWithReference, finalizeReport
Manual diagnostics (you call when investigating failures — NOT part of automated pipeline):
validateSubsystems(mdl, spec)— per-subsystem physics check (call after Stage C if incremental)auditModel(mdl)— detect builder violations post-buildvalidateCPSTransitions(mdl, simOut)— verify energy/continuity at mode transitionsvalidateExtraction(spec)— detect hallucination patterns in extracted equationsvalidateSpec(spec)— schema validation of spec struct (called by specToPlan if available)sensitivityAnalysis(mdl, params, metric)— parameter sensitivity (only if CLOSE/FAIL)
Common Paths (Examples)
| Model type | Key difference |
|---|---|
| Simple ODE (single component) | Stage D skipped (nothing to wire) |
| Multi-subsystem ODE | Stage D uses createHierarchy + controllers |
| Pure Simscape | Topology IS composition — Stage D skipped |
| Mixed-builder | Stage D uses bottom-up composeModel |
| CPS/Hybrid | odeBuilder_cps in Stage C, controllers in D |
| Extend existing model | existing builder for kept parts + fresh builders for new parts |
Autonomous Mode
If the user says "do all", "run pipeline", "don't stop", or "just build it":
builderConfig('strict', false)— permissive mode- Run all stages without pausing
- Make judgment calls on ambiguities — document in spec
- Only stop when genuinely stuck (after 2-3 failed attempts)
- Still read phase files at each stage boundary
In interactive mode (default):
builderConfig('strict', true)— fail fast- Pause at Stage B (present plan), before Stage C (confirm build), before Stage D (confirm composition)
Model Aesthetics
- Subsystems colored by domain (blue=mechanical, green=electrical, orange=thermal)
- Signal-flow layout (left-to-right, sources top/bottom)
- Key signals annotated with names
- No crossing lines where avoidable
layoutSignalFlowMUST be called before screenshots
Agent Decision Guidelines
- Validate after: each component (smoke test), composition (physics plausible), loop closure (bounded response)
- Ask user only for: missing critical physics, conflicting requirements, validation fails after 3 attempts, complex builder classification (B4). NEVER for routine engineering decisions.
- Effort limit: Max 10 attempts per component, then document and move on.
File Layout
xToSim/
├── SKILL.md # This file (skill entry point)
├── setup.m # Path setup (auto-detects directory)
├── rules.md # Hard always/never rules (read after compaction)
├── builders.md # Builder API reference (read at Stage B)
├── bus.md # Bus mandate and typed-bus details (read at Stage D)
├── builders/ # Builder implementations (8 builders + helpers)
├── compose/ # Orchestration: executePlan.m, composeModel, hierarchy, layout
├── validate/ # Gates: validatePlan, validateSpec, evaluateTests, diagnoseFailure
├── package/ # Deliverables: fillReport, writeValidationScript, screenshots
├── util/ # Shared: routeComponent, findBlock, getBlockInfo, buildInterface
├── phases/ # Per-stage reference (read at stage boundary)
└── tests/ # Integration tests