Skip to content

physim: run declared lab worlds (continuum ALife models) through PhySim - #40

Draft
swpo wants to merge 15 commits into
PrimeIntellect-ai:mainfrom
swpo:labworlds-adapter
Draft

swpo wants to merge 15 commits into
PrimeIntellect-ai:mainfrom
swpo:labworlds-adapter

Conversation

@swpo

@swpo swpo commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • physim/labworld.py: runs a declared lab world (fields, grid and dx, native dt and steps per tick, ports with sign, gain and clip, noise forms and intensity in world units, observe-only derived channels) through PhySim's OracleRunner, via LabStepper and LabOracleRunner.
  • physim/labbundle.py: LabBundle, a bundle whose manifest declares a lab world, opened by required_bundle; it binds world, preparation, suite and simulator identity and refuses bytecode caches.
  • physim/taskset.py: agent, finalize and scoring timeouts and the agent sandbox resources become task config. The scoring timeout grows with the suite (cases x (predictor wall limit + 60 s) + 900 s, at least 7200 s). Defaults for existing configs are unchanged.
  • LABWORLDS.md: the world contract, acceptance versus curation checks, and results for the first worlds. It cites world-specific suite scripts that are kept with the evaluation material and are not part of this PR.

Testing

  • tests/test_envs.py: 12 passed.
  • Tasks built from an existing config keep their old timeouts and resources.

🤖 Generated with Claude Code

Note

Add lab-world (continuum ALife) support to PhySim via LabBundle and LabOracleRunner

  • Adds labworld.py with the LabWorld declaration model (ports with gains/clips, signed actuators, derived channels, per-field noise), the LabStepper that advances worlds by public ticks with injections and additive/proportional/conserved noise, and LabOracleRunner that separates inject ports from observed ports.
  • Adds labbundle.py with a LabBundle that validates lab manifests, declarations, apparatus, and prepared states, and gates oracle construction on a source-digest implementation identity.
  • open_bundle now selects LabBundle for lab-schema manifests and the existing Bundle otherwise; required_bundle in taskset.py uses it.
  • Task config gains configurable agent, finalize, and scoring timeouts plus agent resources; the default scoring timeout now scales with suite size instead of a fixed 7200 seconds.
  • Documents the draft world contract, prototype results, and open questions in LABWORLDS.md.
  • Risk: LabBundle.check_runtime rejects bundles whose recorded identity differs from current sources and dependencies (NumPy/SciPy versions), so bundles break when those change. Scoring timeout defaults change from fixed 7200s to a suite-size-derived value.

Macroscope summarized 23f07a3.

claude added 15 commits November 2, 2026 05:49
…eRunner, with a draft world contract

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj
…ed ports

labworld.LabOracleRunner subclasses blobround6.OracleRunner: inject ports index a declared
actuator roster of (field row, sign) pairs, sample arrays carry every observed port, and
observe-only rows (derived channels such as the flow speed, declared with Derived) cannot be
actuators. It reuses the base constructor checks, _parse, member seeding, devices, pose
updates and sampling, and repeats only the sample_truth scheduler with the actuator count and
the actuator's field and sign. LabWorld gains actuators (Actuator(field, sign)) and derived;
declaration() omits them when undeclared so labeval's frozen suites keep their identity.
ports_check.py shows bit-identity with OracleRunner on phase_membrane and a native Blobkit
world, a finite '-' vorticity actuator on the fed vortices, and an observe-only channel that
the sensors return and the roster rejects. blobround6.py, devices.py and bundles.py are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj
…st; record round-2 results in LABWORLDS.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj
…s the refinement nulls

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj
…ield in LabWorld

noise_corr = {field: ell}: the field's white draws are smoothed by a periodic Gaussian
of sd ell world units and rescaled to the white form's per-point variance; conserved
noise smooths the divergence of the white flux (no mass added). Draws per step are
unchanged. Without noise_corr the stepper and the declaration are unchanged (runner
output byte-identical to 637f4cb on the rods world with all three noise forms).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj
…e_intensity)

A field listed in noise_intensity reads its sd as the intensity of the
continuum noise: white draws are scaled by 1/dx (0.5/dx^2 for the conserved
flux divergence) and, with an ell in noise_corr, smoothed by the Gaussian at
unit gain for k = 0 instead of being rescaled to the white per-point variance.
The low-wavenumber spectrum is then sd^2 per native time whatever ell or dx;
the per-point sd falls like 1/(2 sqrt(pi) ell). At dx = 1 without ell it is
the white form bit for bit.

The per-step noise moves into LabStepper.add_noise unchanged. Existing
declarations are bit-identical to 77a6d83 (white in all three forms,
variance-matched noise_corr, runner_demo and vortex_demo declarations, signed
roster: sample bytes, generator state, declaration(); labeval's frozen suite
declarations unchanged).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj
…IPS; intensity-scaled noise

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj
labbundle.py: a lab world as a PhySim bundle (schema physim-lab-bundle-v1): world files (world file,
labkit modules, observe-only channel module), declaration, apparatus, prepared fields and carry keys
(no pickle), suite, truths and checks, with every file and the implementation (runner, adapter,
devices, scorer and labbundle sources; numpy/scipy versions) hashed into the identities. LabBundle
subclasses Bundle with the interface taskset and evaluation use; open_bundle selects it from the
manifest, and taskset.required_bundle now opens bundles through it. The scorer's single port count
requires as many observed ports as actuators; LabBundle refuses other declarations.

scripts/physim/labworlds/fedvortex_*: c53's fed vortices (noise intensity 0.003, ell 2; om additive,
Y proportional) with ports (om,+), (om,-), (Y,+), (Y,-) and observe-only eat and speed channels; a
prepared state from init(31) at t=580 with device 0 on a pinching rod's neck and device 1 on a
drifting vortex; 15 programs (8 generic, 7 mechanism-targeted); calibration-frozen score groups;
2 truths per case; a 64-member native reference and privileged controls (ignore actions, wrong
geometry, initial persistence, flow off, regrowth off, growth off, decay off, body-uniform gain,
dt-halved null); report and validation through required_bundle, LaboratoryTools and evaluation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj

(World-specific suite scripts from the same work are kept separately with the evaluation material.)
…r-group reliance in the report

Records the LabBundle format and hook, the fed vortices' behaviour under the chosen noise (splitting
continues to t~2920, same-sign daughters), ports and envelope, the rod-neck division programs, the
15-program suite's control ratios, the absence of a clean division-specific control, the groups the
evaluation should not rely on, the reference reward under rewards.py (0.726 at K=2) and the
credit-free validation. fedvortex_report.py now lists, per score group, the programs on which a naive
control stays inside that group's native band and the cases where the null leaves it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj

(World-specific suite scripts from the same work are kept separately with the evaluation material.)
…; off by default)

Run scripts for a capability-showcase evaluation suite of c40's CIPS cells with the isotropic drift stencil
(holder of C:metabolic-cell, SIBED; shown here for IBED): 11 programs with device placement (device0 in open bath
beside a round cell, device1 on a dumbbell's neck) and a private adjustment map diag(16, 16, 1), step-3 verification,
a frozen suite with the claim's and audits' deciding controls (chi0 for I, chis0 for B, kF0 for E, d0 for D),
per-capability specificity, and the showcase renderer and fact sheets. Outputs live in
/home/user/evalwork/gc_suites/cips.

labworld.py: LabWorld.noise_bounds = {field: (lo, hi)} projects a field onto its range right after its noise
(bounded noise form). It acts only where noise would leave the range and only when the field's sd > 0; an empty
dict (the default) is bit-identical and is omitted from declaration(), so frozen suites keep their declarations
(checked against pm_cips_eval's suite_cips). The CIPS suite bounds e and p to [0, 1]: proportional noise carried e
to 1.002 under a product pulse at a neck (zero-noise maximum 0.9991).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj

(World-specific suite scripts from the same work are kept separately with the evaluation material.)
Agent, finalize and scoring timeouts and the agent sandbox resources become task
config fields. The scoring timeout defaults to the old 7200 s but grows with the
suite: grading runs the predictor once per case, so it needs at least
cases x (predictor wall limit + 60 s) + 900 s. Predictor limits were already
configurable (tools.predictor_limits); lab-world rollouts set them per world.
Defaults for existing Blobkit configs are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZceC7G6m7DgM6KpXjnWXj

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants