FE-1219: Define and enforce a Scenario HIR for server-side Petrinaut optimization - #9060
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
PR SummaryMedium Risk Overview The CLI calls HIR lowering adds scenario-specific rules (e.g. no Reviewed by Cursor Bugbot for commit 718ddcd. Bugbot is set up for automated code reviews on this repo. Configure here. |
47f2fea to
a38af6e
Compare
718ddcd to
f0e2672
Compare
a38af6e to
e48cebd
Compare
f0e2672 to
e69446c
Compare
e48cebd to
a72b3b5
Compare
e69446c to
33a0607
Compare
a72b3b5 to
0cdc094
Compare
33a0607 to
7f08ccf
Compare
…optimization Server-side scenario materialization now goes through the existing restricted HIR pipeline instead of executing manifest-authored strings via sandboxed `new Function`, closing the last unrestricted raw-code path on the optimizer's server path. The in-editor sandbox path is unchanged. - petrinaut-core: new `scenarioExpression` and `scenarioInit` HIR surfaces, lowered, typechecked, and instantiated over compiler-emitted source only. - Scenario orchestration extracted to `compile-scenario-core.ts`, shared by the unchanged sandboxed `compileScenario` (editor) and the new Node-only `compileScenarioProgram` (compile once per study, evaluate per trial). - petrinaut-cli: the scenario program is compiled once at bootstrap, so a manifest outside the supported subset fails startup with the offending path; per-trial evaluation runs pre-instantiated evaluators. - `Math.random()` is a compile error on scenario surfaces (determinism), and redeclaring the `scenario`/`parameters` inputs is rejected to match the sandbox. - Docs: the threat model's raw-execution path is removed, scenarios.md and hir/README.md document the subset and that server-compiled equality is strict.
0cdc094 to
b7490e8
Compare
7f08ccf to
ba0f6f1
Compare
🌟 What is the purpose of this PR?
Makes server-side Petrinaut scenario materialization go through the existing restricted HIR pipeline instead of executing manifest-authored strings via sandboxed
new Function, closing the last unrestricted raw-code execution path on the optimizer's server path. The in-editor sandbox path is unchanged.🔗 Related links
🚫 Blocked by
#9066 → #9058 → this); needs FE-1220: Harden and document Petrinaut optimization execution isolation #9058'sthreat-model.mdandOPTIMIZATION_INTEGRATION.md🔍 What does this change?
petrinaut-core: two new HIR surface kinds —scenarioExpression(a single expression over(parameters, scenario)→ scalar) andscenarioInit(a statement body → record of place-name → count | token records) — lowered, typechecked, and instantiated over compiler-emitted source only.compile-scenario-core.ts, shared by the unchanged sandboxedcompileScenario(editor) and a new Node-onlycompileScenarioProgram(compile once per study, evaluate per trial). Exported only via the Node-only./compiled-modelsubpath, so the main entry gains no TypeScript-compiler dependency.Math.random()is a compile error on scenario surfaces (determinism).petrinaut-cli:createOptimizationProtocolcompiles the scenario program once at bootstrap; per-trialoptimization.evaluateruns the pre-instantiated evaluators. No sandboxedcompileScenarioreferences remain in CLI source.const/callback parameter shadowing thescenario/parametersinputs (hir:redeclared-parameter), matching the sandbox; documents that server-compiled scenario equality is strict (==→===) and can differ from the editor for mixed-type comparisons.Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
🛡 What tests cover this?
New
petrinaut-coretests: a parity suite (HIR program vs sandbox for representative scenarios incl. code-mode colored tokens and the unknown-place-skip quirk), a rejection matrix (dynamic import,process,globalThis,fetch,Function, template substitution, loops,Math.random, wrapper-name shadowing), and a security test proving zero dynamic evaluation per trial. Newpetrinaut-clitests: bootstrap rejection listing offending paths, compile-once-evaluate-many, and aFunction-proxy test proving no per-trial dynamic evaluation.❓ How to test this?
turbo run test:unit --filter '@hashintel/petrinaut-core' --filter '@hashintel/petrinaut-cli'examples/supply-chain-profit-optimization.jsonand confirm it evaluates; confirm an out-of-subset scenario manifest fails at bootstrap with the offending path in the message.