Skip to content

script: add Translate (prose → DSL) — agentscript owns the grammar prompt#15

Merged
vinodhalaharvi merged 1 commit into
mainfrom
claude/script-translate
May 22, 2026
Merged

script: add Translate (prose → DSL) — agentscript owns the grammar prompt#15
vinodhalaharvi merged 1 commit into
mainfrom
claude/script-translate

Conversation

@vinodhalaharvi-claude
Copy link
Copy Markdown
Collaborator

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.go with 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, reading registry.Names() so the available commands are always the real, current set.

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. Doesn't compile; pass to Compile
  • BuildPrompt(reg) → string — exported so callers can inspect/log it and tests can assert it. Lists reg.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 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. 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

  • Supersedes loom's translator.go — a duplicate grammar prompt in the wrong repo. loom switches to script.Translate next (loom PR-4).
  • Distinct from the LEGACY 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, TranslateAndCompile happy path (prose → 2-node validated plan), and the SAFETY NETteleport "mars" (unknown) and this is not agentscript (malformed) both fail at compile so nothing executes.

Step Result
go mod tidy (+ diff) ✅ no change (no new deps — LLM injected)
go vet -structtag=false ./...
gofmt -l .
staticcheck ./pkg/script/...
go test -race ./pkg/script/...
go build ./...

Next

  • loom PR-4 — delete loom's translator.go, call script.TranslateAndCompile. loom loses all grammar knowledge; becomes pure Slack-ingress + correlation + posting.
  • Open question (separate PR): retire the legacy in-process Runtime + its translator + cmd/geminilive + gemini client, if the Sibyl-backed path is now the only one wanted. Left for an explicit decision.

…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 ./....
@vinodhalaharvi vinodhalaharvi merged commit 231df9a into main May 22, 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