Skip to content

scriptmem: attach the in-memory runtime to the unified pipeline#19

Merged
vinodhalaharvi merged 1 commit into
mainfrom
claude/memory-execution-bridge
May 24, 2026
Merged

scriptmem: attach the in-memory runtime to the unified pipeline#19
vinodhalaharvi merged 1 commit into
mainfrom
claude/memory-execution-bridge

Conversation

@vinodhalaharvi-claude
Copy link
Copy Markdown
Collaborator

What

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)

Purely additive — 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.
  • Adapter shim: Pipeline → *Statement chain 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 (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 needs API keys; execution itself reuses the long-standing, separately-exercised Execute.)

Step Result
go vet -structtag=false / gofmt / staticcheck
go test -race ./...
go build ./...
loom builds + tests against this commit (lean)

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 RunMemory result immediately (vs the temporal correlate-and-await path it already has). Pairs with the discovery PR (#18).

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.
@vinodhalaharvi vinodhalaharvi merged commit 408f2ea into main May 24, 2026
1 check passed
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