script: add Grammar() discovery — front ends query the grammar, never embed it#18
Merged
Merged
Conversation
… embed it
A front end should not name a registry, hardcode a verb list, or change
when the grammar grows. Grammar() is the single discovery entry point: a
caller asks 'what can be done?', pipes the result into translation, and
forwards the output — never inspecting the contents. When AgentScript
adds verbs or restructures, the front end reflects it automatically,
because it FETCHES the grammar instead of embedding knowledge of it.
AgentScript is the source of truth; the front end is a dumb pipe.
New (pkg/script/grammar.go):
- GrammarInfo { Registry, Verbs, Operators, Backends } — self-describing
discovery result. Registry is passed straight to Translate/Compile
(callers are not expected to inspect it); Verbs/Operators/Backends
are advisory metadata for help/docs/CLI surfaces.
- Grammar() GrammarInfo — THE discovery entry, backed by
CompleteRegistry (full vocabulary, per-backend availability decided
at Resolve). Lists all 112 verbs, the >=> and <*> operators, and the
memory/temporal backends.
New (pkg/script/submit.go):
- TranslateGrammar(ctx, complete, GrammarInfo, prose) — discovery-driven
translate: takes GrammarInfo instead of a registry, so a front end
pipes Grammar() straight in without ever touching or naming a
registry.
- CompileGrammar(ctx, GrammarInfo, src) — the matching compile entry.
Tests (grammar_test.go): Grammar exposes the full sorted vocabulary +
representative families; describes >=> / <*> and both backends; the
discovery-driven Translate+Compile path works end to end without naming
a registry; and a historical verb emitted under temporal surfaces
NotImplementedOnBackendError (known, not unknown) — proving discovery
composes with the per-backend availability contract.
loom can now call Grammar() and pipe it through, staying fully decoupled
from the grammar's contents and evolution. (loom change is a separate
PR.) Purely additive; existing API unchanged.
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
Grammar()is a single discovery entry point: a front end asks "what can be done?", pipes the result into translation, and forwards the output — never inspecting the contents, never naming a registry, never hardcoding a verb list. When AgentScript adds verbs or restructures, the front end reflects it automatically, because it fetches the grammar instead of embedding knowledge of it.AgentScript is the source of truth; the front end is a dumb pipe.
Why
Even after the complete-registry work, a front end calling
CompleteRegistry()is still naming a specific registry — it knows too much, and breaks if that name/structure changes. Discovery closes that leak: loom callsGrammar()and pipes it through. agentscript can evolve the grammar freely; loom never changes.New:
pkg/script/grammar.goGrammarInfo { Registry, Verbs, Operators, Backends }— self-describing discovery result.Registrygoes straight to Translate/Compile (callers don't inspect it);Verbs/Operators/Backendsare advisory metadata for help/docs/CLI surfaces.Grammar() GrammarInfo— THE discovery entry, backed byCompleteRegistry. Exposes all 112 verbs, the>=>/<*>operators, and the memory/temporal backends.New:
pkg/script/submit.goTranslateGrammar(ctx, complete, GrammarInfo, prose)— discovery-driven translate: takesGrammarInfo, not a registry, so a front end pipesGrammar()straight in without ever touching or naming a registry.CompileGrammar(ctx, GrammarInfo, src)— matching compile entry.The decoupling, concretely
loom's flow becomes:
loom names no registry, reads no verb list, and auto-reflects any future grammar change.
Tests (
grammar_test.go)Grammarexposes the full sorted vocabulary + representative families (echo, hf_summarize, mcp_agent, perplexity)>=>/<*>and both backendsNotImplementedOnBackendError(known, not unknown) — proving discovery composes with the per-backend availability contractgo vet -structtag=false ./...gofmt/staticcheckgo test -race ./...go build ./...Purely additive; existing API unchanged.
Next
loom PR — call
Grammar()+TranslateGrammar/CompileGrammarinstead of namingDefaultRegistry. loom stops knowing the grammar entirely; gains the full 112-verb vocabulary automatically. (Execution of non-echo verbs on temporal still reports 'not implemented yet' until step 2 wires memory execution / verbs get temporal activities — honest, forward-compatible.)