Skip to content

script: complete builtin catalog + per-backend availability#17

Merged
vinodhalaharvi merged 1 commit into
mainfrom
claude/complete-registry
May 24, 2026
Merged

script: complete builtin catalog + per-backend availability#17
vinodhalaharvi merged 1 commit into
mainfrom
claude/complete-registry

Conversation

@vinodhalaharvi-claude
Copy link
Copy Markdown
Collaborator

What

Makes the registry complete and backwards-compatible: every verb the AgentScript grammar has ever supported is now recognized, and availability is decided per-backend rather than per-existence. This separates two situations that used to collapse into one error:

Situation Error
unknown verb (typo, hallucination) UnknownBuiltinError
known verb, not on this backend yet NotImplementedOnBackendError (new)

Why

Before: the temporal registry held only echo, so hf_summarize under temporal failed as UnknownBuiltinError — indistinguishable from a real typo, and a lie (it is a real verb, just memory-only). After: it resolves as known vocabulary and reports "not implemented on the temporal backend yet." The in-memory interpreter still implements the full set, so the vocabulary the registry advertises matches reality. This is the backwards-compatibility you asked for: every real verb resolves; the backend decides where it can run.

Changes

  • registry.BuiltinSpec.Backends []Backend + SupportsBackend(b). New registry.Backend enum (BackendMemory, BackendTemporal) — the registry is the single source of truth for "what runs where," with no dependency on ast. Empty Backends ⇒ memory-only (the safe default: a verb with no declared Sibyl activity is never dispatched to Temporal).
  • pkg/script/catalog.go: CompleteRegistry() — all 111 historical verbs (sourced from the grammar's authoritative Action enum) as permissive memory-backed specs, plus echo (memory + temporal). Arg schemas are intentionally variadic-string: the registry's job for memory verbs is vocabulary recognition; the in-process interpreter does its own arg handling. DefaultRegistry (echo only) stays for the minimal temporal-only case.
  • Resolve threads the block's backend to each Call and checks availability after the vocabulary lookup: unknown → UnknownBuiltinError (safety net intact); known-but-unsupported-backend → NotImplementedOnBackendError.
  • EchoSpec now declares both backends.

Tested contract (catalog_test.go)

  • CompleteRegistry recognizes a representative spread of all verb families (hf_*, mcp_*, perplexity*, weather/stock/crypto, control flow, exec, …)
  • memory-only verb resolves under memory; under temporal it fails with NotImplementedOnBackendError and explicitly not UnknownBuiltinError
  • echo compiles end-to-end on temporal and resolves on memory
  • safety net preserved: teleport is still UnknownBuiltinError on both backends
  • empty Backends ⇒ memory-only (no accidental temporal dispatch)

(Note: memory execution — Finalize for the memory backend — is the next step. This PR establishes the registry + resolution contract, so memory-backend assertions stop at Resolve.)

loom untouched

Changes are purely additive (new field, new error type). Verified by building + testing loom against this commit with loom's code unchanged — builds clean, all tests pass. Whether loom adopts CompleteRegistry is a separate loom decision.

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

Next

Step 2 — the memory interpreter branch: wire Finalize/dispatch so a memory block actually executes through the in-process runtime via the composed pipeline. Then every one of these now-resolvable verbs runs on memory, end-to-end.

Makes the registry COMPLETE and backwards-compatible: every verb the
AgentScript grammar has ever supported is now recognized, and
availability is decided per-backend rather than per-existence. This
separates two situations that used to collapse into one error:

  - 'unknown verb' (typo, hallucination)            → UnknownBuiltinError
  - 'known verb, not on this backend yet'           → NotImplementedOnBackendError  (NEW)

Before: the temporal registry held only echo, so 'hf_summarize' under
temporal failed as UnknownBuiltinError — indistinguishable from a real
typo, and a lie (it IS a real verb, just memory-only). After: it
resolves as known vocabulary and reports 'not implemented on the
temporal backend yet'. The in-memory interpreter still implements the
full set, so the vocabulary the registry advertises matches reality.

Changes:
  - registry.BuiltinSpec gains a Backends []Backend field +
    SupportsBackend(b). registry.Backend enum (BackendMemory,
    BackendTemporal) — the registry is the single source of truth for
    'what runs where', with no dependency on the ast package. Empty
    Backends defaults to memory-only: the SAFE default, so a verb with
    no declared Sibyl activity is never dispatched to Temporal.
  - pkg/script/catalog.go: CompleteRegistry() — all 111 historical verbs
    (sourced from the grammar's authoritative Action enum) as permissive
    memory-backed specs, plus echo (memory + temporal). Arg schemas are
    intentionally variadic-string: the registry's job for memory verbs
    is vocabulary recognition; the in-process interpreter does its own
    arg handling. DefaultRegistry (echo only) stays for the minimal
    temporal-only case.
  - Resolve threads the block's backend down to each Call and performs
    an availability check AFTER the vocabulary lookup: unknown name →
    UnknownBuiltinError (safety net intact); known but unsupported
    backend → NotImplementedOnBackendError.
  - EchoSpec now declares both backends.

Tested contract (catalog_test.go):
  - CompleteRegistry recognizes a representative spread of all verb
    families (hf_*, mcp_*, perplexity*, weather/stock/crypto, control
    flow, exec, ...).
  - memory-only verb RESOLVES under memory; under temporal it fails with
    NotImplementedOnBackendError and explicitly NOT UnknownBuiltinError.
  - echo compiles end-to-end on temporal and resolves on memory.
  - SAFETY NET preserved: 'teleport' is still UnknownBuiltinError on
    BOTH backends.
  - empty Backends ⇒ memory-only (no accidental temporal dispatch).

Note on Compile vs Resolve in tests: memory *execution* (Finalize for
the memory backend) is the NEXT step; this PR establishes the registry +
resolution contract, so memory-backend assertions stop at Resolve.

loom is UNTOUCHED: changes are purely additive (new field, new error
type). Verified by building + testing loom against this commit with
loom's code unchanged — builds clean, all tests pass. (Whether loom
adopts CompleteRegistry is a separate loom decision.)

CI: go vet -structtag=false, gofmt, staticcheck, go test -race ./...,
go build ./... — all pass.
@vinodhalaharvi vinodhalaharvi merged commit da0a96a 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