scriptmem: attach the in-memory runtime to the unified pipeline#19
Merged
Conversation
Step 2 of the unification: a memory-backend block now EXECUTES. Until
now a 'memory' block resolved (vocabulary + availability) but dead-ended
at Finalize, which only produces a temporal Sibyl Plan. This adds the
memory interpreter branch — the existing in-process runtime, unchanged,
reached through the same Parse → Resolve front as the temporal path.
The two backends now share one front end and diverge only at the final
interpreter:
temporal → Lower → Finalize → sibyl.Plan → submit (durable)
memory → adapt resolved.AST → *Program → runtime.Execute (in-process)
Critically, this is purely ADDITIVE and the runtime is untouched:
- internal/agentscript (Execute, all 44 verbs, plugins) is not modified.
- The bridge ADAPTS the unified pipeline's resolved.AST into the old
*Program the runtime already consumes, then calls the existing
Execute. The proven interpreter runs exactly as it always has.
New package: pkg/scriptmem (deliberately SEPARATE from pkg/script).
- RunMemory(ctx, MemoryConfig, resolved.AST) (string, error) — the
synchronous sibling of the temporal submit path: runs the resolved
memory program in-process and returns the result directly. Rejects a
non-memory program so a temporal block is never run in-process.
- toProgram / nodeToStatement / pipelineToStatement /
parallelToStatement / callToCommand — the adapter shim:
Pipeline → *Statement chain linked by .Pipe (a >=> b >=> c)
Parallel → *Statement{Parallel: branches} (a <*> b)
Call → *Command{Action, Arg..Arg4} (≤4 positional args)
WHY A SEPARATE PACKAGE (important): the in-memory runtime drags a heavy
dependency tree (Google Workspace, GitHub, Gemini, oauth2 SDKs). If the
bridge lived in pkg/script, every consumer of the compile pipeline —
loom included — would transitively pull all of it just to translate or
compile, even when they never run memory. Verified: with the bridge in
pkg/script, loom failed to build (missing go.sum for oauth2 / google
api). Moving it to pkg/scriptmem keeps pkg/script lean; loom builds
clean against this branch with no new deps. You only pay for the
runtime's deps if you actually execute memory.
Tests (pkg/scriptmem/memory_adapter_test.go): run the real front end
(script.Parse → script.Resolve over CompleteRegistry) then assert the
adapter output —
- single call maps name + first arg correctly;
- a >=> b >=> c folds into the correct .Pipe-linked *Statement chain;
- RunMemory rejects a temporal-backend program.
(Structural translation is tested without a live runtime, which would
need API keys; execution itself reuses the long-standing, separately
exercised Execute.)
loom unaffected and lean: pkg/script carries no runtime import; built +
tested loom against this commit, clean.
Next: loom's small sync branch — when it submits a memory-flagged query,
post the RunMemory result immediately (vs the temporal correlate-and-
await path it already has).
CI: vet, gofmt, staticcheck, go test -race ./..., go build ./... pass.
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.
What
Step 2 of the unification: a memory-backend block now EXECUTES. Until now a
memoryblock resolved (vocabulary + availability) but dead-ended atFinalize, which only produces a temporal Sibyl Plan. This adds the memory interpreter branch — the existing in-process runtime, unchanged, reached through the sameParse → Resolvefront as the temporal path.The two backends now share one front end and diverge only at the final interpreter:
Purely additive — the runtime is untouched
internal/agentscript(Execute, all 44 verbs, plugins) is not modified.resolved.ASTinto the old*Programthe runtime already consumes, then calls the existingExecute. The proven interpreter runs exactly as it always has.New package:
pkg/scriptmem(deliberately separate frompkg/script)RunMemory(ctx, MemoryConfig, resolved.AST) (string, error)— the synchronous sibling of the temporal submit path: runs the resolved memory program in-process and returns the result directly. Rejects a non-memory program so a temporal block is never run in-process.Pipeline → *Statementchain via.Pipe;Parallel → *Statement{Parallel};Call → *Command{Action, Arg..Arg4}.Why a separate package (important architecture call)
The in-memory runtime drags a heavy dependency tree (Google Workspace, GitHub, Gemini, oauth2 SDKs). If the bridge lived in
pkg/script, every consumer of the compile pipeline — loom included — would transitively pull all of it just to translate or compile, even when they never run memory.Verified: with the bridge in
pkg/script, loom failed to build (missinggo.sumforoauth2/ google api). Moving it topkg/scriptmemkeepspkg/scriptlean; loom builds clean against this branch with no new deps. You only pay for the runtime's deps if you actually execute memory.Tests (
pkg/scriptmem/memory_adapter_test.go)Run the real front end (
script.Parse → script.ResolveoverCompleteRegistry) then assert the adapter output:a >=> b >=> cfolds into the correct.Pipe-linked*StatementchainRunMemoryrejects a temporal-backend program(Structural translation is tested without a live runtime, which needs API keys; execution itself reuses the long-standing, separately-exercised
Execute.)go vet -structtag=false/gofmt/staticcheckgo test -race ./...go build ./...Now true
memory static ( hf_summarize ... )→ translate → parse → resolve → run in-process → result. All 112 verbs are reachable on the memory backend through the unified pipeline.Next
loom's small sync branch: when it submits a memory-flagged query, post the
RunMemoryresult immediately (vs the temporal correlate-and-await path it already has). Pairs with the discovery PR (#18).