Build a New Substrate Package
Use this guide when you need to add a new substrate package to a repo.
Outcome
Section titled “Outcome”You will produce a package that:
- Exposes launch(domain) at package boundary.
- Uses RAS and one or more synthesizers to produce
ModulatorResultobjects, includingModulatorSuccesschild results withartifact-refvalues. - Uses
Neuromodulatorsto resolve those references into concrete modulators, with the resulting transmissions arriving through the substrate terminal before cocktail injection. - Returns a runtime compatible with substrate-core contracts.
Checklist
Section titled “Checklist”1) Define launch-target metadata in the domain model
Section titled “1) Define launch-target metadata in the domain model”In your cortex or substrate config entry, define:
- launch.launcher
- launch.target.module-path
- launch.target.symbol-name
Use values that resolve to the actual package entrypoint.
2) Keep launcher and adapter thin
Section titled “2) Keep launcher and adapter thin”Launcher responsibilities:
- Resolve dispatch strategy.
- Enforce launch result contract.
Adapter responsibilities:
- Import module from module-path.
- Resolve symbol-name.
- Invoke launch(domain).
Do not put substrate composition logic into either component.
3) Define lamina structure and synthesizer responsibilities
Section titled “3) Define lamina structure and synthesizer responsibilities”For a CliSensoryCortex-style package, keep the inheritance structure explicit:
- BaseLamina
- AgenticLamina
- CortexLamina
- SensoryMotorCortexLamina
- SensoryCortexLamina
Then define which synthesizers can satisfy the modulators those laminae require.
4) Preserve identity propagation
Section titled “4) Preserve identity propagation”Create runtime identity once and propagate unchanged through the cocktail and runtime.
Never regenerate instance identity in a synthesizer or downstream runtime layer.
5) Keep package launch wrapper minimal
Section titled “5) Keep package launch wrapper minimal”The launch function should:
- Wire
RAS,Neuromodulators, and register the required synthesizers. - Request the modulators needed by the concrete substrate.
- Resolve returned
artifact-refvalues fromNeuromodulators, receive the results through a terminal registered toNeuralRelay, and inject them into the cocktail. - Return final runtime.
Avoid embedding policy branching or side effects in launch wrapper.
6) Validate contracts with tests
Section titled “6) Validate contracts with tests”Add tests for:
- launch(domain) returns Substrate-compatible runtime.
- Invalid launch target metadata fails with clear errors.
- Missing modulator requests fail with clear errors.
- Identity is stable across all modulators.
7) Expose clear package exports
Section titled “7) Expose clear package exports”Package init should export launch and, if useful, leaf runtime type.
Keep internal synthesizers and substrate wiring non-public unless a separate extension seam is intentionally supported.
Minimal launch function template
Section titled “Minimal launch function template”from cerebel_substrate_core import Substrate, SubstrateDomain
def launch(domain: SubstrateDomain) -> Substrate: # Wire RAS and local synthesizers. # Request needed modulators and return the runtime. ...Common failure patterns
Section titled “Common failure patterns”- Launcher dispatch and substrate-specific modulation mixed in one class.
- RAS hard-coding which synthesizer owns which modulator.
- Identity rebuilt at multiple layers.
- launch(domain) performing unrelated orchestration policy.
- Skipping
artifact-refresolution and attempting to treat relay payload as a concrete modulator instance.
Done criteria
Section titled “Done criteria”You are done when:
- Package launches through generic launcher using launch target metadata.
- All substrate and package tests pass.
- Runtime handle includes definition_id, instance_id, healthy, and lifecycle_state.