script: add Translate (prose → DSL) — agentscript owns the grammar prompt#15
Merged
Conversation
…rompt
Moves prose->DSL ownership into pkg/script, where the grammar (Parse)
and the builtin registry (Resolve) live. A prose-driven front end like
loom should not carry its own copy of the grammar rules and builtin
list — it drifts the moment the grammar changes. Now the front end hands
over prose and gets back a validated Plan, knowing nothing about >=>,
<*>, or which commands exist.
New (pkg/script/translate.go):
- CompleteFunc — the LLM seam (matches sibyl's agent.CompleteFunc, so
a sibyl client plugs in, but this package depends on nothing in
sibyl for translation and picks no provider / reads no API key).
- Translate(ctx, complete, reg, prose) -> Source — calls the LLM with
the grammar prompt, strips fences/stray prose, returns DSL. Does not
compile; pass to Compile for that.
- BuildPrompt(reg) -> string — exported so callers can inspect/log the
exact instruction and tests can assert it. Lists reg.Names() (the
LLM may use only commands that exist) and states the conservative
composition discipline: sequential >=> by default, parallel <*> only
for an unambiguous flat list. The grammar is permissive; the
translation is conservative — inferring parallelism the user didn't
express is the risky case.
- cleanDSL — conservative fence/prose stripping; does NOT 'fix' the
DSL, so malformed output fails loudly at Compile.
New (pkg/script/submit.go):
- TranslateAndCompile(ctx, complete, reg, prose) -> sibyl.Plan — the
full front-half a prose caller wants: Translate + Compile in one
call. Both translation failure (LLM error) and compile failure
(unknown builtin, bad arity, malformed graph) surface here, before
anything executes.
This supersedes loom's own translator.go (which carried a duplicate
grammar prompt in the wrong repo) — loom will switch to calling
script.Translate next. It also stands distinct from the LEGACY
internal/agentscript/translator.go, which targets the old grammar
(-> pipes, parallel {}) and the old in-process Runtime via Gemini; that
path is left untouched here (its own consumer, cmd/agentscript, still
needs it). Whether to retire the legacy runtime entirely is a separate
decision / PR.
Tests (translate_test.go, 11): BuildPrompt lists builtins + uses >=>
(not the legacy ->), nil-registry safety, fence stripping, surrounding-
prose stripping, nil-LLM and LLM-error handling, TranslateAndCompile
happy path (prose -> 2-node validated plan), and the SAFETY NET —
teleport "mars" (unknown command) and 'this is not agentscript'
(malformed) both fail at compile so nothing executes.
Memo updated: Translate added to the phase table; pipeline note now
covers TranslateAndCompile and the prose->DSL ownership.
No new dependencies (Translate uses only registry + stdlib; the LLM is
injected). All CI steps pass: go vet -structtag=false, gofmt,
staticcheck, go test -race ./pkg/script/..., go build ./....
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
Moves prose→DSL ownership into
pkg/script, where the grammar (Parse) and the builtin registry (Resolve) live. A prose-driven front end like loom should not carry its own copy of the grammar rules and builtin list — it drifts the moment the grammar changes. Now the front end hands over prose and gets back a validated Plan, knowing nothing about>=>,<*>, or which commands exist.Why this is the right boundary
loom currently has a
translator.gowith a hardcoded grammar prompt + builtin list. But agentscript owns the grammar and the registry. When either changes, that prompt must change — and it lives in the wrong repo. This PR puts the prompt next to the grammar it describes, readingregistry.Names()so the available commands are always the real, current set.New:
pkg/script/translate.goCompleteFunc— the LLM seam (matches Sibyl'sagent.CompleteFunc, so a Sibyl client plugs in, but this package depends on nothing in Sibyl for translation and picks no provider / reads no API key)Translate(ctx, complete, reg, prose) → Source— calls the LLM with the grammar prompt, strips fences/stray prose, returns DSL. Doesn't compile; pass toCompileBuildPrompt(reg) → string— exported so callers can inspect/log it and tests can assert it. Listsreg.Names()and states the conservative composition discipline: sequential>=>by default, parallel<*>only for an unambiguous flat list. Inferring parallelism the user didn't express is the risky casecleanDSL— conservative fence/prose stripping; does not 'fix' the DSL, so malformed output fails loudly atCompileNew:
pkg/script/submit.goTranslateAndCompile(ctx, complete, reg, prose) → sibyl.Plan— the full front-half a prose caller wants: Translate + Compile in one. Both translation failure (LLM error) and compile failure (unknown builtin, bad arity, malformed graph) surface here, before anything executes. This is exactly what loom will call.Relationship to existing translators
translator.go— a duplicate grammar prompt in the wrong repo. loom switches toscript.Translatenext (loom PR-4).internal/agentscript/translator.go— that targets the old grammar (->pipes,parallel {}) and the old in-process Runtime via Gemini. Left untouched here; its consumer (cmd/agentscript) still needs it. Whether to retire the legacy runtime entirely is a separate decision/PR (flagged below).Tests (
translate_test.go, 11)BuildPrompt lists builtins + uses
>=>(not legacy->), nil-registry safety, fence stripping, surrounding-prose stripping, nil-LLM + LLM-error handling,TranslateAndCompilehappy path (prose → 2-node validated plan), and the SAFETY NET —teleport "mars"(unknown) andthis is not agentscript(malformed) both fail at compile so nothing executes.go mod tidy(+ diff)go vet -structtag=false ./...gofmt -l .staticcheck ./pkg/script/...go test -race ./pkg/script/...go build ./...Next
translator.go, callscript.TranslateAndCompile. loom loses all grammar knowledge; becomes pure Slack-ingress + correlation + posting.cmd/geminilive+ gemini client, if the Sibyl-backed path is now the only one wanted. Left for an explicit decision.