Skip to content

script: add Grammar() discovery — front ends query the grammar, never embed it#18

Merged
vinodhalaharvi merged 1 commit into
mainfrom
claude/grammar-discovery
May 24, 2026
Merged

script: add Grammar() discovery — front ends query the grammar, never embed it#18
vinodhalaharvi merged 1 commit into
mainfrom
claude/grammar-discovery

Conversation

@vinodhalaharvi-claude
Copy link
Copy Markdown
Collaborator

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 calls Grammar() and pipes it through. agentscript can evolve the grammar freely; loom never changes.

New: pkg/script/grammar.go

  • GrammarInfo { Registry, Verbs, Operators, Backends } — self-describing discovery result. Registry goes straight to Translate/Compile (callers don't inspect it); Verbs/Operators/Backends are advisory metadata for help/docs/CLI surfaces.
  • Grammar() GrammarInfo — THE discovery entry, backed by CompleteRegistry. Exposes all 112 verbs, the >=> / <*> operators, and the memory/temporal backends.

New: pkg/script/submit.go

  • TranslateGrammar(ctx, complete, GrammarInfo, prose) — discovery-driven translate: takes GrammarInfo, not a registry, so a front end pipes Grammar() straight in without ever touching or naming a registry.
  • CompileGrammar(ctx, GrammarInfo, src) — matching compile entry.

The decoupling, concretely

loom's flow becomes:

g := script.Grammar()                          // ask: what can be done?
src, _ := script.TranslateGrammar(ctx, llm, g, prose)  // pipe through — never inspect g
plan, _ := script.CompileGrammar(ctx, g, src)

loom names no registry, reads no verb list, and auto-reflects any future grammar change.

Tests (grammar_test.go)

  • Grammar exposes the full sorted vocabulary + representative families (echo, hf_summarize, mcp_agent, perplexity)
  • describes >=> / <*> and both backends
  • the discovery-driven Translate+Compile path works end-to-end without naming a registry
  • a historical verb emitted under temporal surfaces NotImplementedOnBackendError (known, not unknown) — proving discovery composes with the per-backend availability contract
Step Result
go vet -structtag=false ./...
gofmt / staticcheck
go test -race ./...
go build ./...

Purely additive; existing API unchanged.

Next

loom PR — call Grammar() + TranslateGrammar/CompileGrammar instead of naming DefaultRegistry. 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.)

… 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.
@vinodhalaharvi vinodhalaharvi merged commit ffb2222 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