Skip to content

FE-1212: Read net parameters from a metric#9043

Merged
kube merged 3 commits into
mainfrom
cf/fe-1212-read-net-parameters-from-a-metric
Jul 16, 2026
Merged

FE-1212: Read net parameters from a metric#9043
kube merged 3 commits into
mainfrom
cf/fe-1212-read-net-parameters-from-a-metric

Conversation

@kube

@kube kube commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

🌟 What is the purpose of this PR?

Lets metric code read the net's parameters — previously metrics could only read place state (state.places.<Name>.count / .tokens). A metric can now be expressed relative to a tunable model parameter, e.g. utilisation against a capacity parameter.

Resolves FE-1212.

🔗 Related links

🔍 What does this change?

Net parameters are exposed to metrics as an ambient value (there is no parameters function argument to declare, unlike dynamics/lambdas/kernels):

const { capacity } = parameters;
return state.places.Queue.count / capacity;

Values are bound to the run's resolved net parameter values (defaults overridden by scenario parameter overrides), matching how dynamics/lambdas/kernels resolve them. Scenario parameters remain unavailable to metrics.

  • HIR
    • buildMetricContext now populates parameters from the root net (gated by the parameters extension).
    • Lowering treats parameters as ambient in the metric surface, so parameters.x and const { x } = parameters lower to parameter reads. Typecheck / emit / analyze / lint already handle parameter reads generically.
    • instantiateHirMetric binds __params to the resolved values instead of {}.
  • Runtime
    • createHirMetricEvaluator accepts parameterValues; threaded through the single-run compiled model, the Monte-Carlo local + worker paths, and the simulation-timeline hook (which rebinds when values change, including scenario overrides).
    • New shared resolveNetParameterValues helper (mirrors buildSimulation's resolution).
  • TypeScript LSP: the metric editor declares an ambient const parameters: Parameters, so completion and type-checking work.
  • Docs / AI / schema: updated petri-net-extensions.md, the AI metric prompt in ai.ts, and the metric schema description (all previously stated parameters were unavailable in metrics).

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

  • modifies an npm-publishable library and I have added a changeset file(s)

📜 Does this require a change to the docs?

  • require changes to docs which are made as part of this PR

🕸️ Does this require a change to the Turbo Graph?

  • do not affect the execution graph

⚠️ Known issues

None.

🛡 What tests cover this?

  • HIR lowering: ambient parameters.<name> and const { x } = parameters lower to param reads; bare parameters is rejected (lower-typescript.test.ts).
  • Buffer emit + instantiate: a metric reading ambient params executes with bound values (emit-buffer-js.test.ts).
  • Runtime evaluator binds parameter values (hir-metric.test.ts).
  • TypeScript LSP end-to-end: metric reading a defined net param → no diagnostics; unknown param → error (new metric-session.test.ts).
  • Full suites green: petrinaut-core (817) and petrinaut (154); lint:tsc + lint:eslint clean on both.

❓ How to test this?

  1. Open a net with a numeric net parameter (e.g. the SIR example) in Petrinaut Storybook.
  2. Create/edit a metric that reads it, e.g. return state.places.Infected.count * parameters.infection_rate;.
  3. Confirm the editor type-checks it (autocompletes parameters.), the metric plots on the timeline, and overriding the parameter (directly or via a scenario) changes the plotted values.

Metric code can now read net parameters ambiently as `parameters.<name>`,
bound to the run's resolved values (defaults + scenario parameter
overrides). Scenario parameters remain unavailable to metrics.

- HIR: metric surface context exposes net parameters; lowering treats
  `parameters` as ambient; `instantiateHirMetric` binds `__params`.
- Runtime: `createHirMetricEvaluator` accepts parameter values; threaded
  through the compiled model, Monte-Carlo local/worker paths, and the
  simulation timeline. Adds a shared `resolveNetParameterValues` helper.
- TypeScript LSP: declares ambient `parameters` in the metric editor.
- Docs, AI prompt and metric schema updated.
@kube kube self-assigned this Jul 16, 2026
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment Jul 16, 2026 3:59pm
petrinaut Ready Ready Preview, Comment Jul 16, 2026 3:59pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hashdotdesign-tokens Ignored Ignored Preview Jul 16, 2026 3:59pm

@github-actions github-actions Bot added area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team labels Jul 16, 2026
@kube
kube requested review from CiaranMn and YannisZa July 16, 2026 15:13
@kube
kube marked this pull request as ready for review July 16, 2026 15:15
@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes metric compilation, instantiation, and evaluation paths across single-run and Monte Carlo; behavior depends on parameter resolution matching the rest of the engine, but scenario params remain blocked and coverage is broad.

Overview
Metric code can now read root-net parameters as ambient parameters.<variableName> (e.g. return state.places.Queue.count / parameters.capacity), alongside existing state.places.* access. Scenario parameters stay unavailable in metrics.

The HIR metric surface treats parameters as ambient: parameters.x and const { x } = parameters lower to parameter reads; bare parameters is rejected. buildMetricContext fills parameters from the root net (when the parameters extension is on). instantiateHirMetric takes resolved parameterValues and binds them as __params instead of {}.

Runtime wiring adds resolveNetParameterValues (same resolution as dynamics/lambdas/kernels) and threads values through createHirMetricEvaluator, single-run compiled-model, Monte Carlo local/worker/specs, and SimulationFrameRawView.parameterValues so per-run overrides apply. The metric LSP declares ambient parameters: Parameters; docs, AI prompt, schema, and changeset are updated. The simulation timeline recompiles/rebinds metrics when resolved net parameters change.

Reviewed by Cursor Bugbot for commit 153bfab. Bugbot is set up for automated code reviews on this repo. Configure here.

Expression metrics baked the shared config's resolved net parameters into
the evaluator once at experiment init. Monte Carlo runs can override
parameters per run, so a metric reading ambient `parameters.<name>` would
report the shared values rather than the parameters each run actually used.

Expose each run's resolved `parameterValues` on the frame raw view and have
the metric evaluator bind `__params` from the frame (falling back to the
construction-time values when a frame source carries none), so per-run
overrides are honoured.
@kube

kube commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author

Confirmed this was a real bug — thanks. The Monte-Carlo simulator resolves parameters per run ({...config.parameterValues, ...runConfig.parameterValues} in run-state.ts) and stores each run's resolved values on run.parameterValues, but the expression-metric evaluator baked the shared config's values in once at experiment init, so a metric reading ambient parameters.<name> would report the config values regardless of per-run overrides — exactly the parameter-sweep case this feature targets.

Fixed in 153bfab:

  • SimulationFrameRawView now carries an optional parameterValues, populated from run.parameterValues in the Monte-Carlo frame reader.
  • createHirMetricEvaluator binds __params to a stable object refreshed from each frame's own resolved values (falling back to the construction-time values when a frame source carries none — single-run and timeline are unaffected).

Added an end-to-end test in monte-carlo-simulator.test.ts: two runs overriding weight to 10 and 20 with a return parameters.weight; metric now aggregate to a mean of 15 (previously would have been the config default of 1).

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 153bfab. Configure here.

@kube
kube enabled auto-merge July 16, 2026 17:35
@kube
kube added this pull request to the merge queue Jul 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 16, 2026
@kube
kube added this pull request to the merge queue Jul 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 16, 2026
@kube
kube added this pull request to the merge queue Jul 16, 2026
Merged via the queue into main with commit 63a51e5 Jul 16, 2026
51 checks passed
@kube
kube deleted the cf/fe-1212-read-net-parameters-from-a-metric branch July 16, 2026 18:51
This was referenced Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

2 participants