Repository navigation
feat(runtime-scripts): a Package writes its Runtime Scripts in TypeScript - #402
Merged
Merged
Conversation
This was referenced Sep 3, 2026
Merged
A Runtime Script had no authoring path. The Module ran Lua a Script Artifact carried, but nothing produced one, and the hand-written example artifact was the only way a script reached a Shard. A Package now keeps its sources in `packages/<name>/scripts/`, as `.ts` or as `.lua`. `datascripts/runtime-scripts/` holds the Runtime Script Toolchain: the pinned `typescript-to-lua`, the hand-maintained Host API typings, and the builder that writes one Script Artifact per Package. The sources sit inside the Package because they are its own content; a Datascript stays outside because only artifacts belong in a Package folder. Each file opens with its Script Directives. `@event` and `@id` are required, `@priority` and `@enabled` have defaults. The identifier is written down rather than derived: it is durable, and a file index would renumber a Package's scripts the moment an author added one. The build refuses an unknown event, an identifier outside the Package Script Range, and two scripts claiming one identity. piccolo 0.3.3 leaks an inline table constructor's element count as an extra argument when the constructor is a call's last argument, and transpiler output meets that shape constantly. The emitter passes a trailing constructor through a one-parameter local. The Module pins the fault, the fix, and the fact that parentheses do not help. `lyracore-delta-check` now routes each file on its own `kind` and traces both artifact kinds in one run, so a Runtime Script collision between two Packages fails the same way a Claim Conflict does. The Host's Fuel Budget is sized against real transpiler output: `datascripts/runtime-scripts/fuel-workload.lua` is committed, the Module runs those exact bytes, and a Bun test refuses a stale copy. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Mathih13
force-pushed
the
feat/320-runtime-script-typescript-build
branch
from
September 3, 2026 15:19
f2630e5 to
0653e2f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A Runtime Script is Lua the Module runs on a gameplay event. The Module could already run one and a Script Artifact could already carry one, but nothing produced an artifact. The only example was hand-written JSON, so in practice a Package could not ship a script.
A Package now keeps its sources in its own folder,
packages/<name>/scripts/, as.tsor as.lua. The sources sit inside the Package because they are its own content; a Datascript stays outside because only artifacts belong in a Package folder.Packages may instead ship a source-free prebuilt Script Artifact when they ship authored Lua directly. It has no local author inputs or Build Identity.
packages checkstill uses the authoritative parser and tracer, so this path needs neither Bun nor a Module wasm build.datascripts/runtime-scripts/holds the Runtime Script Toolchain: the pinnedtypescript-to-lua, a hand-maintained.d.tsfor the Host API, the emitter, and the builder that writes one Script Artifact per Package. It is a Bun workspace of the existing Datascript project, so onebun installcovers both and there is no second toolchain.Declaring a script
Every file opens with its Script Directives,
//in TypeScript and--in Lua:@eventand@idare required,@prioritydefaults to 0 and@enabledto true. The identifier is written down rather than derived. It is durable —game_scriptkeys on it — and a sorted file index would renumber every later script the moment an author added one alphabetically earlier. The name is derived, because<package>.<file stem>is the one part with an obvious answer.A TypeScript script declares
function script(): number | void. The emitted Lua ends withreturn script(), because TypeScript has no top-level return and a Script Answer is the chunk's return value. Each file compiles as its own program, so two scripts in one Package may both declarescript.The piccolo call shape
piccolo 0.3.3 passes an inline table constructor's element count as an extra argument when the constructor is a call's last argument, so
f({7, 8, 9})arrives asf(table, 3). Transpiler output meets that shape constantly. The emitter passes a trailing constructor through a one-parameter local, and the Module now pins the fault, the fix, and the fact that parentheses do not help.What checks what
lyracore-delta-checkroutes each file on its ownkindand traces both artifact kinds in one run, so a Runtime Script collision between two Packages fails the way a Claim Conflict does.packages buildsupplies the event catalogue from--print-events, so an unknown@eventis refused while the diagnostic can still name the file.The Fuel Budget is now sized against real transpiler output.
datascripts/runtime-scripts/fuel-workload.luais committed, the Module runs those exact bytes, and a Bun test recompiles the source and refuses a stale copy.packages/fire_nova/scripts/ember_echo.tsis the worked example. It ships switched off:on_cast_resolvedfires for every cast on a realm.The CLI half is LyraCoreProject/lyracore-cli#55.
Implemented by Claude (model claude-opus-5) via Claude Code subagent.